diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812160506.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812160506.js new file mode 100644 index 000000000..f1efe1217 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812160506.js @@ -0,0 +1,763 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161713.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161713.js new file mode 100644 index 000000000..b2ae30acc --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161713.js @@ -0,0 +1,763 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161721.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161721.js new file mode 100644 index 000000000..0dab9802c --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161721.js @@ -0,0 +1,765 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161722.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161722.js new file mode 100644 index 000000000..3fc61d059 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161722.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161726.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161726.js new file mode 100644 index 000000000..3fc61d059 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161726.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161730.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161730.js new file mode 100644 index 000000000..bbb3a0653 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161730.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161732.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161732.js new file mode 100644 index 000000000..8a9afe8ea --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161732.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161735.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161735.js new file mode 100644 index 000000000..6f24f3aa5 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161735.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //数据 + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161736.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161736.js new file mode 100644 index 000000000..f363c02c4 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161736.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //数据量 + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161739.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161739.js new file mode 100644 index 000000000..41c31f55a --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161739.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //数据量过大时, + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161741.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161741.js new file mode 100644 index 000000000..06ea19b01 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161741.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //数据量过大时, + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161746.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161746.js new file mode 100644 index 000000000..b428d3dd0 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161746.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //数据量过大时,渲染出的 + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161750.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161750.js new file mode 100644 index 000000000..ae9a2a284 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161750.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //数据量过大时,渲染出的元素 + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161753.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161753.js new file mode 100644 index 000000000..3a670a42d --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161753.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //数据量过大时,渲染出的元素width + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161754.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161754.js new file mode 100644 index 000000000..3cb02e299 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161754.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //数据量过大时,渲染出的元素width会 + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161758.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161758.js new file mode 100644 index 000000000..86a0bf494 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161758.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //数据量过大时,渲染出的元素width会为0, + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161801.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161801.js new file mode 100644 index 000000000..94faac03b --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161801.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //数据量过大时,渲染出的元素width会为0, + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161803.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161803.js new file mode 100644 index 000000000..6d29dcbcd --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161803.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //数据量过大时,渲染出的元素width会为0,导致无法 + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161805.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161805.js new file mode 100644 index 000000000..5dc29a0eb --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161805.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //数据量过大时,渲染出的元素width会为0,导致无法显示, + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161806.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161806.js new file mode 100644 index 000000000..f9771454d --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161806.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161807.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161807.js new file mode 100644 index 000000000..65fb74af0 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161807.js @@ -0,0 +1,767 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161813.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161813.js new file mode 100644 index 000000000..dbdd6fac6 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161813.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161815.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161815.js new file mode 100644 index 000000000..0cc895296 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161815.js @@ -0,0 +1,767 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161820.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161820.js new file mode 100644 index 000000000..8c4777075 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161820.js @@ -0,0 +1,767 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161822.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161822.js new file mode 100644 index 000000000..9dfd11638 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161822.js @@ -0,0 +1,767 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161929.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161929.js new file mode 100644 index 000000000..de09ca440 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161929.js @@ -0,0 +1,767 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161930.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161930.js new file mode 100644 index 000000000..5de5dadcd --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161930.js @@ -0,0 +1,767 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以 + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161933.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161933.js new file mode 100644 index 000000000..a4f64a445 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161933.js @@ -0,0 +1,767 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小 + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161936.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161936.js new file mode 100644 index 000000000..a4f64a445 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161936.js @@ -0,0 +1,767 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小 + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161945.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161945.js new file mode 100644 index 000000000..40efaa9a8 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161945.js @@ -0,0 +1,767 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算 + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161953.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161953.js new file mode 100644 index 000000000..c347d414f --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812161953.js @@ -0,0 +1,768 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算 + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162021.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162021.js new file mode 100644 index 000000000..32b744ee9 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162021.js @@ -0,0 +1,768 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算 + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162025.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162025.js new file mode 100644 index 000000000..6dddc61e0 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162025.js @@ -0,0 +1,768 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算 + let + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162032.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162032.js new file mode 100644 index 000000000..388ac3501 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162032.js @@ -0,0 +1,768 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算 + let svgWidth= + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162040.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162040.js new file mode 100644 index 000000000..5827864d3 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162040.js @@ -0,0 +1,768 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算 + let svgWidth=this.svg.node(). + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162048.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162048.js new file mode 100644 index 000000000..26fa7f2eb --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162048.js @@ -0,0 +1,768 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算 + let svgWidth=this.svg.node().client + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162052.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162052.js new file mode 100644 index 000000000..377bb3368 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162052.js @@ -0,0 +1,768 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算 + let svgWidth=this.svg.node().clientWidth; + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162053.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162053.js new file mode 100644 index 000000000..3ffe784cc --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162053.js @@ -0,0 +1,769 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算 + let svgWidth=this.svg.node().clientWidth; + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162055.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162055.js new file mode 100644 index 000000000..71d59e9bd --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162055.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算 + let svgWidth=this.svg.node().clientWidth; + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162103.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162103.js new file mode 100644 index 000000000..daf9dd068 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162103.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算, + let svgWidth=this.svg.node().clientWidth; + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162106.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162106.js new file mode 100644 index 000000000..65a454081 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162106.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据 + let svgWidth=this.svg.node().clientWidth; + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162109.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162109.js new file mode 100644 index 000000000..94c3570a7 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162109.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应 + let svgWidth=this.svg.node().clientWidth; + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162220.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162220.js new file mode 100644 index 000000000..12fdc5542 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162220.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1 + let svgWidth=this.svg.node().clientWidth; + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162224.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162224.js new file mode 100644 index 000000000..e06ab458a --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162224.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1* + let svgWidth=this.svg.node().clientWidth; + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162227.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162227.js new file mode 100644 index 000000000..e8781470c --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162227.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas. + let svgWidth=this.svg.node().clientWidth; + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162230.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162230.js new file mode 100644 index 000000000..2acb1ff48 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162230.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[] + let svgWidth=this.svg.node().clientWidth; + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162232.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162232.js new file mode 100644 index 000000000..e3c04c183 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162232.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0] + let svgWidth=this.svg.node().clientWidth; + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162234.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162234.js new file mode 100644 index 000000000..c64f8256e --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162234.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162239.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162239.js new file mode 100644 index 000000000..4c1946cb2 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162239.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162243.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162243.js new file mode 100644 index 000000000..4c1946cb2 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162243.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162244.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162244.js new file mode 100644 index 000000000..cd05cc1d1 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162244.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162250.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162250.js new file mode 100644 index 000000000..cd05cc1d1 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162250.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162302.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162302.js new file mode 100644 index 000000000..cd05cc1d1 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162302.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162305.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162305.js new file mode 100644 index 000000000..5afa9469f --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162305.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let par + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162308.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162308.js new file mode 100644 index 000000000..5afa9469f --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162308.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let par + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162310.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162310.js new file mode 100644 index 000000000..4529c55da --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162310.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parent + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162312.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162312.js new file mode 100644 index 000000000..c025ee677 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162312.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRect + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162317.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162317.js new file mode 100644 index 000000000..41acd94cf --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162317.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=this. + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162320.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162320.js new file mode 100644 index 000000000..38cd67fb9 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162320.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth= + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162322.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162322.js new file mode 100644 index 000000000..c48a8d629 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162322.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1 + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162325.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162325.js new file mode 100644 index 000000000..9a8ceab8f --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162325.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162327.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162327.js new file mode 100644 index 000000000..163a44bac --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162327.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[] + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162328.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162328.js new file mode 100644 index 000000000..a91217860 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162328.js @@ -0,0 +1,770 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0] + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162332.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162332.js new file mode 100644 index 000000000..4a4923b59 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162332.js @@ -0,0 +1,772 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162342.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162342.js new file mode 100644 index 000000000..0c48e6267 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162342.js @@ -0,0 +1,772 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162345.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162345.js new file mode 100644 index 000000000..0c48e6267 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162345.js @@ -0,0 +1,772 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162350.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162350.js new file mode 100644 index 000000000..6fa43de04 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162350.js @@ -0,0 +1,772 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rect + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162356.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162356.js new file mode 100644 index 000000000..325b19c62 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162356.js @@ -0,0 +1,772 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number() + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162403.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162403.js new file mode 100644 index 000000000..a7ec21687 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162403.js @@ -0,0 +1,772 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt() + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162407.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162407.js new file mode 100644 index 000000000..030992367 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162407.js @@ -0,0 +1,772 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svg) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162410.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162410.js new file mode 100644 index 000000000..780a5ce2c --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162410.js @@ -0,0 +1,772 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162414.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162414.js new file mode 100644 index 000000000..74a90cece --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162414.js @@ -0,0 +1,772 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162416.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162416.js new file mode 100644 index 000000000..19b5b68dc --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162416.js @@ -0,0 +1,772 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162426.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162426.js new file mode 100644 index 000000000..c7bc1a2fd --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162426.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('rect ') + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162428.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162428.js new file mode 100644 index 000000000..1348be0c4 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162428.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('rect num') + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162429.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162429.js new file mode 100644 index 000000000..02a6bbd98 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162429.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('rect number') + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162431.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162431.js new file mode 100644 index 000000000..3674821a4 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162431.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('rect number',rectNum) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162754.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162754.js new file mode 100644 index 000000000..36bb6c7ef --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162754.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('rect number',rectNum,'data number') + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162756.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162756.js new file mode 100644 index 000000000..d5606bc30 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162756.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('rect number',rectNum,'data number',th) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162800.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162800.js new file mode 100644 index 000000000..e26d7a340 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162800.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162903.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162903.js new file mode 100644 index 000000000..1dfdd7f7d --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162903.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log(,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162904.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162904.js new file mode 100644 index 000000000..6dbb8b4b4 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162904.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('','rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162907.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162907.js new file mode 100644 index 000000000..3abeaf9d5 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162907.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('parent','rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162911.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162911.js new file mode 100644 index 000000000..93f1a6251 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162911.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('parentRectWidth','rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162914.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162914.js new file mode 100644 index 000000000..756901dc3 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162914.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('parentRectWidth',pare'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162916.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162916.js new file mode 100644 index 000000000..03196151f --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812162916.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let svgWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163012.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163012.js new file mode 100644 index 000000000..1316ce0a8 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163012.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this.svg.node().clientWidth; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163018.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163018.js new file mode 100644 index 000000000..7d5db6eea --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163018.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this. + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163028.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163028.js new file mode 100644 index 000000000..c0d230e9f --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163028.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this.options.width - this.options. + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163031.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163031.js new file mode 100644 index 000000000..4700f1ea6 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163031.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this.options.width - this.options.padding. + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163034.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163034.js new file mode 100644 index 000000000..4ef51656f --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163034.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this.options.width - this.options.padding.left + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163038.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163038.js new file mode 100644 index 000000000..837008b0b --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163038.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this.options.width - this.options.padding.left - this.options. + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163041.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163041.js new file mode 100644 index 000000000..fafabf682 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163041.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this.options.width - this.options.padding.left - this.options.padding. + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163042.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163042.js new file mode 100644 index 000000000..b59aadf80 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163042.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this.options.width - this.options.padding.left - this.options.padding.ri + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163044.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163044.js new file mode 100644 index 000000000..8542c6535 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163044.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this.options.width - this.options.padding.left - this.options.padding.right; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(svgWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163049.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163049.js new file mode 100644 index 000000000..d1bae27ec --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163049.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this.options.width - this.options.padding.left - this.options.padding.right; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(drawWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163052.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163052.js new file mode 100644 index 000000000..d1bae27ec --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163052.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this.options.width - this.options.padding.left - this.options.padding.right; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(drawWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163151.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163151.js new file mode 100644 index 000000000..88bc9b259 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163151.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this.options.width - this.options.padding.left - this.options.padding.right; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(drawWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163206.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163206.js new file mode 100644 index 000000000..db264c8ee --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163206.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this.options.width - this.options.padding.left - this.options.padding.right; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(drawWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + if(this.datas.length/interval>1){ + domain=domain.filter((item,index)=>{return index%interval==0}) + } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163220.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163220.js new file mode 100644 index 000000000..2243e06de --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163220.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this.options.width - this.options.padding.left - this.options.padding.right; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(drawWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + if(this.datas.length/interval>1){ + domain=domain.filter((item,index)=>{return index%interval==0}) + } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163526.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163526.js new file mode 100644 index 000000000..932dea142 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163526.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this.options.width - this.options.padding.left - this.options.padding.right; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(drawWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163628.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163628.js new file mode 100644 index 000000000..aa7d8923b --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163628.js @@ -0,0 +1,772 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this.options.width - this.options.padding.left - this.options.padding.right; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(drawWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163633.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163633.js new file mode 100644 index 000000000..3a6636696 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163633.js @@ -0,0 +1,764 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + let domain=this.datas.map(item=>{return item[0][0]}); + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163634.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163634.js new file mode 100644 index 000000000..dcdf94b28 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163634.js @@ -0,0 +1,761 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + let domain=this.datas.map(item=>{return item[0][0]}); + + + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163636.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163636.js new file mode 100644 index 000000000..836bd0c82 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163636.js @@ -0,0 +1,760 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + let domain=this.datas.map(item=>{return item[0][0]}); + + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163642.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163642.js new file mode 100644 index 000000000..932dea142 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163642.js @@ -0,0 +1,774 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + //以每一个小rect宽度为0.1计算,一条数据对应0.1*this.datas[0].length + let drawWidth=this.options.width - this.options.padding.left - this.options.padding.right; + let parentRectWidth=0.1*this.datas[0].length; + + let rectNum=Number.parseInt(drawWidth/parentRectWidth); + + console.log('parentRectWidth',parentRectWidth,'rect number',rectNum,'data number',this.datas.length) + + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163647.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163647.js new file mode 100644 index 000000000..5062ba1fc --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163647.js @@ -0,0 +1,765 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163651.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163651.js new file mode 100644 index 000000000..99a5e6d78 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163651.js @@ -0,0 +1,765 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163926.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163926.js new file mode 100644 index 000000000..946c1e586 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812163926.js @@ -0,0 +1,765 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + // .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164034.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164034.js new file mode 100644 index 000000000..99a5e6d78 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164034.js @@ -0,0 +1,765 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 20]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164038.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164038.js new file mode 100644 index 000000000..5fb749625 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164038.js @@ -0,0 +1,765 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 30]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164112.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164112.js new file mode 100644 index 000000000..956e2a961 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164112.js @@ -0,0 +1,765 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 50]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164201.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164201.js new file mode 100644 index 000000000..674266779 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164201.js @@ -0,0 +1,765 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + // .scaleExtent([1, 50]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164342.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164342.js new file mode 100644 index 000000000..956e2a961 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164342.js @@ -0,0 +1,765 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 50]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164346.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164346.js new file mode 100644 index 000000000..6e4f82764 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164346.js @@ -0,0 +1,765 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164808.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164808.js new file mode 100644 index 000000000..53303de25 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164808.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _ + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164816.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164816.js new file mode 100644 index 000000000..cbdc904d1 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164816.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormate + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164818.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164818.js new file mode 100644 index 000000000..b4936c5cc --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164818.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormat + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164828.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164828.js new file mode 100644 index 000000000..b4936c5cc --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164828.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormat + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164843.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164843.js new file mode 100644 index 000000000..f8fd149e6 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164843.js @@ -0,0 +1,766 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:func + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164848.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164848.js new file mode 100644 index 000000000..6e190ec1e --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164848.js @@ -0,0 +1,768 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(){ + + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164853.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164853.js new file mode 100644 index 000000000..b2a28a274 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164853.js @@ -0,0 +1,768 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(range){ + + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164900.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164900.js new file mode 100644 index 000000000..7e0422aa8 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164900.js @@ -0,0 +1,772 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(range){ + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164905.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164905.js new file mode 100644 index 000000000..2dcca2576 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164905.js @@ -0,0 +1,772 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(range){ + if(range[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164906.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164906.js new file mode 100644 index 000000000..367301b61 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164906.js @@ -0,0 +1,772 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(range){ + if(range[1]-range[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164909.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164909.js new file mode 100644 index 000000000..b0265dd60 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164909.js @@ -0,0 +1,772 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(range){ + if(range[1]-range[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(range[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164910.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164910.js new file mode 100644 index 000000000..acfa660cf --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164910.js @@ -0,0 +1,772 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(range){ + if(range[1]-range[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(range[1]-range[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + if(t_max_min[1]-t_max_min[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(t_max_min[1]-t_max_min[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164918.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164918.js new file mode 100644 index 000000000..a88938180 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164918.js @@ -0,0 +1,768 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(range){ + if(range[1]-range[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(range[1]-range[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164922.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164922.js new file mode 100644 index 000000000..f4581426b --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164922.js @@ -0,0 +1,768 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(range){ + if(range[1]-range[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(range[1]-range[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + this._ + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164924.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164924.js new file mode 100644 index 000000000..b2acdc40b --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164924.js @@ -0,0 +1,768 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(range){ + if(range[1]-range[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(range[1]-range[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + this._timeFormatCheck() + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164925.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164925.js new file mode 100644 index 000000000..22e2861b1 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164925.js @@ -0,0 +1,768 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(range){ + if(range[1]-range[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(range[1]-range[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + this._timeFormatCheck(t) + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164928.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164928.js new file mode 100644 index 000000000..873c7974d --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164928.js @@ -0,0 +1,768 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(range){ + if(range[1]-range[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(range[1]-range[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + this._timeFormatCheck(t_max_min) + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164946.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164946.js new file mode 100644 index 000000000..bd1b9f61e --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812164946.js @@ -0,0 +1,769 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(range){ + if(range[1]-range[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d') + }else if(range[1]-range[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + this._timeFormatCheck(t_max_min) + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + this._timeFormatCheck(t_max_min) + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812165255.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812165255.js new file mode 100644 index 000000000..0b3caea06 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812165255.js @@ -0,0 +1,769 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(range){ + if(range[1]-range[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d ') + }else if(range[1]-range[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + this._timeFormatCheck(t_max_min) + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + this._timeFormatCheck(t_max_min) + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812165258.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812165258.js new file mode 100644 index 000000000..083539caf --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812165258.js @@ -0,0 +1,769 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(range){ + if(range[1]-range[0]>7*24*60*60*1000){ //时间大于7天不显示小时分钟 + this._timeFormat=d3.timeFormat('%Y-%m-%d %H') + }else if(range[1]-range[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + this._timeFormatCheck(t_max_min) + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + this._timeFormatCheck(t_max_min) + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812165403.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812165403.js new file mode 100644 index 000000000..d001a8d9a --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812165403.js @@ -0,0 +1,767 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(range){ + if(range[1]-range[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + this._timeFormatCheck(t_max_min) + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + this._timeFormatCheck(t_max_min) + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + // .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812165607.js b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812165607.js new file mode 100644 index 000000000..b00f03a23 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Chart_20200812165607.js @@ -0,0 +1,767 @@ +import * as d3 from "d3"; +import './d3Chart.scss' +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; +import i18n from "../../common/i18n"; +import chartDataFormat from "../chartDataFormat"; +import {Bar, CHART_TYPE} from "./d3Util"; +import {Line} from "./d3Util"; +import {tooltipFormatter} from "./d3Util"; +import {getUUID} from "../../common/js/common"; + +export function D3LineChart(selector,option){ + return { + options:{ + selector:selector, //选择器 + type:option.type, + toolbox:{ + show:true, + width:100, + height:25, + stack:{ + title:i18n.t('overall.toolBox.stack'), + backTitle:i18n.t('overall.toolBox.stackBack'), + show:true, + } + }, + width:option.width, + height:option.height, + timeFormat:option.timeFormat?option.timeFormat:'%Y-%m-%d', + datas:option.datas, + legends:option.legends, + title:option.title?option.title:'', + subTitle:option.subTitle?option.subTitle:'', + colors:option.colors, + padding:option.padding?option.padding:{top:40,left:40,bottom:40,right:20}, + duration:option.duration?option.duration:800, + showXAxisTick:option.showXAxisTick?option.showXAxisTick:false, + showYAxisTick:option.showYAxisTick?option.showYAxisTick:false, + tooltipFormatter:option.tooltipFormatter, + unit:option.dataFormatter?option.dataFormatter:9, + }, + + + init:function(){ + //定义画布 + if(option){ + this.initOption(); + } + this.dealData(); + this.drawChart(); + }, + createSvg:function(){ + let $self=this; + this.svg=d3.select(this.options.selector) + .append('svg') + .attr('width',this.options.width) + .attr('height',this.options.height) + .on('mouseover',function(){ + if ($self.tooltip) $self.tooltip.style('display', null); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'orange'); + $self.svg.style('cursor','crosshair') + }) + .on('mouseout', removeTooltip); + + function removeTooltip() { + if ($self.tooltip) $self.tooltip.style('display', 'none'); + if ($self.tooltipLine) $self.tooltipLine.attr('stroke', 'none'); + } + }, + drawChart(){ + this.createSvg(); + + this.drawTitle(); + + this.createDefs() + + this.creatScale(); + // if(this.type!==CHART_TYPE.BAR&&this.type!==CHART_TYPE.STACK_BAR){ + this.createXInnerBar(); + // } + + this.createYInnderBar(); + this.createXAxis(); + this.createYAxis(); + + // this.createLegends(); + if(this._type!==CHART_TYPE.BAR && this._type!==CHART_TYPE.STACK_BAR){ + this.drawLines(); + }else{ + this.drawBars(); + } + + this.createZoom() + + this.drawToolbox(); + + this.drawTooltipContainor() + + }, + initOption:function(){ + let $self=this; + if(this.options.type){ + this._type=this.options.type + }else{ + this._type =CHART_TYPE.LINE + } + + this._timeFormat=d3.timeFormat(this.options.timeFormat) + this._head_height=this.options.padding.top + this._foot_height=this.options.padding.bottom + this.currentLineNum=this.options.datas.length; + this._dataFormatter=chartDataFormat.getUnit(this.options.unit).compute; + + if(this.options.toolbox){ + this.options.toolbox=this.options.toolbox; + } + + if(!this.options.colors || this.options.colors.length{ + if(i!=0){ + let stackData=this.datas[i-1]; + d.forEach((t,j)=>{ + let pre=stackData[j] + + t[1]=t[1]+pre[1] + }) + } + }) + } + + if(this._type == CHART_TYPE.BAR ||this._type == CHART_TYPE.STACK_BAR){ + this._pastSourceData=JSON.parse(JSON.stringify(this.datas)); + this.datas=[]; + for(let i=0;i{ + return item[i] + }) + this.datas.push(data) + } + } + + if(this._type == CHART_TYPE.STACK_BAR){ + this._stackSourceData=JSON.parse(JSON.stringify(this.datas));//保存转换之前的数据 + this.datas.forEach(data=>{ + data.map((item,i)=>{ + if(i != 0){ + let before=data[i-1] + item[1]+=before[1]; + } + return item; + }) + }) + } + /*if(this.type == CHART_TYPE.BAR||this.type == CHART_TYPE.STACK_BAR){ + this.minMax=getBarDataMinMax(this.datas) + }else{ + + }*/ + this.minMax=getMinMax(this.datas); + if(this.options.padding.left < computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'')){ + this.options.padding.left = computeDistance(this._dataFormatter(this.minMax.max,null,-1,3)+'') + } + }, + drawTitle:function(){ + //添加标题 + if (this.options.title != "") { + this.svg.append("g") + .append("text") + .text(this.options.title) + .attr("class", "title") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + this._head_height += 30; + } + //添加副标题 + if (this.options.subTitle != "") { + this.svg.append("g") + .append("text") + .text(this.options.subTitle) + .attr("class", "subTitle") + .attr("x", this.options.width / 2) + .attr("y", this._head_height); + + this._head_height += 20; + } + }, + drawTooltipContainor:function(){ + this.tooltip = d3.select('body') + .append('div') + .attr('id',this.options.selector+'-'+'tooltip') + .attr('style',"position: absolute;z-index:9999; background-color: rgba(221,228,237,1);border-color:rgba(221,228,237,1); padding: 5px; display: none; left: 983px; top: 89px;") + this.tooltipLine = this.svg.append('line'); + this.dotBox = this.svg.append('g') + /* .selectAll() + .data(this.datas) + .enter() + .append('circle') + .attr("cx", 0) + .attr("cy", 0) + .attr("r", 3) + .attr("fill", function(d,i){ + return $self.colors[i] + }) + .transaction()*/ + }, + _timeFormatCheck:function(range){ + if(range[1]-range[0]>24*60*60*1000){//时间大于一天小于7天,不显示秒 + this._timeFormat=d3.timeFormat('%m-%d %H:%M') + } + }, + creatScale:function(){ + let t_max_min = d3.extent(this.datas[0], function(d) { + return d[0]; + }); + this._timeFormatCheck(t_max_min) + this.xTicks = Math.min(this.datas[0].length,10) + + //横坐标轴比例尺 + this.xScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + + t_max_min = d3.extent(this._pastSourceData[0], function(d) { + return d[0]; + }); + this._timeFormatCheck(t_max_min) + + //辅助比例尺 用于确定鼠标当前对应的x轴位置 + this._assistScale = d3.scaleTime() + .domain(t_max_min) + .range([this.options.padding.left, this.options.width - this.options.padding.right]); + + //数据量过大时,渲染出的元素width会为0,导致无法显示 + // let interval=Number.parseInt(this.datas.length/Number.parseInt((this.options.width-this.options.padding.left-this.options.padding.right)/37+'')) + let domain=this.datas.map(item=>{return item[0][0]}); + + // if(this.datas.length/interval>1){ + // domain=domain.filter((item,index)=>{return index%interval==0}) + // } + this._barXAxisDomain=domain; + this.xScale=d3.scaleBand() + .domain(domain) + .range([this.options.padding.left, this.options.width - this.options.padding.right]) + .paddingInner(0.1) + + this.xScale1=d3.scaleBand() + .domain(d3.range(this.options.legends.length)) + .rangeRound([0,this.xScale.bandwidth()]) + } + + let minMax=this.minMax + //纵坐标轴比例尺 + this.yScale = d3.scaleLinear() + .domain([minMax.min, Math.round(minMax.max*1.05)]) + .range([this.options.height - this._foot_height, this._head_height]); + + }, + createZoom:function(){ + let $self=this; + this.zoom = d3.zoom() + .scaleExtent([1, 100]) + .translateExtent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .extent([ + [this.options.padding.top, 0], + [this.options.width - this.options.padding.right, this.options.height] + ]) + .on("zoom", zoomed); + this.svg.call(this.zoom); + + function zoomed() { + let t = d3.event.transform; + $self.currentTransform=t; + if($self._type != CHART_TYPE.BAR&&$self._type != CHART_TYPE.STACK_BAR){ + let xt = t.rescaleX($self.xScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + + $self.svg.select('.inner_line_x').call($self.xInner.scale(xt)); + + for (let i = 0; i < $self.lines.length; i++) { + let lineObject = $self.lines[i]; + + lineObject.scale(i, 0, t); + } + }else{ + $self.xScale.range([$self.options.padding.left, $self.options.width - $self.options.padding.right].map(d=>d3.event.transform.applyX(d))) + $self.xScale1.rangeRound([0,$self.xScale.bandwidth()]) + + let xt = t.rescaleX($self._assistScale); + $self.svg.select('.bottom_axis').call($self.xAxis.scale(xt)).selectAll("text") + .attr("transform", "translate(-10,10) rotate(-20)"); + + if(!$self.options.showXAxisTick){ + let xAxis=$self.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + for (let i = 0; i < $self.bars.length; i++) { + let barObject = $self.bars[i]; + + barObject.scale(i, 0, t); + } + } + } + }, + createDefs:function(){ //创建遮罩 + this._clipSelector=getUUID()+'-clip'; + this.svg.append("defs").append("clipPath") + .attr("id", this._clipSelector) + .append("rect") + + .attr('x', this.options.padding.left) + .attr('y', 0) + .attr("width", this.options.width - this.options.padding.left - this.options.padding.right) + .attr("height", this.options.height); + }, + createXInnerBar:function(){ + + let xInner = d3.axisBottom() + .scale(this.xScale) + .tickSize(-(this.options.height - this._head_height - this._foot_height), 0, 0) + .tickFormat("") + .ticks(this.xTicks); + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xInner.scale(this._assistScale) + } + this.xInner=xInner; + //添加横轴网格线 + let xInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_x") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xInner); + }, + createYInnderBar:function(){ + //定义纵轴网格线 + let yInner = d3.axisLeft() + .scale(this.yScale) + .tickSize(-(this.options.width - this.options.padding.left - this.options.padding.right), 0, 0) + .tickFormat("") + .ticks(10); + this.yInner=yInner + //添加纵轴网格线 + let yInnerBar = this.svg.append("g") + .attr("class", "inner_line inner_line_y") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yInner); + }, + createXAxis:function(){ + let $self=this; + //定义横轴 + let xAxis = d3.axisBottom() + .scale(this.xScale) + .ticks(this.xTicks) + .tickFormat($self._timeFormat) + if(this._type == CHART_TYPE.BAR||this._type == CHART_TYPE.STACK_BAR){ + xAxis.scale(this._assistScale) + } + this.xAxis=xAxis + //添加横坐标轴 + let xBar = this.svg.append("g") + .attr("class", "bottom_axis") + .attr("transform", "translate(0," + (this.options.height - this._foot_height) + ")") + .call(xAxis).selectAll("text") + .attr("transform", "translate(-10,8) rotate(-20)") + + if(!this.options.showXAxisTick){ + let xAxis=this.svg.select('.bottom_axis') + xAxis.select('.domain').remove(); + xAxis.selectAll('.tick').select('line').remove() + } + }, + createYAxis:function(){ + let dataFormatter=this._dataFormatter; + let $self=this; + //定义纵轴 + let yAxis = d3.axisLeft() + .scale(this.yScale) + .tickFormat(function(d,i,g){ + let yAxisVals=g.map(item=>{ + return item.__data__; + }) + let dot = 0; + let yAxisValsCopy=Object.assign([],yAxisVals) + yAxisVals=yAxisValsCopy.map(item=>{ + return dataFormatter(item,null,-1,dot) + }) + while(new Set(yAxisVals).size != yAxisVals.length){ + dot++; + yAxisVals=yAxisValsCopy.map(item => { + return dataFormatter(item,null,-1,dot) + }) + } + + return yAxisVals[i]; + }) + this.yAxis=yAxis; + //添加纵轴 + let yBar = this.svg.append("g") + .attr("class", "left_axis") + .attr("transform", "translate(" + this.options.padding.left + ",0)") + .call(yAxis); + + if(!this.options.showYAxisTick){ + let yAxis=this.svg.select('.left_axis') + yAxis.select('.domain').remove(); + yAxis.selectAll('.tick').select('line').remove() + } + }, + createLegends:function(){ + let $self=this; + let legend = d3.select('#legendArea').attr('class','legend') + let textGroup = legend.selectAll("div") + .data(this.options.legends); + + textGroup.exit().remove(); + + let legendItem=legend.selectAll("div") + .data(this.options.legends) + .enter() + .append("div") + .attr("class", "legend-item") + + legendItem.append('span') + .attr('class','legend-shape') + .style('background',function(d,i){ + return $self.colors[i] + }) + + legendItem.append('span') + .text(function(d,i){ + return d.name + }) + + + /*let rectGroup = legend.selectAll("rect") + .data(this.legends); + + rectGroup.exit().remove(); + + legend.selectAll("rect") + .data(this.legends) + .enter() + .append("rect") + .attr("x", function(d, i) { + return i * 100 - 20; + }) + .attr("y", -10) + .attr("width", 12) + .attr("height", 12) + .attr("fill", function(d, i) { + return $self.colors[i]; + });*/ + + // legend.attr("transform", "translate(" + ((this.width - this.legends.length * 100) / 2) + "," + (this.height - 10) + ")"); + }, + drawLines:function(){ + this.lines=[]; + let $self=this; + this.svg + .on('mousemove', lineTooltip) + + let totalColor=randomcolor(); + function lineTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self.xScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self.xScale.invert(d3.mouse($self.svg.node())[0]); + + drawTipLine(time) + drawTipDot(time) + let sum=0; + let items=[]; + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(time)) + + let tooltipDatas=$self._type == CHART_TYPE.STACK_AREA?$self._stackSourceData:$self.datas; + + tooltipDatas.forEach((d,i)=>{ + let toolVal=d[0]; + let min=Math.abs(+toolVal[0] - +time ) + d.forEach(item=>{ + let temp=Math.abs(+item[0] - +time) + if(temp - min < 0){ + min=temp; + toolVal=item; + } + }) + if(toolVal){ + sum+=toolVal[1]; + items.push({legend:$self.options.legends[i],value:$self._dataFormatter(toolVal[1],null,-1,2),color:$self.colors[i]}) + } + }) + if($self._type == CHART_TYPE.STACK_AREA){ + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(sum,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + + function drawTipLine(time){ + if ($self.currentTransform) + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.currentTransform.applyX($self.xScale(time))) + .attr('x2', $self.currentTransform.applyX($self.xScale(time))) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + else + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)) + .attr('x2', $self.xScale(time)) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + function drawTipDot(time) { + // if(chart.currentTransform){ + // + // }else{ + // + // } + } + + for (let i = 0; i < this.currentLineNum; i++) { + let newLine = new Line(this); + newLine.init(i); + this.lines.push(newLine); + } + }, + drawBars:function(){ + let $self=this; + this.svg.on('mousemove', barTooltip) + let totalColor=randomcolor(); + function barTooltip(){ + let x=d3.mouse($self.svg.node())[0]; + if(x<$self.options.padding.left||x>$self.options.width-$self.options.padding.right){ + return false; + } + + if ($self.currentTransform) + var time = $self.currentTransform.rescaleX($self._assistScale).invert(d3.mouse($self.svg.node())[0]); + else + var time = $self._assistScale.invert(d3.mouse($self.svg.node())[0]); + // var time = assistScale.invert(d3.mouse($self.svg.node())[0]); + + let min=Math.abs(time-$self._barXAxisDomain[0]); + let minIndex=0; + $self._barXAxisDomain.forEach((item,i)=>{ + let temp=Math.min(min,Math.abs(time - item)) + if(min!==temp){ + min=temp; + minIndex=i; + } + }) + let xAisVal=$self._barXAxisDomain[minIndex]; + drawTipLine(xAisVal) + let tooltipArr=$self._type == CHART_TYPE.BAR?$self.datas:$self._stackSourceData + let tooltipData=tooltipArr.find(item=>{return item[0][0] == xAisVal}) + + $self.tooltip.html(d3.timeFormat('%Y-%m-%d %H:%M:%S')(xAisVal)) + + + let items=tooltipData.map((item,i)=>{ + return {legend:$self.options.legends[i],value:$self._dataFormatter(item[1],null,-1,2),color:$self.colors[i]} + }) + if($self._type == CHART_TYPE.STACK_BAR){ + let totalData=d3.sum(tooltipData.map(item=>{return item[1]})) + items.push({legend:{name:i18n.t('dashboard.panel.chartTotal'),isGray:false},value:$self._dataFormatter(totalData,null,-1,2),color:totalColor}) + } + tooltipFormatter($self.tooltip,items) + + let position=getTooltipPosition($self.tooltip); + + $self.tooltip + .style('left', position.left + 'px') + .style('top', position.top + 'px') + } + function drawTipLine(time){ + $self.tooltipLine + .style('stroke-width','1') + .attr("clip-path", "url(#"+$self._clipSelector+")") + .attr('x1', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('x2', $self.xScale(time)+$self.xScale.bandwidth()/2) + .attr('y1', $self._head_height) + .attr('y2', $self.options.height - $self._foot_height); + } + this.bars=[]; + for(let i=0;i < this.datas.length;i++){ + let newBar=new Bar(this); + newBar.init(i) + this.bars.push(newBar) + } + + }, + reDrawChart:function(type,data){ + let $self=this; + this.clearChart(); + $self._type=type?type:$self._type; + this.dealData(); + this.drawChart(); + + }, + drawToolbox:function(){ + if(this.options.toolbox.show){ + let $self=this; + let toolbox=d3.select(this.options.selector).select('.toolbox') + if(!toolbox.node()){ + toolbox=d3.select(this.options.selector) + .append('div').attr('class','toolbox') + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + }else{ + toolbox + .attr('style','position:absolute;top:'+(this._head_height-this.options.toolbox.height)+'px;left:'+(this.options.width-this.options.toolbox.width-this.options.padding.right)+'px;min-width:'+this.options.toolbox.width+'px;height:'+this.options.toolbox.height+'px;') + toolbox.selectAll('i').remove(); + } + if(this.options.toolbox.stack.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-stack toolbox-stack') + .attr('title',this.options.toolbox.stack.title) + .on('click',function(){ + if($self._type == CHART_TYPE.LINE ||$self._type == CHART_TYPE.AREA){ + $self.backZoom={ + type:$self._type, + } + $self.reDrawChart(CHART_TYPE.STACK_AREA) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type==CHART_TYPE.BAR){ + $self.backZoom={ + type:$self._type, + data:JSON.parse(JSON.stringify($self._pastSourceData)) + } + $self.reDrawChart(CHART_TYPE.STACK_BAR,$self._pastSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.backTitle) + }else if($self._type == CHART_TYPE.STACK_AREA){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self._stackSourceData) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + }else if($self._type == CHART_TYPE.STACK_BAR){ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + toolbox.select('.toolbox-stack').attr('title',$self.options.toolbox.stack.title) + } + } + }) + } + /*if(this.toolbox.area.show){ + toolbox.append('i') + .attr('class','nz-icon nz-icon-area') + .attr('title',this.toolbox.area.title) + .on('click',function(){ + if($self.type != CHART_TYPE.AREA){ + $self.reDrawChart(CHART_TYPE.AREA) + }else{ + if($self.backZoom){ + $self.reDrawChart($self.backZoom.type,$self.backZoom.data) + } + } + }) + }*/ + + } + }, + dispatchAction(type,param){ + this.svg.selectAll('.event-echo-unit').dispatch(type,{detail:{name:param}}) + }, + clearChart:function(){ + d3.select(this.options.selector).selectAll('svg').remove(); + this.tooltip.remove(); + this.tooltipLine.remove(); + + } + } +} +//取得多维数组最大值 +function getMaxdata(arr) { + let maxdata = 0; + for (let i = 0; i < arr.length; i++) { + maxdata = d3.max([maxdata, d3.max(arr[i], function(d) { + return d[1]; + })]); + } + return maxdata; +} + +function getMinMax(arr){ + let temp=[]; + arr.forEach((item,i)=>{ + let minMax=d3.extent(item,function(d){return d[1]}) + temp=temp.concat(minMax) + }) + let minMax=d3.extent(temp) + return{min:minMax[0],max:minMax[1]} +} + +function computeDistance(str){ + let width = 0; + let html = document.createElement('span'); + html.innerText = str; + html.className = 'getTextWidth'; + document.querySelector('body').appendChild(html); + width = document.querySelector('.getTextWidth').offsetWidth; + document.querySelector('.getTextWidth').remove(); + return Number((width+5)); +} + +function getTooltipPosition(tooltip){ + + let x=d3.event.pageX + let y=d3.event.pageY + + let tooltipWidth=tooltip.node().offsetWidth + let tooltipHeight=tooltip.node().offsetHeight + + + let windowWidth=document.body.offsetWidth; + let windowHeight=document.body.offsetHeight; + + let left=x + 20; + let top=y + 20; + + if(x+tooltipWidth+20>windowWidth){ + left=x - 20 - tooltipWidth; + } + + if(y+tooltipHeight+20>windowHeight){ + top=y - 20 - tooltipHeight; + } + + return {left:left,top:top} + +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812135814.js b/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812135814.js new file mode 100644 index 000000000..a617cdc5f --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812135814.js @@ -0,0 +1,341 @@ +import * as d3 from "d3"; +import i18n from "../../common/i18n"; +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; + +export function CHART_TYPE(){} +CHART_TYPE.LINE='line' +CHART_TYPE.AREA='area' +CHART_TYPE.STACK_AREA='stackArea' +CHART_TYPE.BAR='bar' +CHART_TYPE.STACK_BAR='stackBar' + +export function Bar(chart){ + this.group=null; + let dataset=chart.datas; + let svg=chart.svg; + let xScale=chart.xScale; + let xScale1=chart.xScale1; + let yScale=chart.yScale; + let colors=chart.colors; + let legends=chart.options.legends; + let singleFlag=legends.find(item=>{return item.isGray==true}) + let state='multi'; + let colorScale=d3.scaleOrdinal() + .domain(chart.options.height - chart._foot_height,chart._head_height) + .range(colors) + + this.init=function(index){ + /*let data=dataset.map((item,i)=>{ + return item[index]; + })*/ + let data=dataset[index] + let time=data[0][0] + let $self=this; + let timeScale=xScale(time); + if(!timeScale){ + return; + } + this.data=data; + this.group=svg.append('g').attr("clip-path","url(#"+chart._clipSelector+")") + .append('g') + .attr('transform','translate('+timeScale+',0)') + this.rects=[]; + data.forEach((d,i)=>{ + let rect=this.group.append('g').attr('fill',legends[i].isGray?'none':colors[i]) + .append('rect') + .attr('class','event-echo-unit') + .attr('y',yScale(d[1])) + .on('legend-single-show',function(){ + state='single' + let legend=chart.options.legends[i]; + let event=d3.event; + let name=event.detail?event.detail.name:"" + if(legend.name == name){ + if(chart._type == CHART_TYPE.BAR){ + rect.transition().duration(chart.options.duration) + .attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + .attr('fill',colors[i]) + }else{ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]) + .attr('height', yScale(chart.minMax.min) - yScale(d[1])) + } + + legend.isGray=false; + }else{ + if(chart._type == CHART_TYPE.BAR){ + rect.attr('fill','none').attr('x',xScale1(i)).attr('width',xScale1.bandwidth()) + }else{ + rect.attr('fill','none') + } + legend.isGray=true; + } + }) + .on('legend-all-show',function(){ + state='multi' + if(chart._type == CHART_TYPE.BAR){ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]).attr('x',xScale1(i)).attr('width',xScale1.bandwidth()) + }else{ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]) + .attr('height',function(){ + if(i==0){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + let before=data[i-1]; + return yScale(before[1]) - yScale(d[1]) + } + }) + } + chart.options.legends.forEach(item=>{item.isGray=false}) + }) + + if(chart._type==CHART_TYPE.BAR){ + rect.attr('x',xScale1 (i) ) + .attr('width',xScale1.bandwidth()) + .attr('height', yScale(chart.minMax.min) - yScale(d[1])) + }else{ + rect.attr('width',xScale.bandwidth()) + .attr('height',function(){ + if(i==0){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + if(singleFlag){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + let before=data[i-1]; + return yScale(before[1]) - yScale(d[1]) + } + } + }) + } + this.rects.push(rect) + }) + } + this.scale = function(index, _duration, transform) { + if(!this.data){ + return; + } + let data=this.data; + let time=data[0][0] + let $self=this; + let timeScale=xScale(time); + + if(!timeScale){ + return; + } + if(this.group){ + this.group.attr('transform','translate('+timeScale+',0)') + if(chart._type == CHART_TYPE.BAR){ + if(state == 'single'){ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + }) + }else{ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(i)) + .attr('width',xScale1.bandwidth()) + }) + } + }else{ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + }) + } + } + } +} +export function Line(chart) { + this.group = null; + this.path = null; + let state = 'multi'//区分是显示单条还是全部显示 + let dataset=chart.datas; + let svg=chart.svg; + let xScale=chart.xScale; + let yScale=chart.yScale; + let lineColor=chart.colors; + let legends=chart.options.legends; + let singleFlag=legends.find(item=>{return item.isGray == true}) + const dispatch=chart.dispatch; + + this.init = function(id) { + let arr = dataset[id]; + let legend=chart.options.legends[id]; + this.group = svg.append("g"); + let $self=this; + let line = d3.line() + .x(function(d, i) { + return xScale(d[0]); + }) + .y(function(d) { + return yScale(d[1]); + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + + let areaForStack = d3.area() + .x(function(d, i) { + return xScale(d[0]); + }) + // .y0(chart.height - chart._foot_height) + .y0(function(d,i){ + if(id==0){ + return chart.options.height - chart._foot_height + }else{ + if(singleFlag){ + return chart.options.height - chart._foot_height + }else{ + return yScale(dataset[id-1][i][1]) + } + } + }) + .y1(function(d) { + return yScale(d[1]) + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + + let areaForNormal=d3.area() + .x(function(d, i) { + return xScale(d[0]); + }) + .y0(chart.options.height - chart._foot_height) + .y1(function(d) { + return yScale(d[1]) + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + //添加折线 + this.path = this.group.append("path") + .attr("clip-path","url(#"+chart._clipSelector+")") + .attr("d", line(arr)) + .attr('class','event-echo-unit chart-line') + .style("fill", 'none') + .style("stroke-width", 1) + .style("stroke", legends[id].isGray?'none':lineColor[id]) + .style("stroke-opacity", 0.9) + .on('legend-single-show',function(d,i,group){ + let event=d3.event; + state='single' + let name=event.detail?event.detail.name:"" + if(legend.name != name){ + $self.group + .transition() + .duration(chart.options.duration) + .style('opacity','0') + legend.isGray=true; + }else{ + $self.group.transition() + .duration(chart.options.duration).style('opacity','1') + legend.isGray=false; + if(chart.currentTransform){ + $self.scale(id,chart.options.duration,chart.currentTransform) + }else{ + $self.group.select('.chart-area').attr('d',areaForNormal(arr)) + } + } + }) + .on('legend-all-show',function(){ + let event=d3.event; + state='multi' + $self.group.transition() + .duration(chart.options.duration).style('opacity','1') + chart.options.legends.forEach(item=>{ + item.isGray=false; + }) + if(chart.currentTransform){ + $self.scale(id,chart.options.duration,chart.currentTransform) + }else{ + $self.group.select('.chart-area').attr('d',areaForStack(arr)) + } + }) + if(chart._type==CHART_TYPE.AREA||chart._type == CHART_TYPE.STACK_AREA){ + this.area=this.group.append('path') + .attr("clip-path", "url(#"+chart._clipSelector+")") + .attr('class','chart-area') + .style('fill',legends[id].isGray?'none':lineColor[id]) + .style("stroke", 'none') + .style('opacity','.1') + if(chart._type == CHART_TYPE.AREA){ + this.area.attr('d',areaForNormal(arr)) + }else{ + this.area.attr('d',areaForStack(arr)) + } + } + }; + + this.scale = function(id, _duration, transform) { + + let arr = dataset[id]; + + let line = d3.line() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y(function(d) { + return yScale(d[1]); + }) + let areaForNormal=d3.area() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y0(chart.options.height - chart._foot_height) + .y1(function(d) { + return yScale(d[1]) + }) + + let areaForStack=d3.area() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y0(function(d,i){ + if(id==0){ + return chart.options.height - chart._foot_height + }else{ + return yScale(dataset[id-1][i][1]) + } + }) + .y1(function(d) { + return yScale(d[1]) + }) + + //添加折线 + this.group.select(".chart-line") + .attr("d", line(arr)) + .style("fill", "none") + .style("stroke-width", 1) + .style("stroke", legends[id].isGray?'none':lineColor[id]) + .style("stroke-opacity", 0.9); + if(chart._type == CHART_TYPE.AREA||chart._type == CHART_TYPE.STACK_AREA){ + let area=this.group.select(".chart-area") + .style('fill',legends[id].isGray?'none':lineColor[id]) + .style("stroke", 'none') + .style('opacity','.1') + if(state == 'single'){ + area.attr("d", areaForNormal(arr)) + }else if(state == 'multi'){ + if(chart._type == CHART_TYPE.STACK_AREA) { + area.attr("d", areaForStack(arr)) + }else { + area.attr("d", areaForNormal(arr)) + } + } + } + } +} + +export function tooltipFormatter(target,params){ + target.selectAll('div') + .data(params) + .enter() + .append('div') + .html(function(d,i){ + if(!d.legend.isGray){ + return `
+
${d.legend.alias?d.legend.alias:d.legend.name}:
+
${d.value}
+
` + } + }) +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812163439.js b/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812163439.js new file mode 100644 index 000000000..9ba42428a --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812163439.js @@ -0,0 +1,341 @@ +import * as d3 from "d3"; +import i18n from "../../common/i18n"; +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; + +export function CHART_TYPE(){} +CHART_TYPE.LINE='line' +CHART_TYPE.AREA='area' +CHART_TYPE.STACK_AREA='stackArea' +CHART_TYPE.BAR='bar' +CHART_TYPE.STACK_BAR='stackBar' + +export function Bar(chart){ + this.group=null; + let dataset=chart.datas; + let svg=chart.svg; + let xScale=chart.xScale; + let xScale1=chart.xScale1; + let yScale=chart.yScale; + let colors=chart.colors; + let legends=chart.options.legends; + let singleFlag=legends.find(item=>{return item.isGray==true}) + let state='multi'; + let colorScale=d3.scaleOrdinal() + .domain(chart.options.height - chart._foot_height,chart._head_height) + .range(colors) + + this.init=function(index){ + /*let data=dataset.map((item,i)=>{ + return item[index]; + })*/ + let data=dataset[index] + let time=data[0][0] + let $self=this; + let timeScale=xScale(time); + if(!timeScale){ + return; + } + this.data=data; + this.group=svg.append('g').attr("clip-path","url(#"+chart._clipSelector+")") + .append('g') + .attr('transform','translate('+timeScale+',0)') + this.rects=[]; + data.forEach((d,i)=>{ + let rect=this.group.append('g').attr('fill',legends[i].isGray?'none':colors[i]) + .append('rect') + .attr('class','event-echo-unit') + .attr('y',yScale(d[1])) + .on('legend-single-show',function(){ + state='single' + let legend=chart.options.legends[i]; + let event=d3.event; + let name=event.detail?event.detail.name:"" + if(legend.name == name){ + if(chart._type == CHART_TYPE.BAR){ + rect.transition().duration(chart.options.duration) + .attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + .attr('fill',colors[i]) + }else{ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]) + .attr('height', yScale(chart.minMax.min) - yScale(d[1])) + } + + legend.isGray=false; + }else{ + if(chart._type == CHART_TYPE.BAR){ + rect.attr('fill','none').attr('x',xScale1(i)).attr('width',xScale1.bandwidth()) + }else{ + rect.attr('fill','none') + } + legend.isGray=true; + } + }) + .on('legend-all-show',function(){ + state='multi' + if(chart._type == CHART_TYPE.BAR){ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]).attr('x',xScale1(i)).attr('width',xScale1.bandwidth()) + }else{ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]) + .attr('height',function(){ + if(i==0){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + let before=data[i-1]; + return yScale(before[1]) - yScale(d[1]) + } + }) + } + chart.options.legends.forEach(item=>{item.isGray=false}) + }) + + if(chart._type==CHART_TYPE.BAR){ + rect.attr('x',xScale1 (i) ) + .attr('width',xScale1.bandwidth()==0?) + .attr('height', yScale(chart.minMax.min) - yScale(d[1])) + }else{ + rect.attr('width',xScale.bandwidth()) + .attr('height',function(){ + if(i==0){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + if(singleFlag){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + let before=data[i-1]; + return yScale(before[1]) - yScale(d[1]) + } + } + }) + } + this.rects.push(rect) + }) + } + this.scale = function(index, _duration, transform) { + if(!this.data){ + return; + } + let data=this.data; + let time=data[0][0] + let $self=this; + let timeScale=xScale(time); + + if(!timeScale){ + return; + } + if(this.group){ + this.group.attr('transform','translate('+timeScale+',0)') + if(chart._type == CHART_TYPE.BAR){ + if(state == 'single'){ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + }) + }else{ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(i)) + .attr('width',xScale1.bandwidth()) + }) + } + }else{ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + }) + } + } + } +} +export function Line(chart) { + this.group = null; + this.path = null; + let state = 'multi'//区分是显示单条还是全部显示 + let dataset=chart.datas; + let svg=chart.svg; + let xScale=chart.xScale; + let yScale=chart.yScale; + let lineColor=chart.colors; + let legends=chart.options.legends; + let singleFlag=legends.find(item=>{return item.isGray == true}) + const dispatch=chart.dispatch; + + this.init = function(id) { + let arr = dataset[id]; + let legend=chart.options.legends[id]; + this.group = svg.append("g"); + let $self=this; + let line = d3.line() + .x(function(d, i) { + return xScale(d[0]); + }) + .y(function(d) { + return yScale(d[1]); + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + + let areaForStack = d3.area() + .x(function(d, i) { + return xScale(d[0]); + }) + // .y0(chart.height - chart._foot_height) + .y0(function(d,i){ + if(id==0){ + return chart.options.height - chart._foot_height + }else{ + if(singleFlag){ + return chart.options.height - chart._foot_height + }else{ + return yScale(dataset[id-1][i][1]) + } + } + }) + .y1(function(d) { + return yScale(d[1]) + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + + let areaForNormal=d3.area() + .x(function(d, i) { + return xScale(d[0]); + }) + .y0(chart.options.height - chart._foot_height) + .y1(function(d) { + return yScale(d[1]) + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + //添加折线 + this.path = this.group.append("path") + .attr("clip-path","url(#"+chart._clipSelector+")") + .attr("d", line(arr)) + .attr('class','event-echo-unit chart-line') + .style("fill", 'none') + .style("stroke-width", 1) + .style("stroke", legends[id].isGray?'none':lineColor[id]) + .style("stroke-opacity", 0.9) + .on('legend-single-show',function(d,i,group){ + let event=d3.event; + state='single' + let name=event.detail?event.detail.name:"" + if(legend.name != name){ + $self.group + .transition() + .duration(chart.options.duration) + .style('opacity','0') + legend.isGray=true; + }else{ + $self.group.transition() + .duration(chart.options.duration).style('opacity','1') + legend.isGray=false; + if(chart.currentTransform){ + $self.scale(id,chart.options.duration,chart.currentTransform) + }else{ + $self.group.select('.chart-area').attr('d',areaForNormal(arr)) + } + } + }) + .on('legend-all-show',function(){ + let event=d3.event; + state='multi' + $self.group.transition() + .duration(chart.options.duration).style('opacity','1') + chart.options.legends.forEach(item=>{ + item.isGray=false; + }) + if(chart.currentTransform){ + $self.scale(id,chart.options.duration,chart.currentTransform) + }else{ + $self.group.select('.chart-area').attr('d',areaForStack(arr)) + } + }) + if(chart._type==CHART_TYPE.AREA||chart._type == CHART_TYPE.STACK_AREA){ + this.area=this.group.append('path') + .attr("clip-path", "url(#"+chart._clipSelector+")") + .attr('class','chart-area') + .style('fill',legends[id].isGray?'none':lineColor[id]) + .style("stroke", 'none') + .style('opacity','.1') + if(chart._type == CHART_TYPE.AREA){ + this.area.attr('d',areaForNormal(arr)) + }else{ + this.area.attr('d',areaForStack(arr)) + } + } + }; + + this.scale = function(id, _duration, transform) { + + let arr = dataset[id]; + + let line = d3.line() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y(function(d) { + return yScale(d[1]); + }) + let areaForNormal=d3.area() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y0(chart.options.height - chart._foot_height) + .y1(function(d) { + return yScale(d[1]) + }) + + let areaForStack=d3.area() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y0(function(d,i){ + if(id==0){ + return chart.options.height - chart._foot_height + }else{ + return yScale(dataset[id-1][i][1]) + } + }) + .y1(function(d) { + return yScale(d[1]) + }) + + //添加折线 + this.group.select(".chart-line") + .attr("d", line(arr)) + .style("fill", "none") + .style("stroke-width", 1) + .style("stroke", legends[id].isGray?'none':lineColor[id]) + .style("stroke-opacity", 0.9); + if(chart._type == CHART_TYPE.AREA||chart._type == CHART_TYPE.STACK_AREA){ + let area=this.group.select(".chart-area") + .style('fill',legends[id].isGray?'none':lineColor[id]) + .style("stroke", 'none') + .style('opacity','.1') + if(state == 'single'){ + area.attr("d", areaForNormal(arr)) + }else if(state == 'multi'){ + if(chart._type == CHART_TYPE.STACK_AREA) { + area.attr("d", areaForStack(arr)) + }else { + area.attr("d", areaForNormal(arr)) + } + } + } + } +} + +export function tooltipFormatter(target,params){ + target.selectAll('div') + .data(params) + .enter() + .append('div') + .html(function(d,i){ + if(!d.legend.isGray){ + return `
+
${d.legend.alias?d.legend.alias:d.legend.name}:
+
${d.value}
+
` + } + }) +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812163442.js b/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812163442.js new file mode 100644 index 000000000..3aef91e2f --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812163442.js @@ -0,0 +1,341 @@ +import * as d3 from "d3"; +import i18n from "../../common/i18n"; +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; + +export function CHART_TYPE(){} +CHART_TYPE.LINE='line' +CHART_TYPE.AREA='area' +CHART_TYPE.STACK_AREA='stackArea' +CHART_TYPE.BAR='bar' +CHART_TYPE.STACK_BAR='stackBar' + +export function Bar(chart){ + this.group=null; + let dataset=chart.datas; + let svg=chart.svg; + let xScale=chart.xScale; + let xScale1=chart.xScale1; + let yScale=chart.yScale; + let colors=chart.colors; + let legends=chart.options.legends; + let singleFlag=legends.find(item=>{return item.isGray==true}) + let state='multi'; + let colorScale=d3.scaleOrdinal() + .domain(chart.options.height - chart._foot_height,chart._head_height) + .range(colors) + + this.init=function(index){ + /*let data=dataset.map((item,i)=>{ + return item[index]; + })*/ + let data=dataset[index] + let time=data[0][0] + let $self=this; + let timeScale=xScale(time); + if(!timeScale){ + return; + } + this.data=data; + this.group=svg.append('g').attr("clip-path","url(#"+chart._clipSelector+")") + .append('g') + .attr('transform','translate('+timeScale+',0)') + this.rects=[]; + data.forEach((d,i)=>{ + let rect=this.group.append('g').attr('fill',legends[i].isGray?'none':colors[i]) + .append('rect') + .attr('class','event-echo-unit') + .attr('y',yScale(d[1])) + .on('legend-single-show',function(){ + state='single' + let legend=chart.options.legends[i]; + let event=d3.event; + let name=event.detail?event.detail.name:"" + if(legend.name == name){ + if(chart._type == CHART_TYPE.BAR){ + rect.transition().duration(chart.options.duration) + .attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + .attr('fill',colors[i]) + }else{ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]) + .attr('height', yScale(chart.minMax.min) - yScale(d[1])) + } + + legend.isGray=false; + }else{ + if(chart._type == CHART_TYPE.BAR){ + rect.attr('fill','none').attr('x',xScale1(i)).attr('width',xScale1.bandwidth()) + }else{ + rect.attr('fill','none') + } + legend.isGray=true; + } + }) + .on('legend-all-show',function(){ + state='multi' + if(chart._type == CHART_TYPE.BAR){ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]).attr('x',xScale1(i)).attr('width',xScale1.bandwidth()) + }else{ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]) + .attr('height',function(){ + if(i==0){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + let before=data[i-1]; + return yScale(before[1]) - yScale(d[1]) + } + }) + } + chart.options.legends.forEach(item=>{item.isGray=false}) + }) + + if(chart._type==CHART_TYPE.BAR){ + rect.attr('x',xScale1 (i) ) + .attr('width',xScale1.bandwidth()==0?0.1:) + .attr('height', yScale(chart.minMax.min) - yScale(d[1])) + }else{ + rect.attr('width',xScale.bandwidth()) + .attr('height',function(){ + if(i==0){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + if(singleFlag){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + let before=data[i-1]; + return yScale(before[1]) - yScale(d[1]) + } + } + }) + } + this.rects.push(rect) + }) + } + this.scale = function(index, _duration, transform) { + if(!this.data){ + return; + } + let data=this.data; + let time=data[0][0] + let $self=this; + let timeScale=xScale(time); + + if(!timeScale){ + return; + } + if(this.group){ + this.group.attr('transform','translate('+timeScale+',0)') + if(chart._type == CHART_TYPE.BAR){ + if(state == 'single'){ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + }) + }else{ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(i)) + .attr('width',xScale1.bandwidth()) + }) + } + }else{ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + }) + } + } + } +} +export function Line(chart) { + this.group = null; + this.path = null; + let state = 'multi'//区分是显示单条还是全部显示 + let dataset=chart.datas; + let svg=chart.svg; + let xScale=chart.xScale; + let yScale=chart.yScale; + let lineColor=chart.colors; + let legends=chart.options.legends; + let singleFlag=legends.find(item=>{return item.isGray == true}) + const dispatch=chart.dispatch; + + this.init = function(id) { + let arr = dataset[id]; + let legend=chart.options.legends[id]; + this.group = svg.append("g"); + let $self=this; + let line = d3.line() + .x(function(d, i) { + return xScale(d[0]); + }) + .y(function(d) { + return yScale(d[1]); + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + + let areaForStack = d3.area() + .x(function(d, i) { + return xScale(d[0]); + }) + // .y0(chart.height - chart._foot_height) + .y0(function(d,i){ + if(id==0){ + return chart.options.height - chart._foot_height + }else{ + if(singleFlag){ + return chart.options.height - chart._foot_height + }else{ + return yScale(dataset[id-1][i][1]) + } + } + }) + .y1(function(d) { + return yScale(d[1]) + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + + let areaForNormal=d3.area() + .x(function(d, i) { + return xScale(d[0]); + }) + .y0(chart.options.height - chart._foot_height) + .y1(function(d) { + return yScale(d[1]) + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + //添加折线 + this.path = this.group.append("path") + .attr("clip-path","url(#"+chart._clipSelector+")") + .attr("d", line(arr)) + .attr('class','event-echo-unit chart-line') + .style("fill", 'none') + .style("stroke-width", 1) + .style("stroke", legends[id].isGray?'none':lineColor[id]) + .style("stroke-opacity", 0.9) + .on('legend-single-show',function(d,i,group){ + let event=d3.event; + state='single' + let name=event.detail?event.detail.name:"" + if(legend.name != name){ + $self.group + .transition() + .duration(chart.options.duration) + .style('opacity','0') + legend.isGray=true; + }else{ + $self.group.transition() + .duration(chart.options.duration).style('opacity','1') + legend.isGray=false; + if(chart.currentTransform){ + $self.scale(id,chart.options.duration,chart.currentTransform) + }else{ + $self.group.select('.chart-area').attr('d',areaForNormal(arr)) + } + } + }) + .on('legend-all-show',function(){ + let event=d3.event; + state='multi' + $self.group.transition() + .duration(chart.options.duration).style('opacity','1') + chart.options.legends.forEach(item=>{ + item.isGray=false; + }) + if(chart.currentTransform){ + $self.scale(id,chart.options.duration,chart.currentTransform) + }else{ + $self.group.select('.chart-area').attr('d',areaForStack(arr)) + } + }) + if(chart._type==CHART_TYPE.AREA||chart._type == CHART_TYPE.STACK_AREA){ + this.area=this.group.append('path') + .attr("clip-path", "url(#"+chart._clipSelector+")") + .attr('class','chart-area') + .style('fill',legends[id].isGray?'none':lineColor[id]) + .style("stroke", 'none') + .style('opacity','.1') + if(chart._type == CHART_TYPE.AREA){ + this.area.attr('d',areaForNormal(arr)) + }else{ + this.area.attr('d',areaForStack(arr)) + } + } + }; + + this.scale = function(id, _duration, transform) { + + let arr = dataset[id]; + + let line = d3.line() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y(function(d) { + return yScale(d[1]); + }) + let areaForNormal=d3.area() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y0(chart.options.height - chart._foot_height) + .y1(function(d) { + return yScale(d[1]) + }) + + let areaForStack=d3.area() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y0(function(d,i){ + if(id==0){ + return chart.options.height - chart._foot_height + }else{ + return yScale(dataset[id-1][i][1]) + } + }) + .y1(function(d) { + return yScale(d[1]) + }) + + //添加折线 + this.group.select(".chart-line") + .attr("d", line(arr)) + .style("fill", "none") + .style("stroke-width", 1) + .style("stroke", legends[id].isGray?'none':lineColor[id]) + .style("stroke-opacity", 0.9); + if(chart._type == CHART_TYPE.AREA||chart._type == CHART_TYPE.STACK_AREA){ + let area=this.group.select(".chart-area") + .style('fill',legends[id].isGray?'none':lineColor[id]) + .style("stroke", 'none') + .style('opacity','.1') + if(state == 'single'){ + area.attr("d", areaForNormal(arr)) + }else if(state == 'multi'){ + if(chart._type == CHART_TYPE.STACK_AREA) { + area.attr("d", areaForStack(arr)) + }else { + area.attr("d", areaForNormal(arr)) + } + } + } + } +} + +export function tooltipFormatter(target,params){ + target.selectAll('div') + .data(params) + .enter() + .append('div') + .html(function(d,i){ + if(!d.legend.isGray){ + return `
+
${d.legend.alias?d.legend.alias:d.legend.name}:
+
${d.value}
+
` + } + }) +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812163450.js b/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812163450.js new file mode 100644 index 000000000..8c23cf68e --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812163450.js @@ -0,0 +1,341 @@ +import * as d3 from "d3"; +import i18n from "../../common/i18n"; +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; + +export function CHART_TYPE(){} +CHART_TYPE.LINE='line' +CHART_TYPE.AREA='area' +CHART_TYPE.STACK_AREA='stackArea' +CHART_TYPE.BAR='bar' +CHART_TYPE.STACK_BAR='stackBar' + +export function Bar(chart){ + this.group=null; + let dataset=chart.datas; + let svg=chart.svg; + let xScale=chart.xScale; + let xScale1=chart.xScale1; + let yScale=chart.yScale; + let colors=chart.colors; + let legends=chart.options.legends; + let singleFlag=legends.find(item=>{return item.isGray==true}) + let state='multi'; + let colorScale=d3.scaleOrdinal() + .domain(chart.options.height - chart._foot_height,chart._head_height) + .range(colors) + + this.init=function(index){ + /*let data=dataset.map((item,i)=>{ + return item[index]; + })*/ + let data=dataset[index] + let time=data[0][0] + let $self=this; + let timeScale=xScale(time); + if(!timeScale){ + return; + } + this.data=data; + this.group=svg.append('g').attr("clip-path","url(#"+chart._clipSelector+")") + .append('g') + .attr('transform','translate('+timeScale+',0)') + this.rects=[]; + data.forEach((d,i)=>{ + let rect=this.group.append('g').attr('fill',legends[i].isGray?'none':colors[i]) + .append('rect') + .attr('class','event-echo-unit') + .attr('y',yScale(d[1])) + .on('legend-single-show',function(){ + state='single' + let legend=chart.options.legends[i]; + let event=d3.event; + let name=event.detail?event.detail.name:"" + if(legend.name == name){ + if(chart._type == CHART_TYPE.BAR){ + rect.transition().duration(chart.options.duration) + .attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + .attr('fill',colors[i]) + }else{ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]) + .attr('height', yScale(chart.minMax.min) - yScale(d[1])) + } + + legend.isGray=false; + }else{ + if(chart._type == CHART_TYPE.BAR){ + rect.attr('fill','none').attr('x',xScale1(i)).attr('width',xScale1.bandwidth()) + }else{ + rect.attr('fill','none') + } + legend.isGray=true; + } + }) + .on('legend-all-show',function(){ + state='multi' + if(chart._type == CHART_TYPE.BAR){ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]).attr('x',xScale1(i)).attr('width',xScale1.bandwidth()) + }else{ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]) + .attr('height',function(){ + if(i==0){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + let before=data[i-1]; + return yScale(before[1]) - yScale(d[1]) + } + }) + } + chart.options.legends.forEach(item=>{item.isGray=false}) + }) + + if(chart._type==CHART_TYPE.BAR){ + rect.attr('x',xScale1 (i) ) + .attr('width',xScale1.bandwidth()==0?0.1:xScale1.bandwidth()) + .attr('height', yScale(chart.minMax.min) - yScale(d[1])) + }else{ + rect.attr('width',xScale.bandwidth()) + .attr('height',function(){ + if(i==0){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + if(singleFlag){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + let before=data[i-1]; + return yScale(before[1]) - yScale(d[1]) + } + } + }) + } + this.rects.push(rect) + }) + } + this.scale = function(index, _duration, transform) { + if(!this.data){ + return; + } + let data=this.data; + let time=data[0][0] + let $self=this; + let timeScale=xScale(time); + + if(!timeScale){ + return; + } + if(this.group){ + this.group.attr('transform','translate('+timeScale+',0)') + if(chart._type == CHART_TYPE.BAR){ + if(state == 'single'){ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + }) + }else{ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(i)) + .attr('width',xScale1.bandwidth()) + }) + } + }else{ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + }) + } + } + } +} +export function Line(chart) { + this.group = null; + this.path = null; + let state = 'multi'//区分是显示单条还是全部显示 + let dataset=chart.datas; + let svg=chart.svg; + let xScale=chart.xScale; + let yScale=chart.yScale; + let lineColor=chart.colors; + let legends=chart.options.legends; + let singleFlag=legends.find(item=>{return item.isGray == true}) + const dispatch=chart.dispatch; + + this.init = function(id) { + let arr = dataset[id]; + let legend=chart.options.legends[id]; + this.group = svg.append("g"); + let $self=this; + let line = d3.line() + .x(function(d, i) { + return xScale(d[0]); + }) + .y(function(d) { + return yScale(d[1]); + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + + let areaForStack = d3.area() + .x(function(d, i) { + return xScale(d[0]); + }) + // .y0(chart.height - chart._foot_height) + .y0(function(d,i){ + if(id==0){ + return chart.options.height - chart._foot_height + }else{ + if(singleFlag){ + return chart.options.height - chart._foot_height + }else{ + return yScale(dataset[id-1][i][1]) + } + } + }) + .y1(function(d) { + return yScale(d[1]) + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + + let areaForNormal=d3.area() + .x(function(d, i) { + return xScale(d[0]); + }) + .y0(chart.options.height - chart._foot_height) + .y1(function(d) { + return yScale(d[1]) + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + //添加折线 + this.path = this.group.append("path") + .attr("clip-path","url(#"+chart._clipSelector+")") + .attr("d", line(arr)) + .attr('class','event-echo-unit chart-line') + .style("fill", 'none') + .style("stroke-width", 1) + .style("stroke", legends[id].isGray?'none':lineColor[id]) + .style("stroke-opacity", 0.9) + .on('legend-single-show',function(d,i,group){ + let event=d3.event; + state='single' + let name=event.detail?event.detail.name:"" + if(legend.name != name){ + $self.group + .transition() + .duration(chart.options.duration) + .style('opacity','0') + legend.isGray=true; + }else{ + $self.group.transition() + .duration(chart.options.duration).style('opacity','1') + legend.isGray=false; + if(chart.currentTransform){ + $self.scale(id,chart.options.duration,chart.currentTransform) + }else{ + $self.group.select('.chart-area').attr('d',areaForNormal(arr)) + } + } + }) + .on('legend-all-show',function(){ + let event=d3.event; + state='multi' + $self.group.transition() + .duration(chart.options.duration).style('opacity','1') + chart.options.legends.forEach(item=>{ + item.isGray=false; + }) + if(chart.currentTransform){ + $self.scale(id,chart.options.duration,chart.currentTransform) + }else{ + $self.group.select('.chart-area').attr('d',areaForStack(arr)) + } + }) + if(chart._type==CHART_TYPE.AREA||chart._type == CHART_TYPE.STACK_AREA){ + this.area=this.group.append('path') + .attr("clip-path", "url(#"+chart._clipSelector+")") + .attr('class','chart-area') + .style('fill',legends[id].isGray?'none':lineColor[id]) + .style("stroke", 'none') + .style('opacity','.1') + if(chart._type == CHART_TYPE.AREA){ + this.area.attr('d',areaForNormal(arr)) + }else{ + this.area.attr('d',areaForStack(arr)) + } + } + }; + + this.scale = function(id, _duration, transform) { + + let arr = dataset[id]; + + let line = d3.line() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y(function(d) { + return yScale(d[1]); + }) + let areaForNormal=d3.area() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y0(chart.options.height - chart._foot_height) + .y1(function(d) { + return yScale(d[1]) + }) + + let areaForStack=d3.area() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y0(function(d,i){ + if(id==0){ + return chart.options.height - chart._foot_height + }else{ + return yScale(dataset[id-1][i][1]) + } + }) + .y1(function(d) { + return yScale(d[1]) + }) + + //添加折线 + this.group.select(".chart-line") + .attr("d", line(arr)) + .style("fill", "none") + .style("stroke-width", 1) + .style("stroke", legends[id].isGray?'none':lineColor[id]) + .style("stroke-opacity", 0.9); + if(chart._type == CHART_TYPE.AREA||chart._type == CHART_TYPE.STACK_AREA){ + let area=this.group.select(".chart-area") + .style('fill',legends[id].isGray?'none':lineColor[id]) + .style("stroke", 'none') + .style('opacity','.1') + if(state == 'single'){ + area.attr("d", areaForNormal(arr)) + }else if(state == 'multi'){ + if(chart._type == CHART_TYPE.STACK_AREA) { + area.attr("d", areaForStack(arr)) + }else { + area.attr("d", areaForNormal(arr)) + } + } + } + } +} + +export function tooltipFormatter(target,params){ + target.selectAll('div') + .data(params) + .enter() + .append('div') + .html(function(d,i){ + if(!d.legend.isGray){ + return `
+
${d.legend.alias?d.legend.alias:d.legend.name}:
+
${d.value}
+
` + } + }) +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812163454.js b/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812163454.js new file mode 100644 index 000000000..d86786284 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812163454.js @@ -0,0 +1,341 @@ +import * as d3 from "d3"; +import i18n from "../../common/i18n"; +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; + +export function CHART_TYPE(){} +CHART_TYPE.LINE='line' +CHART_TYPE.AREA='area' +CHART_TYPE.STACK_AREA='stackArea' +CHART_TYPE.BAR='bar' +CHART_TYPE.STACK_BAR='stackBar' + +export function Bar(chart){ + this.group=null; + let dataset=chart.datas; + let svg=chart.svg; + let xScale=chart.xScale; + let xScale1=chart.xScale1; + let yScale=chart.yScale; + let colors=chart.colors; + let legends=chart.options.legends; + let singleFlag=legends.find(item=>{return item.isGray==true}) + let state='multi'; + let colorScale=d3.scaleOrdinal() + .domain(chart.options.height - chart._foot_height,chart._head_height) + .range(colors) + + this.init=function(index){ + /*let data=dataset.map((item,i)=>{ + return item[index]; + })*/ + let data=dataset[index] + let time=data[0][0] + let $self=this; + let timeScale=xScale(time); + if(!timeScale){ + return; + } + this.data=data; + this.group=svg.append('g').attr("clip-path","url(#"+chart._clipSelector+")") + .append('g') + .attr('transform','translate('+timeScale+',0)') + this.rects=[]; + data.forEach((d,i)=>{ + let rect=this.group.append('g').attr('fill',legends[i].isGray?'none':colors[i]) + .append('rect') + .attr('class','event-echo-unit') + .attr('y',yScale(d[1])) + .on('legend-single-show',function(){ + state='single' + let legend=chart.options.legends[i]; + let event=d3.event; + let name=event.detail?event.detail.name:"" + if(legend.name == name){ + if(chart._type == CHART_TYPE.BAR){ + rect.transition().duration(chart.options.duration) + .attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + .attr('fill',colors[i]) + }else{ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]) + .attr('height', yScale(chart.minMax.min) - yScale(d[1])) + } + + legend.isGray=false; + }else{ + if(chart._type == CHART_TYPE.BAR){ + rect.attr('fill','none').attr('x',xScale1(i)).attr('width',xScale1.bandwidth()) + }else{ + rect.attr('fill','none') + } + legend.isGray=true; + } + }) + .on('legend-all-show',function(){ + state='multi' + if(chart._type == CHART_TYPE.BAR){ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]).attr('x',xScale1(i)).attr('width',xScale1.bandwidth()) + }else{ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]) + .attr('height',function(){ + if(i==0){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + let before=data[i-1]; + return yScale(before[1]) - yScale(d[1]) + } + }) + } + chart.options.legends.forEach(item=>{item.isGray=false}) + }) + + if(chart._type==CHART_TYPE.BAR){ + rect.attr('x',xScale1 (i) ) + .attr('width',xScale1.bandwidth()<=0?0.1:xScale1.bandwidth()) + .attr('height', yScale(chart.minMax.min) - yScale(d[1])) + }else{ + rect.attr('width',xScale.bandwidth()) + .attr('height',function(){ + if(i==0){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + if(singleFlag){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + let before=data[i-1]; + return yScale(before[1]) - yScale(d[1]) + } + } + }) + } + this.rects.push(rect) + }) + } + this.scale = function(index, _duration, transform) { + if(!this.data){ + return; + } + let data=this.data; + let time=data[0][0] + let $self=this; + let timeScale=xScale(time); + + if(!timeScale){ + return; + } + if(this.group){ + this.group.attr('transform','translate('+timeScale+',0)') + if(chart._type == CHART_TYPE.BAR){ + if(state == 'single'){ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + }) + }else{ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(i)) + .attr('width',xScale1.bandwidth()) + }) + } + }else{ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + }) + } + } + } +} +export function Line(chart) { + this.group = null; + this.path = null; + let state = 'multi'//区分是显示单条还是全部显示 + let dataset=chart.datas; + let svg=chart.svg; + let xScale=chart.xScale; + let yScale=chart.yScale; + let lineColor=chart.colors; + let legends=chart.options.legends; + let singleFlag=legends.find(item=>{return item.isGray == true}) + const dispatch=chart.dispatch; + + this.init = function(id) { + let arr = dataset[id]; + let legend=chart.options.legends[id]; + this.group = svg.append("g"); + let $self=this; + let line = d3.line() + .x(function(d, i) { + return xScale(d[0]); + }) + .y(function(d) { + return yScale(d[1]); + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + + let areaForStack = d3.area() + .x(function(d, i) { + return xScale(d[0]); + }) + // .y0(chart.height - chart._foot_height) + .y0(function(d,i){ + if(id==0){ + return chart.options.height - chart._foot_height + }else{ + if(singleFlag){ + return chart.options.height - chart._foot_height + }else{ + return yScale(dataset[id-1][i][1]) + } + } + }) + .y1(function(d) { + return yScale(d[1]) + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + + let areaForNormal=d3.area() + .x(function(d, i) { + return xScale(d[0]); + }) + .y0(chart.options.height - chart._foot_height) + .y1(function(d) { + return yScale(d[1]) + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + //添加折线 + this.path = this.group.append("path") + .attr("clip-path","url(#"+chart._clipSelector+")") + .attr("d", line(arr)) + .attr('class','event-echo-unit chart-line') + .style("fill", 'none') + .style("stroke-width", 1) + .style("stroke", legends[id].isGray?'none':lineColor[id]) + .style("stroke-opacity", 0.9) + .on('legend-single-show',function(d,i,group){ + let event=d3.event; + state='single' + let name=event.detail?event.detail.name:"" + if(legend.name != name){ + $self.group + .transition() + .duration(chart.options.duration) + .style('opacity','0') + legend.isGray=true; + }else{ + $self.group.transition() + .duration(chart.options.duration).style('opacity','1') + legend.isGray=false; + if(chart.currentTransform){ + $self.scale(id,chart.options.duration,chart.currentTransform) + }else{ + $self.group.select('.chart-area').attr('d',areaForNormal(arr)) + } + } + }) + .on('legend-all-show',function(){ + let event=d3.event; + state='multi' + $self.group.transition() + .duration(chart.options.duration).style('opacity','1') + chart.options.legends.forEach(item=>{ + item.isGray=false; + }) + if(chart.currentTransform){ + $self.scale(id,chart.options.duration,chart.currentTransform) + }else{ + $self.group.select('.chart-area').attr('d',areaForStack(arr)) + } + }) + if(chart._type==CHART_TYPE.AREA||chart._type == CHART_TYPE.STACK_AREA){ + this.area=this.group.append('path') + .attr("clip-path", "url(#"+chart._clipSelector+")") + .attr('class','chart-area') + .style('fill',legends[id].isGray?'none':lineColor[id]) + .style("stroke", 'none') + .style('opacity','.1') + if(chart._type == CHART_TYPE.AREA){ + this.area.attr('d',areaForNormal(arr)) + }else{ + this.area.attr('d',areaForStack(arr)) + } + } + }; + + this.scale = function(id, _duration, transform) { + + let arr = dataset[id]; + + let line = d3.line() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y(function(d) { + return yScale(d[1]); + }) + let areaForNormal=d3.area() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y0(chart.options.height - chart._foot_height) + .y1(function(d) { + return yScale(d[1]) + }) + + let areaForStack=d3.area() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y0(function(d,i){ + if(id==0){ + return chart.options.height - chart._foot_height + }else{ + return yScale(dataset[id-1][i][1]) + } + }) + .y1(function(d) { + return yScale(d[1]) + }) + + //添加折线 + this.group.select(".chart-line") + .attr("d", line(arr)) + .style("fill", "none") + .style("stroke-width", 1) + .style("stroke", legends[id].isGray?'none':lineColor[id]) + .style("stroke-opacity", 0.9); + if(chart._type == CHART_TYPE.AREA||chart._type == CHART_TYPE.STACK_AREA){ + let area=this.group.select(".chart-area") + .style('fill',legends[id].isGray?'none':lineColor[id]) + .style("stroke", 'none') + .style('opacity','.1') + if(state == 'single'){ + area.attr("d", areaForNormal(arr)) + }else if(state == 'multi'){ + if(chart._type == CHART_TYPE.STACK_AREA) { + area.attr("d", areaForStack(arr)) + }else { + area.attr("d", areaForNormal(arr)) + } + } + } + } +} + +export function tooltipFormatter(target,params){ + target.selectAll('div') + .data(params) + .enter() + .append('div') + .html(function(d,i){ + if(!d.legend.isGray){ + return `
+
${d.legend.alias?d.legend.alias:d.legend.name}:
+
${d.value}
+
` + } + }) +} diff --git a/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812163725.js b/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812163725.js new file mode 100644 index 000000000..c6de62b18 --- /dev/null +++ b/.history/nezha-fronted/src/components/charts/d3/d3Util_20200812163725.js @@ -0,0 +1,341 @@ +import * as d3 from "d3"; +import i18n from "../../common/i18n"; +import {randomcolor} from "../../common/js/radomcolor/randomcolor"; + +export function CHART_TYPE(){} +CHART_TYPE.LINE='line' +CHART_TYPE.AREA='area' +CHART_TYPE.STACK_AREA='stackArea' +CHART_TYPE.BAR='bar' +CHART_TYPE.STACK_BAR='stackBar' + +export function Bar(chart){ + this.group=null; + let dataset=chart.datas; + let svg=chart.svg; + let xScale=chart.xScale; + let xScale1=chart.xScale1; + let yScale=chart.yScale; + let colors=chart.colors; + let legends=chart.options.legends; + let singleFlag=legends.find(item=>{return item.isGray==true}) + let state='multi'; + let colorScale=d3.scaleOrdinal() + .domain(chart.options.height - chart._foot_height,chart._head_height) + .range(colors) + + this.init=function(index){ + /*let data=dataset.map((item,i)=>{ + return item[index]; + })*/ + let data=dataset[index] + let time=data[0][0] + let $self=this; + let timeScale=xScale(time); + if(!timeScale){ + return; + } + this.data=data; + this.group=svg.append('g').attr("clip-path","url(#"+chart._clipSelector+")") + .append('g') + .attr('transform','translate('+timeScale+',0)') + this.rects=[]; + data.forEach((d,i)=>{ + let rect=this.group.append('g').attr('fill',legends[i].isGray?'none':colors[i]) + .append('rect') + .attr('class','event-echo-unit') + .attr('y',yScale(d[1])) + .on('legend-single-show',function(){ + state='single' + let legend=chart.options.legends[i]; + let event=d3.event; + let name=event.detail?event.detail.name:"" + if(legend.name == name){ + if(chart._type == CHART_TYPE.BAR){ + rect.transition().duration(chart.options.duration) + .attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + .attr('fill',colors[i]) + }else{ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]) + .attr('height', yScale(chart.minMax.min) - yScale(d[1])) + } + + legend.isGray=false; + }else{ + if(chart._type == CHART_TYPE.BAR){ + rect.attr('fill','none').attr('x',xScale1(i)).attr('width',xScale1.bandwidth()) + }else{ + rect.attr('fill','none') + } + legend.isGray=true; + } + }) + .on('legend-all-show',function(){ + state='multi' + if(chart._type == CHART_TYPE.BAR){ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]).attr('x',xScale1(i)).attr('width',xScale1.bandwidth()) + }else{ + rect.transition().duration(chart.options.duration) + .attr('fill',colors[i]) + .attr('height',function(){ + if(i==0){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + let before=data[i-1]; + return yScale(before[1]) - yScale(d[1]) + } + }) + } + chart.options.legends.forEach(item=>{item.isGray=false}) + }) + + if(chart._type==CHART_TYPE.BAR){ + rect.attr('x',xScale1 (i) ) + .attr('width',xScale1.bandwidth()<=0?0.1:xScale1.bandwidth()) + .attr('height', yScale(chart.minMax.min) - yScale(d[1])) + }else{ + rect.attr('width',xScale.bandwidth()) + .attr('height',function(){ + if(i==0){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + if(singleFlag){ + return yScale(chart.minMax.min) - yScale(d[1]) + }else{ + let before=data[i-1]; + return yScale(before[1]) - yScale(d[1]) + } + } + }) + } + this.rects.push(rect) + }) + } + this.scale = function(index, _duration, transform) { + if(!this.data){ + return; + } + let data=this.data; + let time=data[0][0] + let $self=this; + let timeScale=xScale(time); + + if(!timeScale){ + return; + } + if(this.group){ + this.group.attr('transform','translate('+timeScale+',0)') + if(chart._type == CHART_TYPE.BAR){ + if(state == 'single'){ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + }) + }else{ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(i)) + .attr('width',xScale1.bandwidth()<=0?0.1:xScale1.bandwidth()) + }) + } + }else{ + this.rects.forEach((rect,i)=>{ + rect.attr('x',xScale1(0)) + .attr('width',xScale.bandwidth()) + }) + } + } + } +} +export function Line(chart) { + this.group = null; + this.path = null; + let state = 'multi'//区分是显示单条还是全部显示 + let dataset=chart.datas; + let svg=chart.svg; + let xScale=chart.xScale; + let yScale=chart.yScale; + let lineColor=chart.colors; + let legends=chart.options.legends; + let singleFlag=legends.find(item=>{return item.isGray == true}) + const dispatch=chart.dispatch; + + this.init = function(id) { + let arr = dataset[id]; + let legend=chart.options.legends[id]; + this.group = svg.append("g"); + let $self=this; + let line = d3.line() + .x(function(d, i) { + return xScale(d[0]); + }) + .y(function(d) { + return yScale(d[1]); + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + + let areaForStack = d3.area() + .x(function(d, i) { + return xScale(d[0]); + }) + // .y0(chart.height - chart._foot_height) + .y0(function(d,i){ + if(id==0){ + return chart.options.height - chart._foot_height + }else{ + if(singleFlag){ + return chart.options.height - chart._foot_height + }else{ + return yScale(dataset[id-1][i][1]) + } + } + }) + .y1(function(d) { + return yScale(d[1]) + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + + let areaForNormal=d3.area() + .x(function(d, i) { + return xScale(d[0]); + }) + .y0(chart.options.height - chart._foot_height) + .y1(function(d) { + return yScale(d[1]) + }) + .curve(d3.curveCatmullRom.alpha(0.3)); //折线曲度 + //添加折线 + this.path = this.group.append("path") + .attr("clip-path","url(#"+chart._clipSelector+")") + .attr("d", line(arr)) + .attr('class','event-echo-unit chart-line') + .style("fill", 'none') + .style("stroke-width", 1) + .style("stroke", legends[id].isGray?'none':lineColor[id]) + .style("stroke-opacity", 0.9) + .on('legend-single-show',function(d,i,group){ + let event=d3.event; + state='single' + let name=event.detail?event.detail.name:"" + if(legend.name != name){ + $self.group + .transition() + .duration(chart.options.duration) + .style('opacity','0') + legend.isGray=true; + }else{ + $self.group.transition() + .duration(chart.options.duration).style('opacity','1') + legend.isGray=false; + if(chart.currentTransform){ + $self.scale(id,chart.options.duration,chart.currentTransform) + }else{ + $self.group.select('.chart-area').attr('d',areaForNormal(arr)) + } + } + }) + .on('legend-all-show',function(){ + let event=d3.event; + state='multi' + $self.group.transition() + .duration(chart.options.duration).style('opacity','1') + chart.options.legends.forEach(item=>{ + item.isGray=false; + }) + if(chart.currentTransform){ + $self.scale(id,chart.options.duration,chart.currentTransform) + }else{ + $self.group.select('.chart-area').attr('d',areaForStack(arr)) + } + }) + if(chart._type==CHART_TYPE.AREA||chart._type == CHART_TYPE.STACK_AREA){ + this.area=this.group.append('path') + .attr("clip-path", "url(#"+chart._clipSelector+")") + .attr('class','chart-area') + .style('fill',legends[id].isGray?'none':lineColor[id]) + .style("stroke", 'none') + .style('opacity','.1') + if(chart._type == CHART_TYPE.AREA){ + this.area.attr('d',areaForNormal(arr)) + }else{ + this.area.attr('d',areaForStack(arr)) + } + } + }; + + this.scale = function(id, _duration, transform) { + + let arr = dataset[id]; + + let line = d3.line() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y(function(d) { + return yScale(d[1]); + }) + let areaForNormal=d3.area() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y0(chart.options.height - chart._foot_height) + .y1(function(d) { + return yScale(d[1]) + }) + + let areaForStack=d3.area() + .x(function(d, i) { + return transform.applyX(xScale(d[0])) + }) + .y0(function(d,i){ + if(id==0){ + return chart.options.height - chart._foot_height + }else{ + return yScale(dataset[id-1][i][1]) + } + }) + .y1(function(d) { + return yScale(d[1]) + }) + + //添加折线 + this.group.select(".chart-line") + .attr("d", line(arr)) + .style("fill", "none") + .style("stroke-width", 1) + .style("stroke", legends[id].isGray?'none':lineColor[id]) + .style("stroke-opacity", 0.9); + if(chart._type == CHART_TYPE.AREA||chart._type == CHART_TYPE.STACK_AREA){ + let area=this.group.select(".chart-area") + .style('fill',legends[id].isGray?'none':lineColor[id]) + .style("stroke", 'none') + .style('opacity','.1') + if(state == 'single'){ + area.attr("d", areaForNormal(arr)) + }else if(state == 'multi'){ + if(chart._type == CHART_TYPE.STACK_AREA) { + area.attr("d", areaForStack(arr)) + }else { + area.attr("d", areaForNormal(arr)) + } + } + } + } +} + +export function tooltipFormatter(target,params){ + target.selectAll('div') + .data(params) + .enter() + .append('div') + .html(function(d,i){ + if(!d.legend.isGray){ + return `
+
${d.legend.alias?d.legend.alias:d.legend.name}:
+
${d.value}
+
` + } + }) +} diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200915192236.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200915192236.vue new file mode 100644 index 000000000..5883df0c5 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200915192236.vue @@ -0,0 +1,746 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916094704.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916094704.vue new file mode 100644 index 000000000..d549150f5 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916094704.vue @@ -0,0 +1,746 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916094813.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916094813.vue new file mode 100644 index 000000000..d324ec8da --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916094813.vue @@ -0,0 +1,746 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095123.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095123.vue new file mode 100644 index 000000000..ad2111118 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095123.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095129.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095129.vue new file mode 100644 index 000000000..90b2dc8e7 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095129.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095131.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095131.vue new file mode 100644 index 000000000..f0347a0b9 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095131.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095134.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095134.vue new file mode 100644 index 000000000..4084cd7ea --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095134.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095136.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095136.vue new file mode 100644 index 000000000..b0d95ea10 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095136.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095139.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095139.vue new file mode 100644 index 000000000..8e9cd308a --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095139.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095141.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095141.vue new file mode 100644 index 000000000..425e8f69e --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095141.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095151.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095151.vue new file mode 100644 index 000000000..dd2e6c0fb --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095151.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095156.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095156.vue new file mode 100644 index 000000000..e76564de4 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095156.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095202.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095202.vue new file mode 100644 index 000000000..f3781024d --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095202.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095205.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095205.vue new file mode 100644 index 000000000..50bc19db6 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095205.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095211.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095211.vue new file mode 100644 index 000000000..49a22bc76 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095211.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095214.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095214.vue new file mode 100644 index 000000000..49a22bc76 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095214.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095353.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095353.vue new file mode 100644 index 000000000..66bd35b43 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095353.vue @@ -0,0 +1,750 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095941.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095941.vue new file mode 100644 index 000000000..cbcdb8e56 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095941.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095943.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095943.vue new file mode 100644 index 000000000..0f9213b4f --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095943.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916095947.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916095947.vue new file mode 100644 index 000000000..7c38c27c1 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916095947.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916100004.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916100004.vue new file mode 100644 index 000000000..945231662 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916100004.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916100006.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916100006.vue new file mode 100644 index 000000000..5640db6df --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916100006.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916100007.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916100007.vue new file mode 100644 index 000000000..df9765350 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916100007.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916100014.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916100014.vue new file mode 100644 index 000000000..10253cfc2 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916100014.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916100015.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916100015.vue new file mode 100644 index 000000000..10253cfc2 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916100015.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916100210.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916100210.vue new file mode 100644 index 000000000..4bfa918fb --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916100210.vue @@ -0,0 +1,751 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916100228.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916100228.vue new file mode 100644 index 000000000..21f6c1896 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916100228.vue @@ -0,0 +1,752 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916100233.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916100233.vue new file mode 100644 index 000000000..63152493b --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916100233.vue @@ -0,0 +1,752 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916100234.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916100234.vue new file mode 100644 index 000000000..ded122002 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916100234.vue @@ -0,0 +1,752 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916100237.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916100237.vue new file mode 100644 index 000000000..cb0127d53 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916100237.vue @@ -0,0 +1,752 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916100240.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916100240.vue new file mode 100644 index 000000000..dddeb4f6d --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916100240.vue @@ -0,0 +1,752 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916100241.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916100241.vue new file mode 100644 index 000000000..80e36f606 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916100241.vue @@ -0,0 +1,752 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916100243.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916100243.vue new file mode 100644 index 000000000..c7a4fbb57 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916100243.vue @@ -0,0 +1,752 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916100422.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916100422.vue new file mode 100644 index 000000000..096ace504 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916100422.vue @@ -0,0 +1,752 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/common/leftMenu_20200916100606.vue b/.history/nezha-fronted/src/components/common/leftMenu_20200916100606.vue new file mode 100644 index 000000000..a0b5818f2 --- /dev/null +++ b/.history/nezha-fronted/src/components/common/leftMenu_20200916100606.vue @@ -0,0 +1,752 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/page/asset/assetAddUnit_20200109174241.vue b/.history/nezha-fronted/src/components/page/asset/assetAddUnit_20200109174241.vue new file mode 100644 index 000000000..948dc4a5f --- /dev/null +++ b/.history/nezha-fronted/src/components/page/asset/assetAddUnit_20200109174241.vue @@ -0,0 +1,1479 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/asset/assetAddUnit_20200110100141.vue b/.history/nezha-fronted/src/components/page/asset/assetAddUnit_20200110100141.vue new file mode 100644 index 000000000..52bc802ab --- /dev/null +++ b/.history/nezha-fronted/src/components/page/asset/assetAddUnit_20200110100141.vue @@ -0,0 +1,1479 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/asset/asset_20200915191245.vue b/.history/nezha-fronted/src/components/page/asset/asset_20200915191245.vue new file mode 100644 index 000000000..36f3a8bc3 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/asset/asset_20200915191245.vue @@ -0,0 +1,793 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/asset/asset_20200916095227.vue b/.history/nezha-fronted/src/components/page/asset/asset_20200916095227.vue new file mode 100644 index 000000000..27ac1b420 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/asset/asset_20200916095227.vue @@ -0,0 +1,792 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191454.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191454.vue new file mode 100644 index 000000000..d498fff9a --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191454.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191738.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191738.vue new file mode 100644 index 000000000..a17a47641 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191738.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191743.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191743.vue new file mode 100644 index 000000000..c3f454b84 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191743.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191745.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191745.vue new file mode 100644 index 000000000..804f88527 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191745.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191751.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191751.vue new file mode 100644 index 000000000..80fa0a32b --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191751.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191754.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191754.vue new file mode 100644 index 000000000..5b419694b --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191754.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191806.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191806.vue new file mode 100644 index 000000000..c1b868fd3 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191806.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191810.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191810.vue new file mode 100644 index 000000000..e2a5226e6 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191810.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191811.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191811.vue new file mode 100644 index 000000000..8126b90f2 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191811.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191813.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191813.vue new file mode 100644 index 000000000..99cb7362f --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191813.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191814.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191814.vue new file mode 100644 index 000000000..03ba3a692 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191814.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191815.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191815.vue new file mode 100644 index 000000000..ccbb60916 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191815.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191824.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191824.vue new file mode 100644 index 000000000..c01c9eaa0 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191824.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191843.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191843.vue new file mode 100644 index 000000000..0a4e6ce94 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191843.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191846.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191846.vue new file mode 100644 index 000000000..4c9399381 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191846.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191856.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191856.vue new file mode 100644 index 000000000..b67a850f9 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191856.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191859.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191859.vue new file mode 100644 index 000000000..4c9399381 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191859.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191912.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191912.vue new file mode 100644 index 000000000..2c88cd127 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191912.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191914.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191914.vue new file mode 100644 index 000000000..fd6311334 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191914.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191918.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191918.vue new file mode 100644 index 000000000..0c684ae50 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191918.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191921.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191921.vue new file mode 100644 index 000000000..0c684ae50 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609191921.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192625.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192625.vue new file mode 100644 index 000000000..06a7c9286 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192625.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192834.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192834.vue new file mode 100644 index 000000000..1e6dd855b --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192834.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192842.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192842.vue new file mode 100644 index 000000000..1e6dd855b --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192842.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192844.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192844.vue new file mode 100644 index 000000000..be1b187be --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192844.vue @@ -0,0 +1,49 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192851.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192851.vue new file mode 100644 index 000000000..2151fb843 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192851.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192855.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192855.vue new file mode 100644 index 000000000..a5d568912 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192855.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192858.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192858.vue new file mode 100644 index 000000000..1c953a619 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192858.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192901.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192901.vue new file mode 100644 index 000000000..eb4e67157 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192901.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192904.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192904.vue new file mode 100644 index 000000000..0babd209a --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192904.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192912.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192912.vue new file mode 100644 index 000000000..932a1e517 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192912.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192937.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192937.vue new file mode 100644 index 000000000..791b65b5c --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192937.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192939.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192939.vue new file mode 100644 index 000000000..c80a1556b --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192939.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192944.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192944.vue new file mode 100644 index 000000000..881f6e01c --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192944.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192947.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192947.vue new file mode 100644 index 000000000..0e2e96e0c --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192947.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192950.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192950.vue new file mode 100644 index 000000000..6697ed5fb --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192950.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192952.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192952.vue new file mode 100644 index 000000000..522f009b5 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192952.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192958.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192958.vue new file mode 100644 index 000000000..17fd9c4b1 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609192958.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193000.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193000.vue new file mode 100644 index 000000000..70987f448 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193000.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193043.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193043.vue new file mode 100644 index 000000000..afa76748c --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193043.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193046.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193046.vue new file mode 100644 index 000000000..c3a598c2d --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193046.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193135.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193135.vue new file mode 100644 index 000000000..a945257ad --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193135.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193147.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193147.vue new file mode 100644 index 000000000..17fd9c4b1 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193147.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193151.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193151.vue new file mode 100644 index 000000000..0a189371c --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193151.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193154.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193154.vue new file mode 100644 index 000000000..aa2911ef4 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193154.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193155.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193155.vue new file mode 100644 index 000000000..eb6d0f82f --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193155.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193226.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193226.vue new file mode 100644 index 000000000..aa2b499e4 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193226.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193234.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193234.vue new file mode 100644 index 000000000..eb6d0f82f --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193234.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193235.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193235.vue new file mode 100644 index 000000000..eb6d0f82f --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193235.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193244.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193244.vue new file mode 100644 index 000000000..9cbc18e8b --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193244.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193250.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193250.vue new file mode 100644 index 000000000..8347e8e82 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193250.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193254.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193254.vue new file mode 100644 index 000000000..d9df9b2c2 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193254.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193338.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193338.vue new file mode 100644 index 000000000..289aa192f --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193338.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193343.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193343.vue new file mode 100644 index 000000000..e15c4f021 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193343.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193344.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193344.vue new file mode 100644 index 000000000..38287b6d9 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193344.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193350.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193350.vue new file mode 100644 index 000000000..b70d9c8c0 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193350.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193352.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193352.vue new file mode 100644 index 000000000..5898d33cd --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193352.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193354.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193354.vue new file mode 100644 index 000000000..248e131d6 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193354.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193355.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193355.vue new file mode 100644 index 000000000..f18866056 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193355.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193357.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193357.vue new file mode 100644 index 000000000..afe3e8013 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193357.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193358.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193358.vue new file mode 100644 index 000000000..bcd277059 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193358.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193400.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193400.vue new file mode 100644 index 000000000..58aaa34a9 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193400.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193405.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193405.vue new file mode 100644 index 000000000..58aaa34a9 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193405.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193408.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193408.vue new file mode 100644 index 000000000..07357e5ed --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193408.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193410.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193410.vue new file mode 100644 index 000000000..063050c2a --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193410.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193413.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193413.vue new file mode 100644 index 000000000..da9e433b1 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193413.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193416.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193416.vue new file mode 100644 index 000000000..22f8ec019 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193416.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193438.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193438.vue new file mode 100644 index 000000000..9dad40a71 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193438.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193443.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193443.vue new file mode 100644 index 000000000..737d2cd38 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193443.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193448.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193448.vue new file mode 100644 index 000000000..f1b943a51 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193448.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193451.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193451.vue new file mode 100644 index 000000000..dd0b437a2 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193451.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193452.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193452.vue new file mode 100644 index 000000000..e3276f94b --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193452.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193455.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193455.vue new file mode 100644 index 000000000..a8deafb03 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193455.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193515.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193515.vue new file mode 100644 index 000000000..99a31b293 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193515.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193520.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193520.vue new file mode 100644 index 000000000..94f82db77 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193520.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193521.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193521.vue new file mode 100644 index 000000000..8b77b0666 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193521.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193548.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193548.vue new file mode 100644 index 000000000..c553e9833 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193548.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193616.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193616.vue new file mode 100644 index 000000000..2a0d9f08a --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193616.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193618.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193618.vue new file mode 100644 index 000000000..1bcde94dd --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193618.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193622.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193622.vue new file mode 100644 index 000000000..118c1768d --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193622.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193627.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193627.vue new file mode 100644 index 000000000..4830d9e9c --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193627.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193707.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193707.vue new file mode 100644 index 000000000..0ee23d6eb --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193707.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193709.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193709.vue new file mode 100644 index 000000000..0ee23d6eb --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193709.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193744.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193744.vue new file mode 100644 index 000000000..bffdef4a0 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193744.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193750.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193750.vue new file mode 100644 index 000000000..5e2270685 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193750.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193753.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193753.vue new file mode 100644 index 000000000..f542663b4 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193753.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193754.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193754.vue new file mode 100644 index 000000000..fc71bd416 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609193754.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609194242.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609194242.vue new file mode 100644 index 000000000..41e2b2fc7 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609194242.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609194244.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609194244.vue new file mode 100644 index 000000000..ded9e9768 --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200609194244.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200622181933.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200622181933.vue new file mode 100644 index 000000000..5a181166a --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200622181933.vue @@ -0,0 +1,854 @@ + + + + + + diff --git a/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200622182033.vue b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200622182033.vue new file mode 100644 index 000000000..fdc2406dc --- /dev/null +++ b/.history/nezha-fronted/src/components/page/dashboard/explore/editor_20200622182033.vue @@ -0,0 +1,841 @@ + + + + + + diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 000000000..e7e9d11d4 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,2 @@ +# Default ignored files +/workspace.xml diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 000000000..28a804d89 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 000000000..382ade5b5 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/nezha-fronted.iml b/.idea/nezha-fronted.iml new file mode 100644 index 000000000..c956989b2 --- /dev/null +++ b/.idea/nezha-fronted.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..94a25f7f4 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/nezha-fronted/src/components/common/exportXLSX.vue b/nezha-fronted/src/components/common/exportXLSX.vue index 351e221ac..4723a3cbd 100644 --- a/nezha-fronted/src/components/common/exportXLSX.vue +++ b/nezha-fronted/src/components/common/exportXLSX.vue @@ -135,6 +135,8 @@ url = "/endpoint/cancelImport"; } else if (this.importUrl.indexOf("rule") > -1) { url = "/alert/rule/cancelImport"; + } else if(this.importUrl.indexOf("panel") > -1){ + url = "/panel/cancelImport"; } this.$delete(url + '?seq='+this.importResult.seq).then(response=>{ if(response.code == 200 ){ @@ -186,6 +188,8 @@ url = "/asset/template"; } else if (this.importUrl.indexOf("rule") > -1) { url = "/alert/rule/template"; + } else if (this.importUrl.indexOf('panel') > -1){ + url = "/panel/template"; } let param={language:language} diff --git a/nezha-fronted/src/components/common/leftMenu.vue b/nezha-fronted/src/components/common/leftMenu.vue index 3c7f1f554..a0b5818f2 100644 --- a/nezha-fronted/src/components/common/leftMenu.vue +++ b/nezha-fronted/src/components/common/leftMenu.vue @@ -106,7 +106,7 @@ Tag - + @@ -538,11 +538,6 @@ return "--"; } }, - flushData() { - Promise.all([this.getLeftMenuList()]).then(response => { - this.getTableData(); - }); - }, closeAllPop() { this.$refs.idcConfigBox.forEach((item) => { item.show(false); @@ -624,31 +619,18 @@ this.$set(this.searchLabel, "orderBy", orderBy); this.getTableData(); }, - // 获取左侧菜单数据 - getLeftMenuList(){ - return new Promise(resolve => { - this.$get('asset/filter').then(response => { - if (response.code === 200) { - //dc - this.dcData = response.data.dc; - // AssetType - this.assetTypeData = response.data.assetType; - // vendor - this.vendorData = response.data.vendor; - // ping - this.pingData = response.data.ping.map(item => { - item.label = item.name; - item.value = item.status; - return item; - }); - } - resolve(); - }); - }); - }, initEvent() { bus.$on("asset-filter-change", (column, content) => { - this.pageObj[column] = content; + if(column == 'multiParam'){ + let $self=this; + if(content instanceof Array && content.length>0){ + content.forEach(item=>{ + $self.pageObj[item.key] = item.value; + }) + } + }else{ + this.pageObj[column] = content; + } this.getTableData(); }); }, diff --git a/nezha-fronted/src/components/page/config/util.vue b/nezha-fronted/src/components/page/config/util.vue new file mode 100644 index 000000000..0c0e6d088 --- /dev/null +++ b/nezha-fronted/src/components/page/config/util.vue @@ -0,0 +1,60 @@ + + diff --git a/nezha-fronted/src/components/page/dashboard/panel.vue b/nezha-fronted/src/components/page/dashboard/panel.vue index dbc4bc4a1..d67f0dbb7 100644 --- a/nezha-fronted/src/components/page/dashboard/panel.vue +++ b/nezha-fronted/src/components/page/dashboard/panel.vue @@ -50,10 +50,20 @@ - + + + @@ -83,6 +93,7 @@ import timePicker from '../../common/timePicker' import draggable from 'vuedraggable' import pickTime from "../../common/pickTime"; + import exportXLSX from "../../common/exportXLSX"; export default { name: "panel", data() { @@ -162,6 +173,7 @@ 'time-picker':timePicker, draggable, 'pick-time':pickTime, + 'export-excel':exportXLSX, }, methods: { //刷新 diff --git a/nezha-fronted/static/ueditor-1.4.3.3/.editorconfig b/nezha-fronted/static/ueditor-1.4.3.3/.editorconfig new file mode 100644 index 000000000..fa31fcbec --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/.editorconfig @@ -0,0 +1,16 @@ +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 + +[*.{html,js,css,scss,xml}] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[*.yml] +indent_style = space +indent_size = 2 \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/.gitignore b/nezha-fronted/static/ueditor-1.4.3.3/.gitignore new file mode 100644 index 000000000..8260c4f7d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/.gitignore @@ -0,0 +1,192 @@ +############### +# folder # +############### +.idea +log +jsp/upload +php/upload +net/upload +asp/upload +node/upload + + +############### +# fixed file # +############### +*.pptx +*.doc +*.docx +*.xml + + + + + + + + + + +################# +## Eclipse +################# + +*.pydevproject +.project +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + + +################# +## Visual Studio +################# + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Rr]elease/ +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.vspscc +.builds +*.dotCover + +## TODO: If you have NuGet Package Restore enabled, uncomment this +#packages/ + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf + +# Visual Studio profiler +*.psess +*.vsp + +# ReSharper is a .NET coding add-in +_ReSharper* + +# Installshield output folder +[Ee]xpress + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish + +# Others +[Bb]in +[Oo]bj +sql +TestResults +*.Cache +ClientBin +stylecop.* +~$* +*.dbmdl +Generated_Code #added for RIA/Silverlight projects + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML + + + +############ +## Windows +############ + +# Windows image file caches +Thumbs.db + +# Folder config file +Desktop.ini + + +############# +## Python +############# + +*.py[co] + +# Packages +*.egg +*.egg-info +dist +eggs +parts +# bin +var +sdist +develop-eggs +.installed.cfg + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox + +#Translations +*.mo + +#Mr Developer +.mr.developer.cfg + +# Mac crap +.DS_Store +/node_modules diff --git a/nezha-fronted/static/ueditor-1.4.3.3/Gruntfile.js b/nezha-fronted/static/ueditor-1.4.3.3/Gruntfile.js new file mode 100644 index 000000000..ff2cf9eaa --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/Gruntfile.js @@ -0,0 +1,272 @@ +'use strict'; + +module.exports = function (grunt) { + + var fs = require("fs"), + Util = { + + jsBasePath: '_src/', + parseBasePath: '_parse/', + cssBasePath: 'themes/default/_css/', + + fetchScripts: function (readFile, basePath) { + + var sources = fs.readFileSync(readFile); + sources = /\[([^\]]+\.js'[^\]]+)\]/.exec(sources); + sources = sources[1].replace(/\/\/.*\n/g, '\n').replace(/'|"|\n|\t|\s/g, ''); + sources = sources.split(","); + sources.forEach(function (filepath, index) { + sources[ index ] = basePath + filepath; + }); + + return sources; + }, + + fetchStyles: function () { + + var sources = fs.readFileSync(this.cssBasePath + "ueditor.css"), + filepath = null, + pattern = /@import\s+([^;]+)*;/g, + src = []; + + while (filepath = pattern.exec(sources)) { + src.push(this.cssBasePath + filepath[ 1 ].replace(/'|"/g, "")); + } + + return src; + + } + + }, + packageJson = grunt.file.readJSON('package.json'), + server = grunt.option('server') || 'php', + encode = grunt.option('encode') || 'utf8', + disDir = "dist/", + banner = '/*!\n * UEditor\n * version: ' + packageJson.name + '\n * build: <%= new Date() %>\n */\n\n'; + + //init + (function () { + + server = typeof server === "string" ? server.toLowerCase() : 'php'; + encode = typeof encode === "string" ? encode.toLowerCase() : 'utf8'; + + disDir = 'dist/' + encode + '-' + server + '/'; + + })(); + + grunt.initConfig({ + pkg: packageJson, + concat: { + js: { + options: { + banner: banner + '(function(){\n\n', + footer: '\n\n})();\n', + process: function (src, s) { + var filename = s.substr(s.indexOf('/') + 1); + return '// ' + filename + '\n' + src.replace('/_css/', '/css/') + '\n'; + } + }, + src: Util.fetchScripts("_examples/editor_api.js", Util.jsBasePath), + dest: disDir + packageJson.name + '.all.js' + }, + parse: { + options: { + banner: banner + '(function(){\n\n', + footer: '\n\n})();\n' + }, + src: Util.fetchScripts("ueditor.parse.js", Util.parseBasePath), + dest: disDir + packageJson.name + '.parse.js' + }, + css: { + src: Util.fetchStyles(), + dest: disDir + 'themes/default/css/ueditor.css' + } + }, + cssmin: { + options: { + banner: banner + }, + files: { + expand: true, + cwd: disDir + 'themes/default/css/', + src: ['*.css', '!*.min.css'], + dest: disDir + 'themes/default/css/', + ext: '.min.css' + } + }, + uglify: { + options: { + banner: banner + }, + dest: { + src: disDir + '<%= pkg.name %>.all.js', + dest: disDir + '<%= pkg.name %>.all.min.js' + }, + parse: { + src: disDir + '<%= pkg.name %>.parse.js', + dest: disDir + '<%= pkg.name %>.parse.min.js' + } + }, + copy: { + base: { + files: [ + { + + src: [ '*.html', 'themes/iframe.css', 'themes/default/dialogbase.css', 'themes/default/images/**', 'dialogs/**', 'lang/**', 'third-party/**' ], + dest: disDir + + } + ] + }, + demo: { + files: [ + { + src: '_examples/completeDemo.html', + dest: disDir + 'index.html' + } + ] + }, + php: { + + expand: true, + src: 'php/**', + dest: disDir + + }, + asp: { + + expand: true, + src: 'asp/**', + dest: disDir + + }, + jsp: { + + expand: true, + src: 'jsp/**', + dest: disDir + + }, + net: { + + expand: true, + src: 'net/**', + dest: disDir + + } + }, + transcoding: { + + options: { + charset: encode + }, + src: [disDir + '**/*.html', disDir + '**/*.js', disDir + '**/*.css', disDir + '**/*.json', disDir + '**/*.jsp', disDir + '**/*.asp'] + + }, + replace: { + + fileEncode: { + src: [ disDir + '**/*.html', disDir + 'dialogs/**/*.js', disDir + '**/*.css', disDir + '**/*.php', disDir + '**/*.jsp', disDir + '**/*.ashx', disDir + '**/*.asp' ], + overwrite: true, + replacements: [ + { + from: /utf-8/gi, + to: 'gbk' + } + ] + }, + demo: { + src: disDir + 'index.html', + overwrite: true, + replacements: [ + { + from: /\.\.\//gi, + to: '' + }, + { + from: 'editor_api.js', + to: packageJson.name + '.all.min.js' + } + ] + }, + gbkasp: { + src: [ disDir + 'asp/*.asp' ], + overwrite: true, + replacements: [ + { + from: /65001/gi, + to: '936' + } + ] + } + + }, + clean: { + build: { + src: [ + disDir + "jsp/src", + disDir + "*/upload", + disDir + ".DS_Store", + disDir + "**/.DS_Store", + disDir + ".git", + disDir + "**/.git" + ] + } + } + + }); + + grunt.loadNpmTasks('grunt-text-replace'); + grunt.loadNpmTasks('grunt-contrib-concat'); + grunt.loadNpmTasks('grunt-contrib-cssmin'); + grunt.loadNpmTasks('grunt-contrib-uglify'); + grunt.loadNpmTasks('grunt-contrib-copy'); + grunt.loadNpmTasks('grunt-transcoding'); + grunt.loadNpmTasks('grunt-contrib-clean'); + + grunt.registerTask('default', 'UEditor build', function () { + + var tasks = [ 'concat', 'cssmin', 'uglify', 'copy:base', 'copy:' + server, 'copy:demo', 'replace:demo', 'clean' ]; + + if (encode === 'gbk') { + tasks.push('replace:fileEncode'); + if (server === 'asp') { + tasks.push('replace:gbkasp'); + } + } + + tasks.push('transcoding'); + + //config修改 + updateConfigFile(); + + grunt.task.run(tasks); + + }); + + + function updateConfigFile() { + + var filename = 'ueditor.config.js', + file = grunt.file.read(filename), + path = server + "/", + suffix = server === "net" ? ".ashx" : "." + server; + + file = file.replace(/php\//ig, path).replace(/\.php/ig, suffix); + + if (encode == 'gbk') { + file = file.replace(/utf-8/gi, 'gbk'); + } + + //写入到dist + if (grunt.file.write(disDir + filename, file)) { + + grunt.log.writeln('config file update success'); + + } else { + grunt.log.warn('config file update error'); + } + + } + +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/LICENSE b/nezha-fronted/static/ueditor-1.4.3.3/LICENSE new file mode 100644 index 000000000..e84721923 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 ueditor + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/README.md b/nezha-fronted/static/ueditor-1.4.3.3/README.md new file mode 100644 index 000000000..b452f4330 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/README.md @@ -0,0 +1,90 @@ +Get Started +===== + +## ueditor富文本编辑器介绍 + +UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码。 + +## 入门部署和体验 ## + +### 第一步:下载编辑器 ### + +到官网下载ueditor最新版:[[官网地址]](http://ueditor.baidu.com/website/download.html#ueditor "官网下载地址") + +### 第二步:创建demo文件 ### +解压下载的包,在解压后的目录创建demo.html文件,填入下面的html代码 + +```html + + + + + ueditor demo + + + + + + + + + + + + +``` + +### 第三步:在浏览器打开demo.html ### + +如果看到了下面这样的编辑器,恭喜你,初次部署成功! + +![部署成功](http://fex.baidu.com/ueditor/doc/images/demo.png) + +### 自定义的参数 + +编辑器有很多可自定义的参数项,在实例化的时候可以传入给编辑器: +```javascript +var ue = UE.getEditor('container', { + autoHeight: false +}); +``` + +配置项也可以通过ueditor.config.js文件修改,具体的配置方法请看[前端配置项说明](http://fex.baidu.com/ueditor/#start-config1.4 前端配置项说明.md) + +### 设置和读取编辑器的内容 + +通getContent和setContent方法可以设置和读取编辑器的内容 +```javascript +var ue = UE.getContent(); +ue.ready(function(){ + //设置编辑器的内容 + ue.setContent('hello'); + //获取html内容,返回:

hello

+ var html = ue.getContent(); + //获取纯文本内容,返回: hello + var txt = ue.getContentTxt(); +}); +``` + +ueditor的更多API请看[API 文档](http://ueditor.baidu.com/doc "ueditor API 文档") + +## 相关链接 ## + +ueditor 官网:[http://ueditor.baidu.com](http://ueditor.baidu.com "ueditor 官网") + +ueditor API 文档:[http://ueditor.baidu.com/doc](http://ueditor.baidu.com/doc "ueditor API 文档") + +ueditor github 地址:[http://github.com/fex-team/ueditor](http://github.com/fex-team/ueditor "ueditor github 地址") + +## 详细文档 + +ueditor 文档:[http://fex.baidu.com/ueditor/](http://fex.baidu.com/ueditor/) + + + +## 联系我们 ## + +email:[ueditor@baidu.com](mailto://email:ueditor@baidu.com "发邮件给ueditor开发组") +issue:[github issue](http://github.com/fex-team/ueditor/issues "ueditor 论坛") diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/addCustomizeButton.js b/nezha-fronted/static/ueditor-1.4.3.3/_examples/addCustomizeButton.js new file mode 100644 index 000000000..13185ea17 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/addCustomizeButton.js @@ -0,0 +1,38 @@ +UE.registerUI('button',function(editor,uiName){ + //注册按钮执行时的command命令,使用命令默认就会带有回退操作 + editor.registerCommand(uiName,{ + execCommand:function(){ + alert('execCommand:' + uiName) + } + }); + + //创建一个button + var btn = new UE.ui.Button({ + //按钮的名字 + name:uiName, + //提示 + title:uiName, + //需要添加的额外样式,指定icon图标,这里默认使用一个重复的icon + cssRules :'background-position: -500px 0;', + //点击时执行的命令 + onclick:function () { + //这里可以不用执行命令,做你自己的操作也可 + editor.execCommand(uiName); + } + }); + + //当点到编辑内容上时,按钮要做的状态反射 + editor.addListener('selectionchange', function () { + var state = editor.queryCommandState(uiName); + if (state == -1) { + btn.setDisabled(true); + btn.setChecked(false); + } else { + btn.setDisabled(false); + btn.setChecked(state); + } + }); + + //因为你是添加button,所以需要返回这个button + return btn; +}/*index 指定添加到工具栏上的那个位置,默认时追加到最后,editorId 指定这个UI是那个编辑器实例上的,默认是页面上所有的编辑器都会添加这个按钮*/); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/addCustomizeCombox.js b/nezha-fronted/static/ueditor-1.4.3.3/_examples/addCustomizeCombox.js new file mode 100644 index 000000000..fc272abce --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/addCustomizeCombox.js @@ -0,0 +1,69 @@ +UE.registerUI('combox',function(editor,uiName){ + //注册按钮执行时的command命令,用uiName作为command名字,使用命令默认就会带有回退操作 + editor.registerCommand(uiName,{ + execCommand:function(cmdName,value){ + //这里借用fontsize的命令 + this.execCommand('fontsize',value + 'px') + }, + queryCommandValue:function(){ + //这里借用fontsize的查询命令 + return this.queryCommandValue('fontsize') + } + }); + + + //创建下拉菜单中的键值对,这里我用字体大小作为例子 + var items = []; + for(var i= 0,ci;ci=[10, 11, 12, 14, 16, 18, 20, 24, 36][i++];){ + items.push({ + //显示的条目 + label:'字体:' + ci + 'px', + //选中条目后的返回值 + value:ci, + //针对每个条目进行特殊的渲染 + renderLabelHtml:function () { + //这个是希望每个条目的字体是不同的 + return '
' + (this.label || '') + '
'; + } + }); + } + //创建下来框 + var combox = new UE.ui.Combox({ + //需要指定当前的编辑器实例 + editor:editor, + //添加条目 + items:items, + //当选中时要做的事情 + onselect:function (t, index) { + //拿到选中条目的值 + editor.execCommand(uiName, this.items[index].value); + }, + //提示 + title:uiName, + //当编辑器没有焦点时,combox默认显示的内容 + initValue:uiName + }); + + editor.addListener('selectionchange', function (type, causeByUi, uiReady) { + if (!uiReady) { + var state = editor.queryCommandState(uiName); + if (state == -1) { + combox.setDisabled(true); + } else { + combox.setDisabled(false); + var value = editor.queryCommandValue(uiName); + if(!value){ + combox.setValue(uiName); + return; + } + //ie下从源码模式切换回来时,字体会带单引号,而且会有逗号 + value && (value = value.replace(/['"]/g, '').split(',')[0]); + combox.setValue(value); + + } + } + + }); + return combox; +},2/*index 指定添加到工具栏上的那个位置,默认时追加到最后,editorId 指定这个UI是那个编辑器实例上的,默认是页面上所有的编辑器都会添加这个按钮*/); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/addCustomizeDialog.js b/nezha-fronted/static/ueditor-1.4.3.3/_examples/addCustomizeDialog.js new file mode 100644 index 000000000..6b8655556 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/addCustomizeDialog.js @@ -0,0 +1,49 @@ +UE.registerUI('dialog',function(editor,uiName){ + + //创建dialog + var dialog = new UE.ui.Dialog({ + //指定弹出层中页面的路径,这里只能支持页面,因为跟addCustomizeDialog.js相同目录,所以无需加路径 + iframeUrl:'customizeDialogPage.html', + //需要指定当前的编辑器实例 + editor:editor, + //指定dialog的名字 + name:uiName, + //dialog的标题 + title:"这是个测试浮层", + + //指定dialog的外围样式 + cssRules:"width:600px;height:300px;", + + //如果给出了buttons就代表dialog有确定和取消 + buttons:[ + { + className:'edui-okbutton', + label:'确定', + onclick:function () { + dialog.close(true); + } + }, + { + className:'edui-cancelbutton', + label:'取消', + onclick:function () { + dialog.close(false); + } + } + ]}); + + //参考addCustomizeButton.js + var btn = new UE.ui.Button({ + name:'dialogbutton' + uiName, + title:'dialogbutton' + uiName, + //需要添加的额外样式,指定icon图标,这里默认使用一个重复的icon + cssRules :'background-position: -500px 0;', + onclick:function () { + //渲染dialog + dialog.render(); + dialog.open(); + } + }); + + return btn; +}/*index 指定添加到工具栏上的那个位置,默认时追加到最后,editorId 指定这个UI是那个编辑器实例上的,默认是页面上所有的编辑器都会添加这个按钮*/); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/charts.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/charts.html new file mode 100644 index 000000000..db0c000d8 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/charts.html @@ -0,0 +1,71 @@ + + + + 图表demo + + + + + + + + + + +
+ +
+ + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/completeDemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/completeDemo.html new file mode 100644 index 000000000..ba45acf62 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/completeDemo.html @@ -0,0 +1,175 @@ + + + + 完整demo + + + + + + + + + + +
+

完整demo

+ +
+
+
+ + + + + + + + + + + +
+
+ + + + + + + +
+ +
+ + +
+ +
+
+ + +
+ + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/customPluginDemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/customPluginDemo.html new file mode 100644 index 000000000..d6109f92e --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/customPluginDemo.html @@ -0,0 +1,54 @@ + + + + + + + + + + +

UEditor自定义插件

+ + + + + + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/customToolbarDemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/customToolbarDemo.html new file mode 100644 index 000000000..c3aca5bfb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/customToolbarDemo.html @@ -0,0 +1,105 @@ + + + + + + + + + + +

UEditor自定义toolbar

+
+
+
+ + + + + + + + +
+
+
+
+ + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/customizeDialogPage.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/customizeDialogPage.html new file mode 100644 index 000000000..84c1cc2aa --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/customizeDialogPage.html @@ -0,0 +1,25 @@ + + + + + + + +
+

测试页面

+
+ + + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/customizeToolbarUIDemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/customizeToolbarUIDemo.html new file mode 100644 index 000000000..cec1f030a --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/customizeToolbarUIDemo.html @@ -0,0 +1,43 @@ + + + + 完整demo + + + + + + + + + + + + + + + + +
+

二次开发demo

+ +
+ + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/editor_api.js b/nezha-fronted/static/ueditor-1.4.3.3/_examples/editor_api.js new file mode 100644 index 000000000..faf9412cf --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/editor_api.js @@ -0,0 +1,129 @@ +/** + * 开发版本的文件导入 + */ +(function (){ + var paths = [ + 'editor.js', + 'core/browser.js', + 'core/utils.js', + 'core/EventBase.js', + 'core/dtd.js', + 'core/domUtils.js', + 'core/Range.js', + 'core/Selection.js', + 'core/Editor.js', + 'core/Editor.defaultoptions.js', + 'core/loadconfig.js', + 'core/ajax.js', + 'core/filterword.js', + 'core/node.js', + 'core/htmlparser.js', + 'core/filternode.js', + 'core/plugin.js', + 'core/keymap.js', + 'core/localstorage.js', + 'plugins/defaultfilter.js', + 'plugins/inserthtml.js', + 'plugins/autotypeset.js', + 'plugins/autosubmit.js', + 'plugins/background.js', + 'plugins/image.js', + 'plugins/justify.js', + 'plugins/font.js', + 'plugins/link.js', + 'plugins/iframe.js', + 'plugins/scrawl.js', + 'plugins/removeformat.js', + 'plugins/blockquote.js', + 'plugins/convertcase.js', + 'plugins/indent.js', + 'plugins/print.js', + 'plugins/preview.js', + 'plugins/selectall.js', + 'plugins/paragraph.js', + 'plugins/directionality.js', + 'plugins/horizontal.js', + 'plugins/time.js', + 'plugins/rowspacing.js', + 'plugins/lineheight.js', + 'plugins/insertcode.js', + 'plugins/cleardoc.js', + 'plugins/anchor.js', + 'plugins/wordcount.js', + 'plugins/pagebreak.js', + 'plugins/wordimage.js', + 'plugins/dragdrop.js', + 'plugins/undo.js', + 'plugins/copy.js', + 'plugins/paste.js', + 'plugins/puretxtpaste.js', + 'plugins/list.js', + 'plugins/source.js', + 'plugins/enterkey.js', + 'plugins/keystrokes.js', + 'plugins/fiximgclick.js', + 'plugins/autolink.js', + 'plugins/autoheight.js', + 'plugins/autofloat.js', + 'plugins/video.js', + 'plugins/table.core.js', + 'plugins/table.cmds.js', + 'plugins/table.action.js', + 'plugins/table.sort.js', + 'plugins/contextmenu.js', + 'plugins/shortcutmenu.js', + 'plugins/basestyle.js', + 'plugins/elementpath.js', + 'plugins/formatmatch.js', + 'plugins/searchreplace.js', + 'plugins/customstyle.js', + 'plugins/catchremoteimage.js', + 'plugins/snapscreen.js', + 'plugins/insertparagraph.js', + 'plugins/webapp.js', + 'plugins/template.js', + 'plugins/music.js', + 'plugins/autoupload.js', + 'plugins/autosave.js', + 'plugins/charts.js', + 'plugins/section.js', + 'plugins/simpleupload.js', + 'plugins/serverparam.js', + 'plugins/insertfile.js', + 'plugins/xssFilter.js', + 'ui/ui.js', + 'ui/uiutils.js', + 'ui/uibase.js', + 'ui/separator.js', + 'ui/mask.js', + 'ui/popup.js', + 'ui/colorpicker.js', + 'ui/tablepicker.js', + 'ui/stateful.js', + 'ui/button.js', + 'ui/splitbutton.js', + 'ui/colorbutton.js', + 'ui/tablebutton.js', + 'ui/autotypesetpicker.js', + 'ui/autotypesetbutton.js', + 'ui/cellalignpicker.js', + 'ui/pastepicker.js', + 'ui/toolbar.js', + 'ui/menu.js', + 'ui/combox.js', + 'ui/dialog.js', + 'ui/menubutton.js', + 'ui/multiMenu.js', + 'ui/shortcutmenu.js', + 'ui/breakline.js', + 'ui/message.js', + 'adapter/editorui.js', + 'adapter/editor.js', + 'adapter/message.js', + 'adapter/autosave.js' + ], + baseURL = '../_src/'; + for (var i=0,pi;pi = paths[i++];) { + document.write(''); + } +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/filterRuleDemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/filterRuleDemo.html new file mode 100644 index 000000000..b9bc8baa7 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/filterRuleDemo.html @@ -0,0 +1,151 @@ + + + + 过滤规则定制化 + + + + + + +

尝试粘贴内容近来,这里边不能粘贴任何inline的样式,不能有iframe,style,script,embed等标签,表格不能嵌套

+
+ +
+ + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/highlightDemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/highlightDemo.html new file mode 100644 index 000000000..650569124 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/highlightDemo.html @@ -0,0 +1,39 @@ + + + + + + + + + + + + + +

代码高亮演示

+

获得编辑器实例

+
+
+        UE.getEditor('myEditor');
+    
+
+ + + + + + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/index.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/index.html new file mode 100644 index 000000000..a5a434711 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/index.html @@ -0,0 +1,118 @@ + + + + + + + + +

UEditor各种实例演示

+

基础示例

+
    +
  • + 简单示例
    + 使用基础的按钮实现简单的功能 +
  • +
+

应用展示

+
    +
  • + 表单应用
    + 编辑器的内容通过表单提交到后台 +
  • +
  • + 重置编辑器
    + 将编辑器的内部变量清空,重置。 +
  • +
  • + 文本域渲染编辑器
    + 将编辑器渲染到文本域,并且将文本域的内容放到编辑器的初始化内容里 +
  • +
+

二次开发

+ +

高级案例

+ + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/jqueryCompleteDemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/jqueryCompleteDemo.html new file mode 100644 index 000000000..dac705032 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/jqueryCompleteDemo.html @@ -0,0 +1,43 @@ + + + + 使用jquery的完整demo + + + + + + + +
+ + +
+ + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/jqueryValidation.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/jqueryValidation.html new file mode 100644 index 000000000..fa08e3a52 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/jqueryValidation.html @@ -0,0 +1,63 @@ + + + + + Ueditor在jquery validation下的验证 + + + + + + + + + + + +
+

Ueditor在jquery validation下的验证

+ + + + +
+ + + + +
+ +
+ + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/multiDemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/multiDemo.html new file mode 100644 index 000000000..47a65cc7e --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/multiDemo.html @@ -0,0 +1,43 @@ + + + + + + + + + +

UEditor多实例

+ + + + + + + + + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/multiEditorWithOneInstance.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/multiEditorWithOneInstance.html new file mode 100644 index 000000000..44d1da264 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/multiEditorWithOneInstance.html @@ -0,0 +1,60 @@ + + + + + + + + + + + +

UEditor多编辑区域一个编辑器实例

+ + + + + + + + + + + + + +
+ 编辑区域一 +
+ 编辑区域二 + 内容2
+ 编辑区域三 + 内容3
+ + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/renderInTable.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/renderInTable.html new file mode 100644 index 000000000..ae86a1088 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/renderInTable.html @@ -0,0 +1,26 @@ + + + + + + + 表格内实例化编辑器实例 + + + +
+
+ + + + + + + +
表格标题
标题内容
中国
+
+ + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/resetDemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/resetDemo.html new file mode 100644 index 000000000..34d56a98f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/resetDemo.html @@ -0,0 +1,52 @@ + + + + + + 重置编辑器 + + + + + +

重置编辑器和销毁编辑器示例

+
+

+

+ + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/sectiondemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/sectiondemo.html new file mode 100644 index 000000000..f62554e6f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/sectiondemo.html @@ -0,0 +1,181 @@ + + + + 目录大纲demo + + + + + + + + +
+

目录大纲demo

+
+
+
目录:
+
+
+
+
+ +
+
+ + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/server/getContent.ashx b/nezha-fronted/static/ueditor-1.4.3.3/_examples/server/getContent.ashx new file mode 100644 index 000000000..d6104df59 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/server/getContent.ashx @@ -0,0 +1,44 @@ +<%@ WebHandler Language="C#" Class="getContent" %> +/** + * Created by visual studio 2010 + * User: xuheng + * Date: 12-3-6 + * Time: 下午21:23 + * To get the value of editor and output the value . + */ +using System; +using System.Web; + +public class getContent : IHttpHandler { + + public void ProcessRequest (HttpContext context) { + context.Response.ContentType = "text/html"; + + //获取数据 + string content = context.Server.HtmlEncode(context.Request.Form["myEditor"]); + + + //存入数据库或者其他操作 + //------------- + + //显示 + context.Response.Write(""); + context.Response.Write( + + ""); + + context.Response.Write("Content of First Editor: "); + context.Response.Write("
" + context.Server.HtmlDecode(content) + "
"); + + } + + public bool IsReusable { + get { + return false; + } + } + +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/server/getContent.asp b/nezha-fronted/static/ueditor-1.4.3.3/_examples/server/getContent.asp new file mode 100644 index 000000000..fa4cb6216 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/server/getContent.asp @@ -0,0 +1,15 @@ +<% @LANGUAGE="VBSCRIPT" CODEPAGE="65001" %> + + + +<% + Dim content + content = Request.Form("myEditor") + Response.Write("第1个编辑器的值") + Response.Write("
" + content + "
") +%> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/server/getContent.jsp b/nezha-fronted/static/ueditor-1.4.3.3/_examples/server/getContent.jsp new file mode 100644 index 000000000..1ea45081a --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/server/getContent.jsp @@ -0,0 +1,19 @@ + <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> + + + +<% +request.setCharacterEncoding("utf-8"); +response.setCharacterEncoding("utf-8"); +String content = request.getParameter("myEditor"); + + + +response.getWriter().print("第1个编辑器的值"); +response.getWriter().print("
"+content+"
"); + +%> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/server/getContent.php b/nezha-fronted/static/ueditor-1.4.3.3/_examples/server/getContent.php new file mode 100644 index 000000000..67778486b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/server/getContent.php @@ -0,0 +1,19 @@ + + + +".htmlspecialchars_decode($content).""; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/setWidthHeightDemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/setWidthHeightDemo.html new file mode 100644 index 000000000..b02162507 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/setWidthHeightDemo.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + +

UEditor设置宽高demo

+

这里的宽高都只是编辑区域的宽高,不包括工具栏的高度和状态栏的高度

+

容器给定编辑器的宽高

+ + + +
+

初始化时给定编辑器的宽高

+ + +

没有工具栏的编辑器

+
+ + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/simpleDemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/simpleDemo.html new file mode 100644 index 000000000..881a59c74 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/simpleDemo.html @@ -0,0 +1,36 @@ + + + + + + + + + + +

UEditor简单功能

+ + + + + + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/sortableDemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/sortableDemo.html new file mode 100644 index 000000000..ee7d33f6f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/sortableDemo.html @@ -0,0 +1,86 @@ + + + + + + + + + +

表格排序演示

+

+

+ 默认排序方法有五种:
+ reversecurrent : 逆序当前
+ orderbyasc : 按ASCII字符升序
+ reversebyasc : 按ASCII字符降序
+ orderbynum : 按数值大小升序
+ reversebynum : 按数值大小降序 +

+

+ 表格data-sort-type属性值为reversebynum,按照数值大小降序排序,点击第一行的单元格进行排序。 +

+
+ + + + + + + + +
343 352 323 234 379 782
341 163 422 234 725 833
221 456 335 423 445 793
112 277 563 423 932 425
587 175 159 734 582 458
+
+ +

+
+

+

+ 自定义排序,按照个位数排序,点击第一行的单元格进行排序。 +

+
+ + + + + + + + +
343 352 323 234 379 782
341 163 422 234 725 833
221 456 335 423 445 793
112 277 563 423 932 425
587 175 159 734 582 458
+
+ + + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/submitFormDemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/submitFormDemo.html new file mode 100644 index 000000000..c2694eecb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/submitFormDemo.html @@ -0,0 +1,54 @@ + + + + + + + + + + + +

UEditor提交示例

+
+ + +
+

+ 从1.2.6开始,会自动同步数据无需再手动调用sync方法 + + +

+ + + + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/textareaDemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/textareaDemo.html new file mode 100644 index 000000000..7b0a08b6c --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/textareaDemo.html @@ -0,0 +1,34 @@ + + + + + + + + + + + + +

文本域渲染编辑器

+ + + +
+ + + + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_examples/uparsedemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_examples/uparsedemo.html new file mode 100644 index 000000000..3bd561367 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_examples/uparsedemo.html @@ -0,0 +1,204 @@ + + + + + + + + + +

解析编辑的内容

+
+
  1. 这里可以书写,编辑器的初始内容

  • sdfas

    1. dfas

  1. dfa

    1. sdfadf

+

+ 这里可以书写,编辑器的初始内容 +

+

+ +

+
+               moveToBookmark:function (bookmark) {
+            var start = bookmark.id ? this.document.getElementById(bookmark.start) : bookmark.start,
+                end = bookmark.end && bookmark.id ? this.document.getElementById(bookmark.end) : bookmark.end;
+            this.setStartBefore(start);
+            domUtils.remove(start);
+            if (end) {
+                this.setEndBefore(end);
+                domUtils.remove(end);
+            } else {
+                this.collapse(true);
+            }
+            return this;
+        },
+        
+
    +
  1. +

    + dfasdf +

    +
  2. +
  3. +

    + asd +

    +
  4. +
  5. +

    + fa +

    +
  6. +
  7. +

    + sdfa +

    +
  8. +
  9. +

    + sdfa +

    +
  10. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ sdf
+
+ sdf
+
+ sdf
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ UEditor +

+

+ 简介 +

+

+ UEditor是由百度WEB前端研发部开发的所见即所得的开源富文本编辑器,具有轻量、可定制、用户体验优秀等特点。开源基于BSD协议,所有源代码在协议允许范围内可自由修改和使用。百度UEditor的推出,可以帮助不少网站开者在开发富文本编辑器所遇到的难题,节约开发者因开发富文本编辑器所需要的大量时间,有效降低了企业的开发成本。 +

+

+ 特点
+

+

+ 1、核心层提供了编辑器底层的一些方法和概念,如DOM树操作、Selection、Range等。 +

+

+ 2、在核心层之上覆盖的是命令插件层。之所以叫命令插件层,是因为UEditor中所有的功能型实现都是通过这一层中的命令和插件来完成的,并且各个命令和插件之间基本互不耦合——使用者需要使用哪个功能就导入哪个功能对应的命令或者插件文件,完全不用考虑另外那些杂七杂八的JS文件(极少数插件除外,关于这些插件下文会整理出一个依赖列表来供同学们参考)。 +

+

+ 理论上来讲,所有的命令都是可以用插件来代替的,但是依然将两者分开的主要原因是命令都是一些静态的方法,无需随editor实例初始化,从而优化了编辑器的性能。而插件随编辑器的初始化而初始化,性能上会有少许的影响,但相比命令而言,插件能够完成更加复杂的功能。其中最主要的一个特点是在插件内部既可以为编辑器注册命令,也可以为编辑器绑定监听事件。这个特点使得为编辑器添加任何功能都可以在插件中独立完成。 +

+

+ 3、在命令插件层之上则是UI层。UEditor的UI设计与核心层和命令插件层几乎完全解耦,简单的几个配置就可以为编辑器在界面上添加额外的UI元素和功能,具体的配置下面将会深入阐述。 +

+

+
+

+

+
+

+
+ + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_parse/background.js b/nezha-fronted/static/ueditor-1.4.3.3/_parse/background.js new file mode 100644 index 000000000..acc8008ef --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_parse/background.js @@ -0,0 +1,16 @@ +UE.parse.register('background', function (utils) { + var me = this, + root = me.root, + p = root.getElementsByTagName('p'), + styles; + + for (var i = 0,ci; ci = p[i++];) { + styles = ci.getAttribute('data-background'); + if (styles){ + ci.parentNode.removeChild(ci); + } + } + + //追加默认的表格样式 + styles && utils.cssRule('ueditor_background', me.selector + '{' + styles + '}', document); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_parse/charts.js b/nezha-fronted/static/ueditor-1.4.3.3/_parse/charts.js new file mode 100644 index 000000000..c1339aee2 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_parse/charts.js @@ -0,0 +1,337 @@ +UE.parse.register('charts',function( utils ){ + + utils.cssRule('chartsContainerHeight','.edui-chart-container { height:'+(this.chartContainerHeight||300)+'px}'); + var resourceRoot = this.rootPath, + containers = this.root, + sources = null; + + //不存在指定的根路径, 则直接退出 + if ( !resourceRoot ) { + return; + } + + if ( sources = parseSources() ) { + + loadResources(); + + } + + + function parseSources () { + + if ( !containers ) { + return null; + } + + return extractChartData( containers ); + + } + + /** + * 提取数据 + */ + function extractChartData ( rootNode ) { + + var data = [], + tables = rootNode.getElementsByTagName( "table" ); + + for ( var i = 0, tableNode; tableNode = tables[ i ]; i++ ) { + + if ( tableNode.getAttribute( "data-chart" ) !== null ) { + + data.push( formatData( tableNode ) ); + + } + + } + + return data.length ? data : null; + + } + + function formatData ( tableNode ) { + + var meta = tableNode.getAttribute( "data-chart" ), + metaConfig = {}, + data = []; + + //提取table数据 + for ( var i = 0, row; row = tableNode.rows[ i ]; i++ ) { + + var rowData = []; + + for ( var j = 0, cell; cell = row.cells[ j ]; j++ ) { + + var value = ( cell.innerText || cell.textContent || '' ); + rowData.push( cell.tagName == 'TH' ? value:(value | 0) ); + + } + + data.push( rowData ); + + } + + //解析元信息 + meta = meta.split( ";" ); + for ( var i = 0, metaData; metaData = meta[ i ]; i++ ) { + + metaData = metaData.split( ":" ); + metaConfig[ metaData[ 0 ] ] = metaData[ 1 ]; + + } + + + return { + table: tableNode, + meta: metaConfig, + data: data + }; + + } + + //加载资源 + function loadResources () { + + loadJQuery(); + + } + + function loadJQuery () { + + //不存在jquery, 则加载jquery + if ( !window.jQuery ) { + + utils.loadFile(document,{ + src : resourceRoot + "/third-party/jquery-1.10.2.min.js", + tag : "script", + type : "text/javascript", + defer : "defer" + },function(){ + + loadHighcharts(); + + }); + + } else { + + loadHighcharts(); + + } + + } + + function loadHighcharts () { + + //不存在Highcharts, 则加载Highcharts + if ( !window.Highcharts ) { + + utils.loadFile(document,{ + src : resourceRoot + "/third-party/highcharts/highcharts.js", + tag : "script", + type : "text/javascript", + defer : "defer" + },function(){ + + loadTypeConfig(); + + }); + + } else { + + loadTypeConfig(); + + } + + } + + //加载图表差异化配置文件 + function loadTypeConfig () { + + utils.loadFile(document,{ + src : resourceRoot + "/dialogs/charts/chart.config.js", + tag : "script", + type : "text/javascript", + defer : "defer" + },function(){ + + render(); + + }); + + } + + //渲染图表 + function render () { + + var config = null, + chartConfig = null, + container = null; + + for ( var i = 0, len = sources.length; i < len; i++ ) { + + config = sources[ i ]; + + chartConfig = analysisConfig( config ); + + container = createContainer( config.table ); + + renderChart( container, typeConfig[ config.meta.chartType ], chartConfig ); + + } + + + } + + /** + * 渲染图表 + * @param container 图表容器节点对象 + * @param typeConfig 图表类型配置 + * @param config 图表通用配置 + * */ + function renderChart ( container, typeConfig, config ) { + + + $( container ).highcharts( $.extend( {}, typeConfig, { + + credits: { + enabled: false + }, + exporting: { + enabled: false + }, + title: { + text: config.title, + x: -20 //center + }, + subtitle: { + text: config.subTitle, + x: -20 + }, + xAxis: { + title: { + text: config.xTitle + }, + categories: config.categories + }, + yAxis: { + title: { + text: config.yTitle + }, + plotLines: [{ + value: 0, + width: 1, + color: '#808080' + }] + }, + tooltip: { + enabled: true, + valueSuffix: config.suffix + }, + legend: { + layout: 'vertical', + align: 'right', + verticalAlign: 'middle', + borderWidth: 1 + }, + series: config.series + + } )); + + } + + /** + * 创建图表的容器 + * 新创建的容器会替换掉对应的table对象 + * */ + function createContainer ( tableNode ) { + + var container = document.createElement( "div" ); + container.className = "edui-chart-container"; + + tableNode.parentNode.replaceChild( container, tableNode ); + + return container; + + } + + //根据config解析出正确的类别和图表数据信息 + function analysisConfig ( config ) { + + var series = [], + //数据类别 + categories = [], + result = [], + data = config.data, + meta = config.meta; + + //数据对齐方式为相反的方式, 需要反转数据 + if ( meta.dataFormat != "1" ) { + + for ( var i = 0, len = data.length; i < len ; i++ ) { + + for ( var j = 0, jlen = data[ i ].length; j < jlen; j++ ) { + + if ( !result[ j ] ) { + result[ j ] = []; + } + + result[ j ][ i ] = data[ i ][ j ]; + + } + + } + + data = result; + + } + + result = {}; + + //普通图表 + if ( meta.chartType != typeConfig.length - 1 ) { + + categories = data[ 0 ].slice( 1 ); + + for ( var i = 1, curData; curData = data[ i ]; i++ ) { + series.push( { + name: curData[ 0 ], + data: curData.slice( 1 ) + } ); + } + + result.series = series; + result.categories = categories; + result.title = meta.title; + result.subTitle = meta.subTitle; + result.xTitle = meta.xTitle; + result.yTitle = meta.yTitle; + result.suffix = meta.suffix; + + } else { + + var curData = []; + + for ( var i = 1, len = data[ 0 ].length; i < len; i++ ) { + + curData.push( [ data[ 0 ][ i ], data[ 1 ][ i ] | 0 ] ); + + } + + //饼图 + series[ 0 ] = { + type: 'pie', + name: meta.tip, + data: curData + }; + + result.series = series; + result.title = meta.title; + result.suffix = meta.suffix; + + } + + return result; + + } + +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_parse/insertcode.js b/nezha-fronted/static/ueditor-1.4.3.3/_parse/insertcode.js new file mode 100644 index 000000000..e34b9bc55 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_parse/insertcode.js @@ -0,0 +1,42 @@ +UE.parse.register('insertcode',function(utils){ + var pres = this.root.getElementsByTagName('pre'); + if(pres.length){ + if(typeof XRegExp == "undefined"){ + var jsurl,cssurl; + if(this.rootPath !== undefined){ + jsurl = utils.removeLastbs(this.rootPath) + '/third-party/SyntaxHighlighter/shCore.js'; + cssurl = utils.removeLastbs(this.rootPath) + '/third-party/SyntaxHighlighter/shCoreDefault.css'; + }else{ + jsurl = this.highlightJsUrl; + cssurl = this.highlightCssUrl; + } + utils.loadFile(document,{ + id : "syntaxhighlighter_css", + tag : "link", + rel : "stylesheet", + type : "text/css", + href : cssurl + }); + utils.loadFile(document,{ + id : "syntaxhighlighter_js", + src : jsurl, + tag : "script", + type : "text/javascript", + defer : "defer" + },function(){ + utils.each(pres,function(pi){ + if(pi && /brush/i.test(pi.className)){ + SyntaxHighlighter.highlight(pi); + } + }); + }); + }else{ + utils.each(pres,function(pi){ + if(pi && /brush/i.test(pi.className)){ + SyntaxHighlighter.highlight(pi); + } + }); + } + } + +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_parse/list.js b/nezha-fronted/static/ueditor-1.4.3.3/_parse/list.js new file mode 100644 index 000000000..f28b2c221 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_parse/list.js @@ -0,0 +1,94 @@ +UE.parse.register('list',function(utils){ + var customCss = [], + customStyle = { + 'cn' : 'cn-1-', + 'cn1' : 'cn-2-', + 'cn2' : 'cn-3-', + 'num' : 'num-1-', + 'num1' : 'num-2-', + 'num2' : 'num-3-', + 'dash' : 'dash', + 'dot' : 'dot' + }; + + + utils.extend(this,{ + liiconpath : 'http://bs.baidu.com/listicon/', + listDefaultPaddingLeft : '20' + }); + + var root = this.root, + ols = root.getElementsByTagName('ol'), + uls = root.getElementsByTagName('ul'), + selector = this.selector; + + if(ols.length){ + applyStyle.call(this,ols); + } + + if(uls.length){ + applyStyle.call(this,uls); + } + + if(ols.length || uls.length){ + customCss.push(selector +' .list-paddingleft-1{padding-left:0}'); + customCss.push(selector +' .list-paddingleft-2{padding-left:'+ this.listDefaultPaddingLeft+'px}'); + customCss.push(selector +' .list-paddingleft-3{padding-left:'+ this.listDefaultPaddingLeft*2+'px}'); + + utils.cssRule('list', selector +' ol,'+selector +' ul{margin:0;padding:0;}li{clear:both;}'+customCss.join('\n'), document); + } + function applyStyle(nodes){ + var T = this; + utils.each(nodes,function(list){ + if(list.className && /custom_/i.test(list.className)){ + var listStyle = list.className.match(/custom_(\w+)/)[1]; + if(listStyle == 'dash' || listStyle == 'dot'){ + utils.pushItem(customCss,selector +' li.list-' + customStyle[listStyle] + '{background-image:url(' + T.liiconpath +customStyle[listStyle]+'.gif)}'); + utils.pushItem(customCss,selector +' ul.custom_'+listStyle+'{list-style:none;} '+ selector +' ul.custom_'+listStyle+' li{background-position:0 3px;background-repeat:no-repeat}'); + + }else{ + var index = 1; + utils.each(list.childNodes,function(li){ + if(li.tagName == 'LI'){ + utils.pushItem(customCss,selector + ' li.list-' + customStyle[listStyle] + index + '{background-image:url(' + T.liiconpath + 'list-'+customStyle[listStyle] +index + '.gif)}'); + index++; + } + }); + utils.pushItem(customCss,selector + ' ol.custom_'+listStyle+'{list-style:none;}'+selector+' ol.custom_'+listStyle+' li{background-position:0 3px;background-repeat:no-repeat}'); + } + switch(listStyle){ + case 'cn': + utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-1{padding-left:25px}'); + utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-2{padding-left:40px}'); + utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-3{padding-left:55px}'); + break; + case 'cn1': + utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-1{padding-left:30px}'); + utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-2{padding-left:40px}'); + utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-3{padding-left:55px}'); + break; + case 'cn2': + utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-1{padding-left:40px}'); + utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-2{padding-left:55px}'); + utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-3{padding-left:68px}'); + break; + case 'num': + case 'num1': + utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-1{padding-left:25px}'); + break; + case 'num2': + utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-1{padding-left:35px}'); + utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-2{padding-left:40px}'); + break; + case 'dash': + utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft{padding-left:35px}'); + break; + case 'dot': + utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft{padding-left:20px}'); + } + } + }); + } + + +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_parse/parse.js b/nezha-fronted/static/ueditor-1.4.3.3/_parse/parse.js new file mode 100644 index 000000000..fe1275507 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_parse/parse.js @@ -0,0 +1,327 @@ +(function(){ + UE = window.UE || {}; + var isIE = !!window.ActiveXObject; + //定义utils工具 + var utils = { + removeLastbs : function(url){ + return url.replace(/\/$/,'') + }, + extend : function(t,s){ + var a = arguments, + notCover = this.isBoolean(a[a.length - 1]) ? a[a.length - 1] : false, + len = this.isBoolean(a[a.length - 1]) ? a.length - 1 : a.length; + for (var i = 1; i < len; i++) { + var x = a[i]; + for (var k in x) { + if (!notCover || !t.hasOwnProperty(k)) { + t[k] = x[k]; + } + } + } + return t; + }, + isIE : isIE, + cssRule : isIE ? function(key,style,doc){ + var indexList,index; + doc = doc || document; + if(doc.indexList){ + indexList = doc.indexList; + }else{ + indexList = doc.indexList = {}; + } + var sheetStyle; + if(!indexList[key]){ + if(style === undefined){ + return '' + } + sheetStyle = doc.createStyleSheet('',index = doc.styleSheets.length); + indexList[key] = index; + }else{ + sheetStyle = doc.styleSheets[indexList[key]]; + } + if(style === undefined){ + return sheetStyle.cssText + } + sheetStyle.cssText = sheetStyle.cssText + '\n' + (style || '') + } : function(key,style,doc){ + doc = doc || document; + var head = doc.getElementsByTagName('head')[0],node; + if(!(node = doc.getElementById(key))){ + if(style === undefined){ + return '' + } + node = doc.createElement('style'); + node.id = key; + head.appendChild(node) + } + if(style === undefined){ + return node.innerHTML + } + if(style !== ''){ + node.innerHTML = node.innerHTML + '\n' + style; + }else{ + head.removeChild(node) + } + }, + domReady : function (onready) { + var doc = window.document; + if (doc.readyState === "complete") { + onready(); + }else{ + if (isIE) { + (function () { + if (doc.isReady) return; + try { + doc.documentElement.doScroll("left"); + } catch (error) { + setTimeout(arguments.callee, 0); + return; + } + onready(); + })(); + window.attachEvent('onload', function(){ + onready() + }); + } else { + doc.addEventListener("DOMContentLoaded", function () { + doc.removeEventListener("DOMContentLoaded", arguments.callee, false); + onready(); + }, false); + window.addEventListener('load', function(){onready()}, false); + } + } + + }, + each : function(obj, iterator, context) { + if (obj == null) return; + if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if(iterator.call(context, obj[i], i, obj) === false) + return false; + } + } else { + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + if(iterator.call(context, obj[key], key, obj) === false) + return false; + } + } + } + }, + inArray : function(arr,item){ + var index = -1; + this.each(arr,function(v,i){ + if(v === item){ + index = i; + return false; + } + }); + return index; + }, + pushItem : function(arr,item){ + if(this.inArray(arr,item)==-1){ + arr.push(item) + } + }, + trim: function (str) { + return str.replace(/(^[ \t\n\r]+)|([ \t\n\r]+$)/g, ''); + }, + indexOf: function (array, item, start) { + var index = -1; + start = this.isNumber(start) ? start : 0; + this.each(array, function (v, i) { + if (i >= start && v === item) { + index = i; + return false; + } + }); + return index; + }, + hasClass: function (element, className) { + className = className.replace(/(^[ ]+)|([ ]+$)/g, '').replace(/[ ]{2,}/g, ' ').split(' '); + for (var i = 0, ci, cls = element.className; ci = className[i++];) { + if (!new RegExp('\\b' + ci + '\\b', 'i').test(cls)) { + return false; + } + } + return i - 1 == className.length; + }, + addClass:function (elm, classNames) { + if(!elm)return; + classNames = this.trim(classNames).replace(/[ ]{2,}/g,' ').split(' '); + for(var i = 0,ci,cls = elm.className;ci=classNames[i++];){ + if(!new RegExp('\\b' + ci + '\\b').test(cls)){ + cls += ' ' + ci; + } + } + elm.className = utils.trim(cls); + }, + removeClass:function (elm, classNames) { + classNames = this.isArray(classNames) ? classNames : + this.trim(classNames).replace(/[ ]{2,}/g,' ').split(' '); + for(var i = 0,ci,cls = elm.className;ci=classNames[i++];){ + cls = cls.replace(new RegExp('\\b' + ci + '\\b'),'') + } + cls = this.trim(cls).replace(/[ ]{2,}/g,' '); + elm.className = cls; + !cls && elm.removeAttribute('className'); + }, + on: function (element, type, handler) { + var types = this.isArray(type) ? type : type.split(/\s+/), + k = types.length; + if (k) while (k--) { + type = types[k]; + if (element.addEventListener) { + element.addEventListener(type, handler, false); + } else { + if (!handler._d) { + handler._d = { + els : [] + }; + } + var key = type + handler.toString(),index = utils.indexOf(handler._d.els,element); + if (!handler._d[key] || index == -1) { + if(index == -1){ + handler._d.els.push(element); + } + if(!handler._d[key]){ + handler._d[key] = function (evt) { + return handler.call(evt.srcElement, evt || window.event); + }; + } + + + element.attachEvent('on' + type, handler._d[key]); + } + } + } + element = null; + }, + off: function (element, type, handler) { + var types = this.isArray(type) ? type : type.split(/\s+/), + k = types.length; + if (k) while (k--) { + type = types[k]; + if (element.removeEventListener) { + element.removeEventListener(type, handler, false); + } else { + var key = type + handler.toString(); + try{ + element.detachEvent('on' + type, handler._d ? handler._d[key] : handler); + }catch(e){} + if (handler._d && handler._d[key]) { + var index = utils.indexOf(handler._d.els,element); + if(index!=-1){ + handler._d.els.splice(index,1); + } + handler._d.els.length == 0 && delete handler._d[key]; + } + } + } + }, + loadFile : function () { + var tmpList = []; + function getItem(doc,obj){ + try{ + for(var i= 0,ci;ci=tmpList[i++];){ + if(ci.doc === doc && ci.url == (obj.src || obj.href)){ + return ci; + } + } + }catch(e){ + return null; + } + + } + return function (doc, obj, fn) { + var item = getItem(doc,obj); + if (item) { + if(item.ready){ + fn && fn(); + }else{ + item.funs.push(fn) + } + return; + } + tmpList.push({ + doc:doc, + url:obj.src||obj.href, + funs:[fn] + }); + if (!doc.body) { + var html = []; + for(var p in obj){ + if(p == 'tag')continue; + html.push(p + '="' + obj[p] + '"') + } + doc.write('<' + obj.tag + ' ' + html.join(' ') + ' >'); + return; + } + if (obj.id && doc.getElementById(obj.id)) { + return; + } + var element = doc.createElement(obj.tag); + delete obj.tag; + for (var p in obj) { + element.setAttribute(p, obj[p]); + } + element.onload = element.onreadystatechange = function () { + if (!this.readyState || /loaded|complete/.test(this.readyState)) { + item = getItem(doc,obj); + if (item.funs.length > 0) { + item.ready = 1; + for (var fi; fi = item.funs.pop();) { + fi(); + } + } + element.onload = element.onreadystatechange = null; + } + }; + element.onerror = function(){ + throw Error('The load '+(obj.href||obj.src)+' fails,check the url') + }; + doc.getElementsByTagName("head")[0].appendChild(element); + } + }() + }; + utils.each(['String', 'Function', 'Array', 'Number', 'RegExp', 'Object','Boolean'], function (v) { + utils['is' + v] = function (obj) { + return Object.prototype.toString.apply(obj) == '[object ' + v + ']'; + } + }); + var parselist = {}; + UE.parse = { + register : function(parseName,fn){ + parselist[parseName] = fn; + }, + load : function(opt){ + utils.each(parselist,function(v){ + v.call(opt,utils); + }) + } + }; + uParse = function(selector,opt){ + utils.domReady(function(){ + var contents; + if(document.querySelectorAll){ + contents = document.querySelectorAll(selector) + }else{ + if(/^#/.test(selector)){ + contents = [document.getElementById(selector.replace(/^#/,''))] + }else if(/^\./.test(selector)){ + var contents = []; + utils.each(document.getElementsByTagName('*'),function(node){ + if(node.className && new RegExp('\\b' + selector.replace(/^\./,'') + '\\b','i').test(node.className)){ + contents.push(node) + } + }) + }else{ + contents = document.getElementsByTagName(selector) + } + } + utils.each(contents,function(v){ + UE.parse.load(utils.extend({root:v,selector:selector},opt)) + }) + }) + } +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_parse/table.js b/nezha-fronted/static/ueditor-1.4.3.3/_parse/table.js new file mode 100644 index 000000000..3e24f313d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_parse/table.js @@ -0,0 +1,161 @@ +UE.parse.register('table', function (utils) { + var me = this, + root = this.root, + tables = root.getElementsByTagName('table'); + if (tables.length) { + var selector = this.selector; + //追加默认的表格样式 + utils.cssRule('table', + selector + ' table.noBorderTable td,' + + selector + ' table.noBorderTable th,' + + selector + ' table.noBorderTable caption{border:1px dashed #ddd !important}' + + selector + ' table.sortEnabled tr.firstRow th,' + selector + ' table.sortEnabled tr.firstRow td{padding-right:20px; background-repeat: no-repeat;' + + 'background-position: center right; background-image:url(' + this.rootPath + 'themes/default/images/sortable.png);}' + + selector + ' table.sortEnabled tr.firstRow th:hover,' + selector + ' table.sortEnabled tr.firstRow td:hover{background-color: #EEE;}' + + selector + ' table{margin-bottom:10px;border-collapse:collapse;display:table;}' + + selector + ' td,' + selector + ' th{ background:white; padding: 5px 10px;border: 1px solid #DDD;}' + + selector + ' caption{border:1px dashed #DDD;border-bottom:0;padding:3px;text-align:center;}' + + selector + ' th{border-top:1px solid #BBB;background:#F7F7F7;}' + + selector + ' table tr.firstRow th{border-top:2px solid #BBB;background:#F7F7F7;}' + + selector + ' tr.ue-table-interlace-color-single td{ background: #fcfcfc; }' + + selector + ' tr.ue-table-interlace-color-double td{ background: #f7faff; }' + + selector + ' td p{margin:0;padding:0;}', + document); + //填充空的单元格 + + utils.each('td th caption'.split(' '), function (tag) { + var cells = root.getElementsByTagName(tag); + cells.length && utils.each(cells, function (node) { + if (!node.firstChild) { + node.innerHTML = ' '; + + } + }) + }); + + //表格可排序 + var tables = root.getElementsByTagName('table'); + utils.each(tables, function (table) { + if (/\bsortEnabled\b/.test(table.className)) { + utils.on(table, 'click', function(e){ + var target = e.target || e.srcElement, + cell = findParentByTagName(target, ['td', 'th']); + var table = findParentByTagName(target, 'table'), + colIndex = utils.indexOf(table.rows[0].cells, cell), + sortType = table.getAttribute('data-sort-type'); + if(colIndex != -1) { + sortTable(table, colIndex, me.tableSortCompareFn || sortType); + updateTable(table); + } + }); + } + }); + + //按照标签名查找父节点 + function findParentByTagName(target, tagNames) { + var i, current = target; + tagNames = utils.isArray(tagNames) ? tagNames:[tagNames]; + while(current){ + for(i = 0;i < tagNames.length; i++) { + if(current.tagName == tagNames[i].toUpperCase()) return current; + } + current = current.parentNode; + } + return null; + } + //表格排序 + function sortTable(table, sortByCellIndex, compareFn) { + var rows = table.rows, + trArray = [], + flag = rows[0].cells[0].tagName === "TH", + lastRowIndex = 0; + + for (var i = 0,len = rows.length; i < len; i++) { + trArray[i] = rows[i]; + } + + var Fn = { + 'reversecurrent': function(td1,td2){ + return 1; + }, + 'orderbyasc': function(td1,td2){ + var value1 = td1.innerText||td1.textContent, + value2 = td2.innerText||td2.textContent; + return value1.localeCompare(value2); + }, + 'reversebyasc': function(td1,td2){ + var value1 = td1.innerHTML, + value2 = td2.innerHTML; + return value2.localeCompare(value1); + }, + 'orderbynum': function(td1,td2){ + var value1 = td1[utils.isIE ? 'innerText':'textContent'].match(/\d+/), + value2 = td2[utils.isIE ? 'innerText':'textContent'].match(/\d+/); + if(value1) value1 = +value1[0]; + if(value2) value2 = +value2[0]; + return (value1||0) - (value2||0); + }, + 'reversebynum': function(td1,td2){ + var value1 = td1[utils.isIE ? 'innerText':'textContent'].match(/\d+/), + value2 = td2[utils.isIE ? 'innerText':'textContent'].match(/\d+/); + if(value1) value1 = +value1[0]; + if(value2) value2 = +value2[0]; + return (value2||0) - (value1||0); + } + }; + + //对表格设置排序的标记data-sort-type + table.setAttribute('data-sort-type', compareFn && typeof compareFn === "string" && Fn[compareFn] ? compareFn:''); + + //th不参与排序 + flag && trArray.splice(0, 1); + trArray = sort(trArray,function (tr1, tr2) { + var result; + if (compareFn && typeof compareFn === "function") { + result = compareFn.call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex]); + } else if (compareFn && typeof compareFn === "number") { + result = 1; + } else if (compareFn && typeof compareFn === "string" && Fn[compareFn]) { + result = Fn[compareFn].call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex]); + } else { + result = Fn['orderbyasc'].call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex]); + } + return result; + }); + var fragment = table.ownerDocument.createDocumentFragment(); + for (var j = 0, len = trArray.length; j < len; j++) { + fragment.appendChild(trArray[j]); + } + var tbody = table.getElementsByTagName("tbody")[0]; + if(!lastRowIndex){ + tbody.appendChild(fragment); + }else{ + tbody.insertBefore(fragment,rows[lastRowIndex- range.endRowIndex + range.beginRowIndex - 1]) + } + } + //冒泡排序 + function sort(array, compareFn){ + compareFn = compareFn || function(item1, item2){ return item1.localeCompare(item2);}; + for(var i= 0,len = array.length; i 0){ + var t = array[i]; + array[i] = array[j]; + array[j] = t; + } + } + } + return array; + } + //更新表格 + function updateTable(table) { + //给第一行设置firstRow的样式名称,在排序图标的样式上使用到 + if(!utils.hasClass(table.rows[0], "firstRow")) { + for(var i = 1; i< table.rows.length; i++) { + utils.removeClass(table.rows[i], "firstRow"); + } + utils.addClass(table.rows[0], "firstRow"); + } + } + } +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_parse/video.js b/nezha-fronted/static/ueditor-1.4.3.3/_parse/video.js new file mode 100644 index 000000000..da8ff80eb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_parse/video.js @@ -0,0 +1,34 @@ +UE.parse.register('vedio',function(utils){ + var video = this.root.getElementsByTagName('video'), + audio = this.root.getElementsByTagName('audio'); + + document.createElement('video');document.createElement('audio'); + if(video.length || audio.length){ + var sourcePath = utils.removeLastbs(this.rootPath), + jsurl = sourcePath + '/third-party/video-js/video.js', + cssurl = sourcePath + '/third-party/video-js/video-js.min.css', + swfUrl = sourcePath + '/third-party/video-js/video-js.swf'; + + if(window.videojs) { + videojs.autoSetup(); + } else { + utils.loadFile(document,{ + id : "video_css", + tag : "link", + rel : "stylesheet", + type : "text/css", + href : cssurl + }); + utils.loadFile(document,{ + id : "video_js", + src : jsurl, + tag : "script", + type : "text/javascript" + },function(){ + videojs.options.flash.swf = swfUrl; + videojs.autoSetup(); + }); + } + + } +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/adapter/autosave.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/adapter/autosave.js new file mode 100644 index 000000000..1923aa874 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/adapter/autosave.js @@ -0,0 +1,18 @@ +UE.registerUI('autosave', function(editor) { + var timer = null,uid = null; + editor.on('afterautosave',function(){ + clearTimeout(timer); + + timer = setTimeout(function(){ + if(uid){ + editor.trigger('hidemessage',uid); + } + uid = editor.trigger('showmessage',{ + content : editor.getLang('autosave.success'), + timeout : 2000 + }); + + },2000) + }) + +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/adapter/editor.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/adapter/editor.js new file mode 100644 index 000000000..f0dfb77ef --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/adapter/editor.js @@ -0,0 +1,858 @@ +///import core +///commands 全屏 +///commandsName FullScreen +///commandsTitle 全屏 +(function () { + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + UIBase = baidu.editor.ui.UIBase, + domUtils = baidu.editor.dom.domUtils; + var nodeStack = []; + + function EditorUI(options) { + this.initOptions(options); + this.initEditorUI(); + } + + EditorUI.prototype = { + uiName:'editor', + initEditorUI:function () { + this.editor.ui = this; + this._dialogs = {}; + this.initUIBase(); + this._initToolbars(); + var editor = this.editor, + me = this; + + editor.addListener('ready', function () { + //提供getDialog方法 + editor.getDialog = function (name) { + return editor.ui._dialogs[name + "Dialog"]; + }; + domUtils.on(editor.window, 'scroll', function (evt) { + baidu.editor.ui.Popup.postHide(evt); + }); + //提供编辑器实时宽高(全屏时宽高不变化) + editor.ui._actualFrameWidth = editor.options.initialFrameWidth; + + UE.browser.ie && UE.browser.version === 6 && editor.container.ownerDocument.execCommand("BackgroundImageCache", false, true); + + //display bottom-bar label based on config + if (editor.options.elementPathEnabled) { + editor.ui.getDom('elementpath').innerHTML = '
' + editor.getLang("elementPathTip") + ':
'; + } + if (editor.options.wordCount) { + function countFn() { + setCount(editor,me); + domUtils.un(editor.document, "click", arguments.callee); + } + domUtils.on(editor.document, "click", countFn); + editor.ui.getDom('wordcount').innerHTML = editor.getLang("wordCountTip"); + } + editor.ui._scale(); + if (editor.options.scaleEnabled) { + if (editor.autoHeightEnabled) { + editor.disableAutoHeight(); + } + me.enableScale(); + } else { + me.disableScale(); + } + if (!editor.options.elementPathEnabled && !editor.options.wordCount && !editor.options.scaleEnabled) { + editor.ui.getDom('elementpath').style.display = "none"; + editor.ui.getDom('wordcount').style.display = "none"; + editor.ui.getDom('scale').style.display = "none"; + } + + if (!editor.selection.isFocus())return; + editor.fireEvent('selectionchange', false, true); + + + }); + + editor.addListener('mousedown', function (t, evt) { + var el = evt.target || evt.srcElement; + baidu.editor.ui.Popup.postHide(evt, el); + baidu.editor.ui.ShortCutMenu.postHide(evt); + + }); + editor.addListener("delcells", function () { + if (UE.ui['edittip']) { + new UE.ui['edittip'](editor); + } + editor.getDialog('edittip').open(); + }); + + var pastePop, isPaste = false, timer; + editor.addListener("afterpaste", function () { + if(editor.queryCommandState('pasteplain')) + return; + if(baidu.editor.ui.PastePicker){ + pastePop = new baidu.editor.ui.Popup({ + content:new baidu.editor.ui.PastePicker({editor:editor}), + editor:editor, + className:'edui-wordpastepop' + }); + pastePop.render(); + } + isPaste = true; + }); + + editor.addListener("afterinserthtml", function () { + clearTimeout(timer); + timer = setTimeout(function () { + if (pastePop && (isPaste || editor.ui._isTransfer)) { + if(pastePop.isHidden()){ + var span = domUtils.createElement(editor.document, 'span', { + 'style':"line-height:0px;", + 'innerHTML':'\ufeff' + }), + range = editor.selection.getRange(); + range.insertNode(span); + var tmp= getDomNode(span, 'firstChild', 'previousSibling'); + tmp && pastePop.showAnchor(tmp.nodeType == 3 ? tmp.parentNode : tmp); + domUtils.remove(span); + }else{ + pastePop.show(); + } + delete editor.ui._isTransfer; + isPaste = false; + } + }, 200) + }); + editor.addListener('contextmenu', function (t, evt) { + baidu.editor.ui.Popup.postHide(evt); + }); + editor.addListener('keydown', function (t, evt) { + if (pastePop) pastePop.dispose(evt); + var keyCode = evt.keyCode || evt.which; + if(evt.altKey&&keyCode==90){ + UE.ui.buttons['fullscreen'].onclick(); + } + }); + editor.addListener('wordcount', function (type) { + setCount(this,me); + }); + function setCount(editor,ui) { + editor.setOpt({ + wordCount:true, + maximumWords:10000, + wordCountMsg:editor.options.wordCountMsg || editor.getLang("wordCountMsg"), + wordOverFlowMsg:editor.options.wordOverFlowMsg || editor.getLang("wordOverFlowMsg") + }); + var opt = editor.options, + max = opt.maximumWords, + msg = opt.wordCountMsg , + errMsg = opt.wordOverFlowMsg, + countDom = ui.getDom('wordcount'); + if (!opt.wordCount) { + return; + } + var count = editor.getContentLength(true); + if (count > max) { + countDom.innerHTML = errMsg; + editor.fireEvent("wordcountoverflow"); + } else { + countDom.innerHTML = msg.replace("{#leave}", max - count).replace("{#count}", count); + } + } + + editor.addListener('selectionchange', function () { + if (editor.options.elementPathEnabled) { + me[(editor.queryCommandState('elementpath') == -1 ? 'dis' : 'en') + 'ableElementPath']() + } + if (editor.options.scaleEnabled) { + me[(editor.queryCommandState('scale') == -1 ? 'dis' : 'en') + 'ableScale'](); + + } + }); + var popup = new baidu.editor.ui.Popup({ + editor:editor, + content:'', + className:'edui-bubble', + _onEditButtonClick:function () { + this.hide(); + editor.ui._dialogs.linkDialog.open(); + }, + _onImgEditButtonClick:function (name) { + this.hide(); + editor.ui._dialogs[name] && editor.ui._dialogs[name].open(); + + }, + _onImgSetFloat:function (value) { + this.hide(); + editor.execCommand("imagefloat", value); + + }, + _setIframeAlign:function (value) { + var frame = popup.anchorEl; + var newFrame = frame.cloneNode(true); + switch (value) { + case -2: + newFrame.setAttribute("align", ""); + break; + case -1: + newFrame.setAttribute("align", "left"); + break; + case 1: + newFrame.setAttribute("align", "right"); + break; + } + frame.parentNode.insertBefore(newFrame, frame); + domUtils.remove(frame); + popup.anchorEl = newFrame; + popup.showAnchor(popup.anchorEl); + }, + _updateIframe:function () { + var frame = editor._iframe = popup.anchorEl; + if(domUtils.hasClass(frame, 'ueditor_baidumap')) { + editor.selection.getRange().selectNode(frame).select(); + editor.ui._dialogs.mapDialog.open(); + popup.hide(); + } else { + editor.ui._dialogs.insertframeDialog.open(); + popup.hide(); + } + }, + _onRemoveButtonClick:function (cmdName) { + editor.execCommand(cmdName); + this.hide(); + }, + queryAutoHide:function (el) { + if (el && el.ownerDocument == editor.document) { + if (el.tagName.toLowerCase() == 'img' || domUtils.findParentByTagName(el, 'a', true)) { + return el !== popup.anchorEl; + } + } + return baidu.editor.ui.Popup.prototype.queryAutoHide.call(this, el); + } + }); + popup.render(); + if (editor.options.imagePopup) { + editor.addListener('mouseover', function (t, evt) { + evt = evt || window.event; + var el = evt.target || evt.srcElement; + if (editor.ui._dialogs.insertframeDialog && /iframe/ig.test(el.tagName)) { + var html = popup.formatHtml( + '' + editor.getLang("property") + ': ' + editor.getLang("default") + '  ' + editor.getLang("justifyleft") + '  ' + editor.getLang("justifyright") + '  ' + + ' ' + editor.getLang("modify") + ''); + if (html) { + popup.getDom('content').innerHTML = html; + popup.anchorEl = el; + popup.showAnchor(popup.anchorEl); + } else { + popup.hide(); + } + } + }); + editor.addListener('selectionchange', function (t, causeByUi) { + if (!causeByUi) return; + var html = '', str = "", + img = editor.selection.getRange().getClosedNode(), + dialogs = editor.ui._dialogs; + if (img && img.tagName == 'IMG') { + var dialogName = 'insertimageDialog'; + if (img.className.indexOf("edui-faked-video") != -1 || img.className.indexOf("edui-upload-video") != -1) { + dialogName = "insertvideoDialog" + } + if (img.className.indexOf("edui-faked-webapp") != -1) { + dialogName = "webappDialog" + } + if (img.src.indexOf("http://api.map.baidu.com") != -1) { + dialogName = "mapDialog" + } + if (img.className.indexOf("edui-faked-music") != -1) { + dialogName = "musicDialog" + } + if (img.src.indexOf("http://maps.google.com/maps/api/staticmap") != -1) { + dialogName = "gmapDialog" + } + if (img.getAttribute("anchorname")) { + dialogName = "anchorDialog"; + html = popup.formatHtml( + '' + editor.getLang("property") + ': ' + editor.getLang("modify") + '  ' + + '' + editor.getLang("delete") + ''); + } + if (img.getAttribute("word_img")) { + //todo 放到dialog去做查询 + editor.word_img = [img.getAttribute("word_img")]; + dialogName = "wordimageDialog" + } + if(domUtils.hasClass(img, 'loadingclass') || domUtils.hasClass(img, 'loaderrorclass')) { + dialogName = ""; + } + if (!dialogs[dialogName]) { + return; + } + str = '' + editor.getLang("property") + ': '+ + '' + editor.getLang("default") + '  ' + + '' + editor.getLang("justifyleft") + '  ' + + '' + editor.getLang("justifyright") + '  ' + + '' + editor.getLang("justifycenter") + '  '+ + '' + editor.getLang("modify") + ''; + + !html && (html = popup.formatHtml(str)) + + } + if (editor.ui._dialogs.linkDialog) { + var link = editor.queryCommandValue('link'); + var url; + if (link && (url = (link.getAttribute('_href') || link.getAttribute('href', 2)))) { + var txt = url; + if (url.length > 30) { + txt = url.substring(0, 20) + "..."; + } + if (html) { + html += '
' + } + html += popup.formatHtml( + '' + editor.getLang("anthorMsg") + ': ' + txt + '' + + ' ' + editor.getLang("modify") + '' + + ' ' + editor.getLang("clear") + ''); + popup.showAnchor(link); + } + } + + if (html) { + popup.getDom('content').innerHTML = html; + popup.anchorEl = img || link; + popup.showAnchor(popup.anchorEl); + } else { + popup.hide(); + } + }); + } + + }, + _initToolbars:function () { + var editor = this.editor; + var toolbars = this.toolbars || []; + var toolbarUis = []; + for (var i = 0; i < toolbars.length; i++) { + var toolbar = toolbars[i]; + var toolbarUi = new baidu.editor.ui.Toolbar({theme:editor.options.theme}); + for (var j = 0; j < toolbar.length; j++) { + var toolbarItem = toolbar[j]; + var toolbarItemUi = null; + if (typeof toolbarItem == 'string') { + toolbarItem = toolbarItem.toLowerCase(); + if (toolbarItem == '|') { + toolbarItem = 'Separator'; + } + if(toolbarItem == '||'){ + toolbarItem = 'Breakline'; + } + if (baidu.editor.ui[toolbarItem]) { + toolbarItemUi = new baidu.editor.ui[toolbarItem](editor); + } + + //fullscreen这里单独处理一下,放到首行去 + if (toolbarItem == 'fullscreen') { + if (toolbarUis && toolbarUis[0]) { + toolbarUis[0].items.splice(0, 0, toolbarItemUi); + } else { + toolbarItemUi && toolbarUi.items.splice(0, 0, toolbarItemUi); + } + + continue; + + + } + } else { + toolbarItemUi = toolbarItem; + } + if (toolbarItemUi && toolbarItemUi.id) { + + toolbarUi.add(toolbarItemUi); + } + } + toolbarUis[i] = toolbarUi; + } + + //接受外部定制的UI + + utils.each(UE._customizeUI,function(obj,key){ + var itemUI,index; + if(obj.id && obj.id != editor.key){ + return false; + } + itemUI = obj.execFn.call(editor,editor,key); + if(itemUI){ + index = obj.index; + if(index === undefined){ + index = toolbarUi.items.length; + } + toolbarUi.add(itemUI,index) + } + }); + + this.toolbars = toolbarUis; + }, + getHtmlTpl:function () { + return '
' + + '
' + + (this.toolbars.length ? + '
' + + this.renderToolbarBoxHtml() + + '
' : '') + + '' + + '
' + + '
' + + '
' + + '
' + + //modify wdcount by matao + '
' + + '' + + '' + + '' + + '
' + + '
' + + '
'; + }, + showWordImageDialog:function () { + this._dialogs['wordimageDialog'].open(); + }, + renderToolbarBoxHtml:function () { + var buff = []; + for (var i = 0; i < this.toolbars.length; i++) { + buff.push(this.toolbars[i].renderHtml()); + } + return buff.join(''); + }, + setFullScreen:function (fullscreen) { + + var editor = this.editor, + container = editor.container.parentNode.parentNode; + if (this._fullscreen != fullscreen) { + this._fullscreen = fullscreen; + this.editor.fireEvent('beforefullscreenchange', fullscreen); + if (baidu.editor.browser.gecko) { + var bk = editor.selection.getRange().createBookmark(); + } + if (fullscreen) { + while (container.tagName != "BODY") { + var position = baidu.editor.dom.domUtils.getComputedStyle(container, "position"); + nodeStack.push(position); + container.style.position = "static"; + container = container.parentNode; + } + this._bakHtmlOverflow = document.documentElement.style.overflow; + this._bakBodyOverflow = document.body.style.overflow; + this._bakAutoHeight = this.editor.autoHeightEnabled; + this._bakScrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop); + + this._bakEditorContaninerWidth = editor.iframe.parentNode.offsetWidth; + if (this._bakAutoHeight) { + //当全屏时不能执行自动长高 + editor.autoHeightEnabled = false; + this.editor.disableAutoHeight(); + } + + document.documentElement.style.overflow = 'hidden'; + //修复,滚动条不收起的问题 + + window.scrollTo(0,window.scrollY); + this._bakCssText = this.getDom().style.cssText; + this._bakCssText1 = this.getDom('iframeholder').style.cssText; + editor.iframe.parentNode.style.width = ''; + this._updateFullScreen(); + } else { + while (container.tagName != "BODY") { + container.style.position = nodeStack.shift(); + container = container.parentNode; + } + this.getDom().style.cssText = this._bakCssText; + this.getDom('iframeholder').style.cssText = this._bakCssText1; + if (this._bakAutoHeight) { + editor.autoHeightEnabled = true; + this.editor.enableAutoHeight(); + } + + document.documentElement.style.overflow = this._bakHtmlOverflow; + document.body.style.overflow = this._bakBodyOverflow; + editor.iframe.parentNode.style.width = this._bakEditorContaninerWidth + 'px'; + window.scrollTo(0, this._bakScrollTop); + } + if (browser.gecko && editor.body.contentEditable === 'true') { + var input = document.createElement('input'); + document.body.appendChild(input); + editor.body.contentEditable = false; + setTimeout(function () { + input.focus(); + setTimeout(function () { + editor.body.contentEditable = true; + editor.fireEvent('fullscreenchanged', fullscreen); + editor.selection.getRange().moveToBookmark(bk).select(true); + baidu.editor.dom.domUtils.remove(input); + fullscreen && window.scroll(0, 0); + }, 0) + }, 0) + } + + if(editor.body.contentEditable === 'true'){ + this.editor.fireEvent('fullscreenchanged', fullscreen); + this.triggerLayout(); + } + + } + }, + _updateFullScreen:function () { + if (this._fullscreen) { + var vpRect = uiUtils.getViewportRect(); + this.getDom().style.cssText = 'border:0;position:absolute;left:0;top:' + (this.editor.options.topOffset || 0) + 'px;width:' + vpRect.width + 'px;height:' + vpRect.height + 'px;z-index:' + (this.getDom().style.zIndex * 1 + 100); + uiUtils.setViewportOffset(this.getDom(), { left:0, top:this.editor.options.topOffset || 0 }); + this.editor.setHeight(vpRect.height - this.getDom('toolbarbox').offsetHeight - this.getDom('bottombar').offsetHeight - (this.editor.options.topOffset || 0),true); + //不手动调一下,会导致全屏失效 + if(browser.gecko){ + try{ + window.onresize(); + }catch(e){ + + } + + } + } + }, + _updateElementPath:function () { + var bottom = this.getDom('elementpath'), list; + if (this.elementPathEnabled && (list = this.editor.queryCommandValue('elementpath'))) { + + var buff = []; + for (var i = 0, ci; ci = list[i]; i++) { + buff[i] = this.formatHtml('' + ci + ''); + } + bottom.innerHTML = '
' + this.editor.getLang("elementPathTip") + ': ' + buff.join(' > ') + '
'; + + } else { + bottom.style.display = 'none' + } + }, + disableElementPath:function () { + var bottom = this.getDom('elementpath'); + bottom.innerHTML = ''; + bottom.style.display = 'none'; + this.elementPathEnabled = false; + + }, + enableElementPath:function () { + var bottom = this.getDom('elementpath'); + bottom.style.display = ''; + this.elementPathEnabled = true; + this._updateElementPath(); + }, + _scale:function () { + var doc = document, + editor = this.editor, + editorHolder = editor.container, + editorDocument = editor.document, + toolbarBox = this.getDom("toolbarbox"), + bottombar = this.getDom("bottombar"), + scale = this.getDom("scale"), + scalelayer = this.getDom("scalelayer"); + + var isMouseMove = false, + position = null, + minEditorHeight = 0, + minEditorWidth = editor.options.minFrameWidth, + pageX = 0, + pageY = 0, + scaleWidth = 0, + scaleHeight = 0; + + function down() { + position = domUtils.getXY(editorHolder); + + if (!minEditorHeight) { + minEditorHeight = editor.options.minFrameHeight + toolbarBox.offsetHeight + bottombar.offsetHeight; + } + + scalelayer.style.cssText = "position:absolute;left:0;display:;top:0;background-color:#41ABFF;opacity:0.4;filter: Alpha(opacity=40);width:" + editorHolder.offsetWidth + "px;height:" + + editorHolder.offsetHeight + "px;z-index:" + (editor.options.zIndex + 1); + + domUtils.on(doc, "mousemove", move); + domUtils.on(editorDocument, "mouseup", up); + domUtils.on(doc, "mouseup", up); + } + + var me = this; + //by xuheng 全屏时关掉缩放 + this.editor.addListener('fullscreenchanged', function (e, fullScreen) { + if (fullScreen) { + me.disableScale(); + + } else { + if (me.editor.options.scaleEnabled) { + me.enableScale(); + var tmpNode = me.editor.document.createElement('span'); + me.editor.body.appendChild(tmpNode); + me.editor.body.style.height = Math.max(domUtils.getXY(tmpNode).y, me.editor.iframe.offsetHeight - 20) + 'px'; + domUtils.remove(tmpNode) + } + } + }); + function move(event) { + clearSelection(); + var e = event || window.event; + pageX = e.pageX || (doc.documentElement.scrollLeft + e.clientX); + pageY = e.pageY || (doc.documentElement.scrollTop + e.clientY); + scaleWidth = pageX - position.x; + scaleHeight = pageY - position.y; + + if (scaleWidth >= minEditorWidth) { + isMouseMove = true; + scalelayer.style.width = scaleWidth + 'px'; + } + if (scaleHeight >= minEditorHeight) { + isMouseMove = true; + scalelayer.style.height = scaleHeight + "px"; + } + } + + function up() { + if (isMouseMove) { + isMouseMove = false; + editor.ui._actualFrameWidth = scalelayer.offsetWidth - 2; + editorHolder.style.width = editor.ui._actualFrameWidth + 'px'; + + editor.setHeight(scalelayer.offsetHeight - bottombar.offsetHeight - toolbarBox.offsetHeight - 2,true); + } + if (scalelayer) { + scalelayer.style.display = "none"; + } + clearSelection(); + domUtils.un(doc, "mousemove", move); + domUtils.un(editorDocument, "mouseup", up); + domUtils.un(doc, "mouseup", up); + } + + function clearSelection() { + if (browser.ie) + doc.selection.clear(); + else + window.getSelection().removeAllRanges(); + } + + this.enableScale = function () { + //trace:2868 + if (editor.queryCommandState("source") == 1) return; + scale.style.display = ""; + this.scaleEnabled = true; + domUtils.on(scale, "mousedown", down); + }; + this.disableScale = function () { + scale.style.display = "none"; + this.scaleEnabled = false; + domUtils.un(scale, "mousedown", down); + }; + }, + isFullScreen:function () { + return this._fullscreen; + }, + postRender:function () { + UIBase.prototype.postRender.call(this); + for (var i = 0; i < this.toolbars.length; i++) { + this.toolbars[i].postRender(); + } + var me = this; + var timerId, + domUtils = baidu.editor.dom.domUtils, + updateFullScreenTime = function () { + clearTimeout(timerId); + timerId = setTimeout(function () { + me._updateFullScreen(); + }); + }; + domUtils.on(window, 'resize', updateFullScreenTime); + + me.addListener('destroy', function () { + domUtils.un(window, 'resize', updateFullScreenTime); + clearTimeout(timerId); + }) + }, + showToolbarMsg:function (msg, flag) { + this.getDom('toolbarmsg_label').innerHTML = msg; + this.getDom('toolbarmsg').style.display = ''; + // + if (!flag) { + var w = this.getDom('upload_dialog'); + w.style.display = 'none'; + } + }, + hideToolbarMsg:function () { + this.getDom('toolbarmsg').style.display = 'none'; + }, + mapUrl:function (url) { + return url ? url.replace('~/', this.editor.options.UEDITOR_HOME_URL || '') : '' + }, + triggerLayout:function () { + var dom = this.getDom(); + if (dom.style.zoom == '1') { + dom.style.zoom = '100%'; + } else { + dom.style.zoom = '1'; + } + } + }; + utils.inherits(EditorUI, baidu.editor.ui.UIBase); + + + var instances = {}; + + + UE.ui.Editor = function (options) { + var editor = new UE.Editor(options); + editor.options.editor = editor; + utils.loadFile(document, { + href:editor.options.themePath + editor.options.theme + "/_css/ueditor.css", + tag:"link", + type:"text/css", + rel:"stylesheet" + }); + + var oldRender = editor.render; + editor.render = function (holder) { + if (holder.constructor === String) { + editor.key = holder; + instances[holder] = editor; + } + utils.domReady(function () { + editor.langIsReady ? renderUI() : editor.addListener("langReady", renderUI); + function renderUI() { + editor.setOpt({ + labelMap:editor.options.labelMap || editor.getLang('labelMap') + }); + new EditorUI(editor.options); + if (holder) { + if (holder.constructor === String) { + holder = document.getElementById(holder); + } + holder && holder.getAttribute('name') && ( editor.options.textarea = holder.getAttribute('name')); + if (holder && /script|textarea/ig.test(holder.tagName)) { + var newDiv = document.createElement('div'); + holder.parentNode.insertBefore(newDiv, holder); + var cont = holder.value || holder.innerHTML; + editor.options.initialContent = /^[\t\r\n ]*$/.test(cont) ? editor.options.initialContent : + cont.replace(/>[\n\r\t]+([ ]{4})+/g, '>') + .replace(/[\n\r\t]+([ ]{4})+[\n\r\t]+<'); + holder.className && (newDiv.className = holder.className); + holder.style.cssText && (newDiv.style.cssText = holder.style.cssText); + if (/textarea/i.test(holder.tagName)) { + editor.textarea = holder; + editor.textarea.style.display = 'none'; + + + } else { + holder.parentNode.removeChild(holder); + + + } + if(holder.id){ + newDiv.id = holder.id; + domUtils.removeAttributes(holder,'id'); + } + holder = newDiv; + holder.innerHTML = ''; + } + + } + domUtils.addClass(holder, "edui-" + editor.options.theme); + editor.ui.render(holder); + var opt = editor.options; + //给实例添加一个编辑器的容器引用 + editor.container = editor.ui.getDom(); + var parents = domUtils.findParents(holder,true); + var displays = []; + for(var i = 0 ,ci;ci=parents[i];i++){ + displays[i] = ci.style.display; + ci.style.display = 'block' + } + if (opt.initialFrameWidth) { + opt.minFrameWidth = opt.initialFrameWidth; + } else { + opt.minFrameWidth = opt.initialFrameWidth = holder.offsetWidth; + var styleWidth = holder.style.width; + if(/%$/.test(styleWidth)) { + opt.initialFrameWidth = styleWidth; + } + } + if (opt.initialFrameHeight) { + opt.minFrameHeight = opt.initialFrameHeight; + } else { + opt.initialFrameHeight = opt.minFrameHeight = holder.offsetHeight; + } + for(var i = 0 ,ci;ci=parents[i];i++){ + ci.style.display = displays[i] + } + //编辑器最外容器设置了高度,会导致,编辑器不占位 + //todo 先去掉,没有找到原因 + if(holder.style.height){ + holder.style.height = '' + } + editor.container.style.width = opt.initialFrameWidth + (/%$/.test(opt.initialFrameWidth) ? '' : 'px'); + editor.container.style.zIndex = opt.zIndex; + oldRender.call(editor, editor.ui.getDom('iframeholder')); + editor.fireEvent("afteruiready"); + } + }) + }; + return editor; + }; + + + /** + * @file + * @name UE + * @short UE + * @desc UEditor的顶部命名空间 + */ + /** + * @name getEditor + * @since 1.2.4+ + * @grammar UE.getEditor(id,[opt]) => Editor实例 + * @desc 提供一个全局的方法得到编辑器实例 + * + * * ''id'' 放置编辑器的容器id, 如果容器下的编辑器已经存在,就直接返回 + * * ''opt'' 编辑器的可选参数 + * @example + * UE.getEditor('containerId',{onready:function(){//创建一个编辑器实例 + * this.setContent('hello') + * }}); + * UE.getEditor('containerId'); //返回刚创建的实例 + * + */ + UE.getEditor = function (id, opt) { + var editor = instances[id]; + if (!editor) { + editor = instances[id] = new UE.ui.Editor(opt); + editor.render(id); + } + return editor; + }; + + + UE.delEditor = function (id) { + var editor; + if (editor = instances[id]) { + editor.key && editor.destroy(); + delete instances[id] + } + }; + + UE.registerUI = function(uiName,fn,index,editorId){ + utils.each(uiName.split(/\s+/), function (name) { + UE._customizeUI[name] = { + id : editorId, + execFn:fn, + index:index + }; + }) + + } + +})(); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/adapter/editorui.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/adapter/editorui.js new file mode 100644 index 000000000..965b8b40d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/adapter/editorui.js @@ -0,0 +1,854 @@ +//ui跟编辑器的适配層 +//那个按钮弹出是dialog,是下拉筐等都是在这个js中配置 +//自己写的ui也要在这里配置,放到baidu.editor.ui下边,当编辑器实例化的时候会根据ueditor.config中的toolbars找到相应的进行实例化 +(function () { + var utils = baidu.editor.utils; + var editorui = baidu.editor.ui; + var _Dialog = editorui.Dialog; + editorui.buttons = {}; + + editorui.Dialog = function (options) { + var dialog = new _Dialog(options); + dialog.addListener('hide', function () { + + if (dialog.editor) { + var editor = dialog.editor; + try { + if (browser.gecko) { + var y = editor.window.scrollY, + x = editor.window.scrollX; + editor.body.focus(); + editor.window.scrollTo(x, y); + } else { + editor.focus(); + } + + + } catch (ex) { + } + } + }); + return dialog; + }; + + var iframeUrlMap = { + 'anchor':'~/dialogs/anchor/anchor.html', + 'insertimage':'~/dialogs/image/image.html', + 'link':'~/dialogs/link/link.html', + 'spechars':'~/dialogs/spechars/spechars.html', + 'searchreplace':'~/dialogs/searchreplace/searchreplace.html', + 'map':'~/dialogs/map/map.html', + 'gmap':'~/dialogs/gmap/gmap.html', + 'insertvideo':'~/dialogs/video/video.html', + 'help':'~/dialogs/help/help.html', + 'preview':'~/dialogs/preview/preview.html', + 'emotion':'~/dialogs/emotion/emotion.html', + 'wordimage':'~/dialogs/wordimage/wordimage.html', + 'attachment':'~/dialogs/attachment/attachment.html', + 'insertframe':'~/dialogs/insertframe/insertframe.html', + 'edittip':'~/dialogs/table/edittip.html', + 'edittable':'~/dialogs/table/edittable.html', + 'edittd':'~/dialogs/table/edittd.html', + 'webapp':'~/dialogs/webapp/webapp.html', + 'snapscreen':'~/dialogs/snapscreen/snapscreen.html', + 'scrawl':'~/dialogs/scrawl/scrawl.html', + 'music':'~/dialogs/music/music.html', + 'template':'~/dialogs/template/template.html', + 'background':'~/dialogs/background/background.html', + 'charts': '~/dialogs/charts/charts.html' + }; + //为工具栏添加按钮,以下都是统一的按钮触发命令,所以写在一起 + var btnCmds = ['undo', 'redo', 'formatmatch', + 'bold', 'italic', 'underline', 'fontborder', 'touppercase', 'tolowercase', + 'strikethrough', 'subscript', 'superscript', 'source', 'indent', 'outdent', + 'blockquote', 'pasteplain', 'pagebreak', + 'selectall', 'print','horizontal', 'removeformat', 'time', 'date', 'unlink', + 'insertparagraphbeforetable', 'insertrow', 'insertcol', 'mergeright', 'mergedown', 'deleterow', + 'deletecol', 'splittorows', 'splittocols', 'splittocells', 'mergecells', 'deletetable', 'drafts']; + + for (var i = 0, ci; ci = btnCmds[i++];) { + ci = ci.toLowerCase(); + editorui[ci] = function (cmd) { + return function (editor) { + var ui = new editorui.Button({ + className:'edui-for-' + cmd, + title:editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd) || '', + onclick:function () { + editor.execCommand(cmd); + }, + theme:editor.options.theme, + showText:false + }); + editorui.buttons[cmd] = ui; + editor.addListener('selectionchange', function (type, causeByUi, uiReady) { + var state = editor.queryCommandState(cmd); + if (state == -1) { + ui.setDisabled(true); + ui.setChecked(false); + } else { + if (!uiReady) { + ui.setDisabled(false); + ui.setChecked(state); + } + } + }); + return ui; + }; + }(ci); + } + + //清除文档 + editorui.cleardoc = function (editor) { + var ui = new editorui.Button({ + className:'edui-for-cleardoc', + title:editor.options.labelMap.cleardoc || editor.getLang("labelMap.cleardoc") || '', + theme:editor.options.theme, + onclick:function () { + if (confirm(editor.getLang("confirmClear"))) { + editor.execCommand('cleardoc'); + } + } + }); + editorui.buttons["cleardoc"] = ui; + editor.addListener('selectionchange', function () { + ui.setDisabled(editor.queryCommandState('cleardoc') == -1); + }); + return ui; + }; + + //排版,图片排版,文字方向 + var typeset = { + 'justify':['left', 'right', 'center', 'justify'], + 'imagefloat':['none', 'left', 'center', 'right'], + 'directionality':['ltr', 'rtl'] + }; + + for (var p in typeset) { + + (function (cmd, val) { + for (var i = 0, ci; ci = val[i++];) { + (function (cmd2) { + editorui[cmd.replace('float', '') + cmd2] = function (editor) { + var ui = new editorui.Button({ + className:'edui-for-' + cmd.replace('float', '') + cmd2, + title:editor.options.labelMap[cmd.replace('float', '') + cmd2] || editor.getLang("labelMap." + cmd.replace('float', '') + cmd2) || '', + theme:editor.options.theme, + onclick:function () { + editor.execCommand(cmd, cmd2); + } + }); + editorui.buttons[cmd] = ui; + editor.addListener('selectionchange', function (type, causeByUi, uiReady) { + ui.setDisabled(editor.queryCommandState(cmd) == -1); + ui.setChecked(editor.queryCommandValue(cmd) == cmd2 && !uiReady); + }); + return ui; + }; + })(ci) + } + })(p, typeset[p]) + } + + //字体颜色和背景颜色 + for (var i = 0, ci; ci = ['backcolor', 'forecolor'][i++];) { + editorui[ci] = function (cmd) { + return function (editor) { + var ui = new editorui.ColorButton({ + className:'edui-for-' + cmd, + color:'default', + title:editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd) || '', + editor:editor, + onpickcolor:function (t, color) { + editor.execCommand(cmd, color); + }, + onpicknocolor:function () { + editor.execCommand(cmd, 'default'); + this.setColor('transparent'); + this.color = 'default'; + }, + onbuttonclick:function () { + editor.execCommand(cmd, this.color); + } + }); + editorui.buttons[cmd] = ui; + editor.addListener('selectionchange', function () { + ui.setDisabled(editor.queryCommandState(cmd) == -1); + }); + return ui; + }; + }(ci); + } + + + var dialogBtns = { + noOk:['searchreplace', 'help', 'spechars', 'webapp','preview'], + ok:['attachment', 'anchor', 'link', 'insertimage', 'map', 'gmap', 'insertframe', 'wordimage', + 'insertvideo', 'insertframe', 'edittip', 'edittable', 'edittd', 'scrawl', 'template', 'music', 'background', 'charts'] + }; + + for (var p in dialogBtns) { + (function (type, vals) { + for (var i = 0, ci; ci = vals[i++];) { + //todo opera下存在问题 + if (browser.opera && ci === "searchreplace") { + continue; + } + (function (cmd) { + editorui[cmd] = function (editor, iframeUrl, title) { + iframeUrl = iframeUrl || (editor.options.iframeUrlMap || {})[cmd] || iframeUrlMap[cmd]; + title = editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd) || ''; + + var dialog; + //没有iframeUrl不创建dialog + if (iframeUrl) { + dialog = new editorui.Dialog(utils.extend({ + iframeUrl:editor.ui.mapUrl(iframeUrl), + editor:editor, + className:'edui-for-' + cmd, + title:title, + holdScroll: cmd === 'insertimage', + fullscreen: /charts|preview/.test(cmd), + closeDialog:editor.getLang("closeDialog") + }, type == 'ok' ? { + buttons:[ + { + className:'edui-okbutton', + label:editor.getLang("ok"), + editor:editor, + onclick:function () { + dialog.close(true); + } + }, + { + className:'edui-cancelbutton', + label:editor.getLang("cancel"), + editor:editor, + onclick:function () { + dialog.close(false); + } + } + ] + } : {})); + + editor.ui._dialogs[cmd + "Dialog"] = dialog; + } + + var ui = new editorui.Button({ + className:'edui-for-' + cmd, + title:title, + onclick:function () { + if (dialog) { + switch (cmd) { + case "wordimage": + var images = editor.execCommand("wordimage"); + if (images && images.length) { + dialog.render(); + dialog.open(); + } + break; + case "scrawl": + if (editor.queryCommandState("scrawl") != -1) { + dialog.render(); + dialog.open(); + } + + break; + default: + dialog.render(); + dialog.open(); + } + } + }, + theme:editor.options.theme, + disabled:(cmd == 'scrawl' && editor.queryCommandState("scrawl") == -1) || ( cmd == 'charts' ) + }); + editorui.buttons[cmd] = ui; + editor.addListener('selectionchange', function () { + //只存在于右键菜单而无工具栏按钮的ui不需要检测状态 + var unNeedCheckState = {'edittable':1}; + if (cmd in unNeedCheckState)return; + + var state = editor.queryCommandState(cmd); + if (ui.getDom()) { + ui.setDisabled(state == -1); + ui.setChecked(state); + } + + }); + + return ui; + }; + })(ci.toLowerCase()) + } + })(p, dialogBtns[p]); + } + + editorui.snapscreen = function (editor, iframeUrl, title) { + title = editor.options.labelMap['snapscreen'] || editor.getLang("labelMap.snapscreen") || ''; + var ui = new editorui.Button({ + className:'edui-for-snapscreen', + title:title, + onclick:function () { + editor.execCommand("snapscreen"); + }, + theme:editor.options.theme + + }); + editorui.buttons['snapscreen'] = ui; + iframeUrl = iframeUrl || (editor.options.iframeUrlMap || {})["snapscreen"] || iframeUrlMap["snapscreen"]; + if (iframeUrl) { + var dialog = new editorui.Dialog({ + iframeUrl:editor.ui.mapUrl(iframeUrl), + editor:editor, + className:'edui-for-snapscreen', + title:title, + buttons:[ + { + className:'edui-okbutton', + label:editor.getLang("ok"), + editor:editor, + onclick:function () { + dialog.close(true); + } + }, + { + className:'edui-cancelbutton', + label:editor.getLang("cancel"), + editor:editor, + onclick:function () { + dialog.close(false); + } + } + ] + + }); + dialog.render(); + editor.ui._dialogs["snapscreenDialog"] = dialog; + } + editor.addListener('selectionchange', function () { + ui.setDisabled(editor.queryCommandState('snapscreen') == -1); + }); + return ui; + }; + + editorui.insertcode = function (editor, list, title) { + list = editor.options['insertcode'] || []; + title = editor.options.labelMap['insertcode'] || editor.getLang("labelMap.insertcode") || ''; + // if (!list.length) return; + var items = []; + utils.each(list,function(key,val){ + items.push({ + label:key, + value:val, + theme:editor.options.theme, + renderLabelHtml:function () { + return '
' + (this.label || '') + '
'; + } + }); + }); + + var ui = new editorui.Combox({ + editor:editor, + items:items, + onselect:function (t, index) { + editor.execCommand('insertcode', this.items[index].value); + }, + onbuttonclick:function () { + this.showPopup(); + }, + title:title, + initValue:title, + className:'edui-for-insertcode', + indexByValue:function (value) { + if (value) { + for (var i = 0, ci; ci = this.items[i]; i++) { + if (ci.value.indexOf(value) != -1) + return i; + } + } + + return -1; + } + }); + editorui.buttons['insertcode'] = ui; + editor.addListener('selectionchange', function (type, causeByUi, uiReady) { + if (!uiReady) { + var state = editor.queryCommandState('insertcode'); + if (state == -1) { + ui.setDisabled(true); + } else { + ui.setDisabled(false); + var value = editor.queryCommandValue('insertcode'); + if(!value){ + ui.setValue(title); + return; + } + //trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号 + value && (value = value.replace(/['"]/g, '').split(',')[0]); + ui.setValue(value); + + } + } + + }); + return ui; + }; + editorui.fontfamily = function (editor, list, title) { + + list = editor.options['fontfamily'] || []; + title = editor.options.labelMap['fontfamily'] || editor.getLang("labelMap.fontfamily") || ''; + if (!list.length) return; + for (var i = 0, ci, items = []; ci = list[i]; i++) { + var langLabel = editor.getLang('fontfamily')[ci.name] || ""; + (function (key, val) { + items.push({ + label:key, + value:val, + theme:editor.options.theme, + renderLabelHtml:function () { + return '
' + (this.label || '') + '
'; + } + }); + })(ci.label || langLabel, ci.val) + } + var ui = new editorui.Combox({ + editor:editor, + items:items, + onselect:function (t, index) { + editor.execCommand('FontFamily', this.items[index].value); + }, + onbuttonclick:function () { + this.showPopup(); + }, + title:title, + initValue:title, + className:'edui-for-fontfamily', + indexByValue:function (value) { + if (value) { + for (var i = 0, ci; ci = this.items[i]; i++) { + if (ci.value.indexOf(value) != -1) + return i; + } + } + + return -1; + } + }); + editorui.buttons['fontfamily'] = ui; + editor.addListener('selectionchange', function (type, causeByUi, uiReady) { + if (!uiReady) { + var state = editor.queryCommandState('FontFamily'); + if (state == -1) { + ui.setDisabled(true); + } else { + ui.setDisabled(false); + var value = editor.queryCommandValue('FontFamily'); + //trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号 + value && (value = value.replace(/['"]/g, '').split(',')[0]); + ui.setValue(value); + + } + } + + }); + return ui; + }; + + editorui.fontsize = function (editor, list, title) { + title = editor.options.labelMap['fontsize'] || editor.getLang("labelMap.fontsize") || ''; + list = list || editor.options['fontsize'] || []; + if (!list.length) return; + var items = []; + for (var i = 0; i < list.length; i++) { + var size = list[i] + 'px'; + items.push({ + label:size, + value:size, + theme:editor.options.theme, + renderLabelHtml:function () { + return '
' + (this.label || '') + '
'; + } + }); + } + var ui = new editorui.Combox({ + editor:editor, + items:items, + title:title, + initValue:title, + onselect:function (t, index) { + editor.execCommand('FontSize', this.items[index].value); + }, + onbuttonclick:function () { + this.showPopup(); + }, + className:'edui-for-fontsize' + }); + editorui.buttons['fontsize'] = ui; + editor.addListener('selectionchange', function (type, causeByUi, uiReady) { + if (!uiReady) { + var state = editor.queryCommandState('FontSize'); + if (state == -1) { + ui.setDisabled(true); + } else { + ui.setDisabled(false); + ui.setValue(editor.queryCommandValue('FontSize')); + } + } + + }); + return ui; + }; + + editorui.paragraph = function (editor, list, title) { + title = editor.options.labelMap['paragraph'] || editor.getLang("labelMap.paragraph") || ''; + list = editor.options['paragraph'] || []; + if (utils.isEmptyObject(list)) return; + var items = []; + for (var i in list) { + items.push({ + value:i, + label:list[i] || editor.getLang("paragraph")[i], + theme:editor.options.theme, + renderLabelHtml:function () { + return '
' + (this.label || '') + '
'; + } + }) + } + var ui = new editorui.Combox({ + editor:editor, + items:items, + title:title, + initValue:title, + className:'edui-for-paragraph', + onselect:function (t, index) { + editor.execCommand('Paragraph', this.items[index].value); + }, + onbuttonclick:function () { + this.showPopup(); + } + }); + editorui.buttons['paragraph'] = ui; + editor.addListener('selectionchange', function (type, causeByUi, uiReady) { + if (!uiReady) { + var state = editor.queryCommandState('Paragraph'); + if (state == -1) { + ui.setDisabled(true); + } else { + ui.setDisabled(false); + var value = editor.queryCommandValue('Paragraph'); + var index = ui.indexByValue(value); + if (index != -1) { + ui.setValue(value); + } else { + ui.setValue(ui.initValue); + } + } + } + + }); + return ui; + }; + + + //自定义标题 + editorui.customstyle = function (editor) { + var list = editor.options['customstyle'] || [], + title = editor.options.labelMap['customstyle'] || editor.getLang("labelMap.customstyle") || ''; + if (!list.length)return; + var langCs = editor.getLang('customstyle'); + for (var i = 0, items = [], t; t = list[i++];) { + (function (t) { + var ck = {}; + ck.label = t.label ? t.label : langCs[t.name]; + ck.style = t.style; + ck.className = t.className; + ck.tag = t.tag; + items.push({ + label:ck.label, + value:ck, + theme:editor.options.theme, + renderLabelHtml:function () { + return '
' + '<' + ck.tag + ' ' + (ck.className ? ' class="' + ck.className + '"' : "") + + (ck.style ? ' style="' + ck.style + '"' : "") + '>' + ck.label + "<\/" + ck.tag + ">" + + '
'; + } + }); + })(t); + } + + var ui = new editorui.Combox({ + editor:editor, + items:items, + title:title, + initValue:title, + className:'edui-for-customstyle', + onselect:function (t, index) { + editor.execCommand('customstyle', this.items[index].value); + }, + onbuttonclick:function () { + this.showPopup(); + }, + indexByValue:function (value) { + for (var i = 0, ti; ti = this.items[i++];) { + if (ti.label == value) { + return i - 1 + } + } + return -1; + } + }); + editorui.buttons['customstyle'] = ui; + editor.addListener('selectionchange', function (type, causeByUi, uiReady) { + if (!uiReady) { + var state = editor.queryCommandState('customstyle'); + if (state == -1) { + ui.setDisabled(true); + } else { + ui.setDisabled(false); + var value = editor.queryCommandValue('customstyle'); + var index = ui.indexByValue(value); + if (index != -1) { + ui.setValue(value); + } else { + ui.setValue(ui.initValue); + } + } + } + + }); + return ui; + }; + editorui.inserttable = function (editor, iframeUrl, title) { + title = editor.options.labelMap['inserttable'] || editor.getLang("labelMap.inserttable") || ''; + var ui = new editorui.TableButton({ + editor:editor, + title:title, + className:'edui-for-inserttable', + onpicktable:function (t, numCols, numRows) { + editor.execCommand('InsertTable', {numRows:numRows, numCols:numCols, border:1}); + }, + onbuttonclick:function () { + this.showPopup(); + } + }); + editorui.buttons['inserttable'] = ui; + editor.addListener('selectionchange', function () { + ui.setDisabled(editor.queryCommandState('inserttable') == -1); + }); + return ui; + }; + + editorui.lineheight = function (editor) { + var val = editor.options.lineheight || []; + if (!val.length)return; + for (var i = 0, ci, items = []; ci = val[i++];) { + items.push({ + //todo:写死了 + label:ci, + value:ci, + theme:editor.options.theme, + onclick:function () { + editor.execCommand("lineheight", this.value); + } + }) + } + var ui = new editorui.MenuButton({ + editor:editor, + className:'edui-for-lineheight', + title:editor.options.labelMap['lineheight'] || editor.getLang("labelMap.lineheight") || '', + items:items, + onbuttonclick:function () { + var value = editor.queryCommandValue('LineHeight') || this.value; + editor.execCommand("LineHeight", value); + } + }); + editorui.buttons['lineheight'] = ui; + editor.addListener('selectionchange', function () { + var state = editor.queryCommandState('LineHeight'); + if (state == -1) { + ui.setDisabled(true); + } else { + ui.setDisabled(false); + var value = editor.queryCommandValue('LineHeight'); + value && ui.setValue((value + '').replace(/cm/, '')); + ui.setChecked(state) + } + }); + return ui; + }; + + var rowspacings = ['top', 'bottom']; + for (var r = 0, ri; ri = rowspacings[r++];) { + (function (cmd) { + editorui['rowspacing' + cmd] = function (editor) { + var val = editor.options['rowspacing' + cmd] || []; + if (!val.length) return null; + for (var i = 0, ci, items = []; ci = val[i++];) { + items.push({ + label:ci, + value:ci, + theme:editor.options.theme, + onclick:function () { + editor.execCommand("rowspacing", this.value, cmd); + } + }) + } + var ui = new editorui.MenuButton({ + editor:editor, + className:'edui-for-rowspacing' + cmd, + title:editor.options.labelMap['rowspacing' + cmd] || editor.getLang("labelMap.rowspacing" + cmd) || '', + items:items, + onbuttonclick:function () { + var value = editor.queryCommandValue('rowspacing', cmd) || this.value; + editor.execCommand("rowspacing", value, cmd); + } + }); + editorui.buttons[cmd] = ui; + editor.addListener('selectionchange', function () { + var state = editor.queryCommandState('rowspacing', cmd); + if (state == -1) { + ui.setDisabled(true); + } else { + ui.setDisabled(false); + var value = editor.queryCommandValue('rowspacing', cmd); + value && ui.setValue((value + '').replace(/%/, '')); + ui.setChecked(state) + } + }); + return ui; + } + })(ri) + } + //有序,无序列表 + var lists = ['insertorderedlist', 'insertunorderedlist']; + for (var l = 0, cl; cl = lists[l++];) { + (function (cmd) { + editorui[cmd] = function (editor) { + var vals = editor.options[cmd], + _onMenuClick = function () { + editor.execCommand(cmd, this.value); + }, items = []; + for (var i in vals) { + items.push({ + label:vals[i] || editor.getLang()[cmd][i] || "", + value:i, + theme:editor.options.theme, + onclick:_onMenuClick + }) + } + var ui = new editorui.MenuButton({ + editor:editor, + className:'edui-for-' + cmd, + title:editor.getLang("labelMap." + cmd) || '', + 'items':items, + onbuttonclick:function () { + var value = editor.queryCommandValue(cmd) || this.value; + editor.execCommand(cmd, value); + } + }); + editorui.buttons[cmd] = ui; + editor.addListener('selectionchange', function () { + var state = editor.queryCommandState(cmd); + if (state == -1) { + ui.setDisabled(true); + } else { + ui.setDisabled(false); + var value = editor.queryCommandValue(cmd); + ui.setValue(value); + ui.setChecked(state) + } + }); + return ui; + }; + })(cl) + } + + editorui.fullscreen = function (editor, title) { + title = editor.options.labelMap['fullscreen'] || editor.getLang("labelMap.fullscreen") || ''; + var ui = new editorui.Button({ + className:'edui-for-fullscreen', + title:title, + theme:editor.options.theme, + onclick:function () { + if (editor.ui) { + editor.ui.setFullScreen(!editor.ui.isFullScreen()); + } + this.setChecked(editor.ui.isFullScreen()); + } + }); + editorui.buttons['fullscreen'] = ui; + editor.addListener('selectionchange', function () { + var state = editor.queryCommandState('fullscreen'); + ui.setDisabled(state == -1); + ui.setChecked(editor.ui.isFullScreen()); + }); + return ui; + }; + + // 表情 + editorui["emotion"] = function (editor, iframeUrl) { + var cmd = "emotion"; + var ui = new editorui.MultiMenuPop({ + title:editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd + "") || '', + editor:editor, + className:'edui-for-' + cmd, + iframeUrl:editor.ui.mapUrl(iframeUrl || (editor.options.iframeUrlMap || {})[cmd] || iframeUrlMap[cmd]) + }); + editorui.buttons[cmd] = ui; + + editor.addListener('selectionchange', function () { + ui.setDisabled(editor.queryCommandState(cmd) == -1) + }); + return ui; + }; + + editorui.autotypeset = function (editor) { + var ui = new editorui.AutoTypeSetButton({ + editor:editor, + title:editor.options.labelMap['autotypeset'] || editor.getLang("labelMap.autotypeset") || '', + className:'edui-for-autotypeset', + onbuttonclick:function () { + editor.execCommand('autotypeset') + } + }); + editorui.buttons['autotypeset'] = ui; + editor.addListener('selectionchange', function () { + ui.setDisabled(editor.queryCommandState('autotypeset') == -1); + }); + return ui; + }; + + /* 简单上传插件 */ + editorui["simpleupload"] = function (editor) { + var name = 'simpleupload', + ui = new editorui.Button({ + className:'edui-for-' + name, + title:editor.options.labelMap[name] || editor.getLang("labelMap." + name) || '', + onclick:function () {}, + theme:editor.options.theme, + showText:false + }); + editorui.buttons[name] = ui; + editor.addListener('ready', function() { + var b = ui.getDom('body'), + iconSpan = b.children[0]; + editor.fireEvent('simpleuploadbtnready', iconSpan); + }); + editor.addListener('selectionchange', function (type, causeByUi, uiReady) { + var state = editor.queryCommandState(name); + if (state == -1) { + ui.setDisabled(true); + ui.setChecked(false); + } else { + if (!uiReady) { + ui.setDisabled(false); + ui.setChecked(state); + } + } + }); + return ui; + }; + +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/adapter/message.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/adapter/message.js new file mode 100644 index 000000000..37c9193a3 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/adapter/message.js @@ -0,0 +1,58 @@ +UE.registerUI('message', function(editor) { + + var editorui = baidu.editor.ui; + var Message = editorui.Message; + var holder; + var _messageItems = []; + var me = editor; + + me.addListener('ready', function(){ + holder = document.getElementById(me.ui.id + '_message_holder'); + updateHolderPos(); + setTimeout(function(){ + updateHolderPos(); + }, 500); + }); + + me.addListener('showmessage', function(type, opt){ + opt = utils.isString(opt) ? { + 'content': opt + } : opt; + var message = new Message({ + 'timeout': opt.timeout, + 'type': opt.type, + 'content': opt.content, + 'keepshow': opt.keepshow, + 'editor': me + }), + mid = opt.id || ('msg_' + (+new Date()).toString(36)); + message.render(holder); + _messageItems[mid] = message; + message.reset(opt); + updateHolderPos(); + return mid; + }); + + me.addListener('updatemessage',function(type, id, opt){ + opt = utils.isString(opt) ? { + 'content': opt + } : opt; + var message = _messageItems[id]; + message.render(holder); + message && message.reset(opt); + }); + + me.addListener('hidemessage',function(type, id){ + var message = _messageItems[id]; + message && message.hide(); + }); + + function updateHolderPos(){ + var toolbarbox = me.ui.getDom('toolbarbox'); + if (toolbarbox) { + holder.style.top = toolbarbox.offsetHeight + 3 + 'px'; + } + holder.style.zIndex = Math.max(me.options.zIndex, me.iframe.style.zIndex) + 1; + } + +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/api.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/api.js new file mode 100644 index 000000000..bb206ca62 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/api.js @@ -0,0 +1,62 @@ +/** + * 该文件定义了API文档所使用到的本地函数的说明 + * @file + * @module Native + */ + +/** + * 辅助接口说明 + * @module Native + * @unfile + */ + +/** + * 原生String对象, 字符串 + * @class String + */ + +/** + * 原生Function对象, 函数 + * @class Function + */ + +/** + * 原生Object对象, 普通对象 + * @remind 如果某一方法的参数类型为Object时, 表示该参数应该接受一个key-value集合 + * @class Object + */ + +/** + * 原生Boolean对象, 布尔值 + * @class Boolean + */ + +/** + * 原生Number对象, 数值 + * @class Number + */ + +/** + * 原生NULL对象, 空 + * @class NULL + */ + +/** + * 原生Array对象, 数组 + * @class Array + */ + +/** + * 浏览器Node, dom节点 + * @class Node + */ + +/** + * 浏览器Element, dom元素 + * @class Element + */ + +/** + * UEditor模拟dom节点对象 + * @class uNode + */ \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/Editor.defaultoptions.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/Editor.defaultoptions.js new file mode 100644 index 000000000..18a7132aa --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/Editor.defaultoptions.js @@ -0,0 +1,31 @@ +//维护编辑器一下默认的不在插件中的配置项 +UE.Editor.defaultOptions = function(editor){ + + var _url = editor.options.UEDITOR_HOME_URL; + return { + isShow: true, + initialContent: '', + initialStyle:'', + autoClearinitialContent: false, + iframeCssUrl: _url + 'themes/iframe.css', + textarea: 'editorValue', + focus: false, + focusInEnd: true, + autoClearEmptyNode: true, + fullscreen: false, + readonly: false, + zIndex: 999, + imagePopup: true, + enterTag: 'p', + customDomain: false, + lang: 'zh-cn', + langPath: _url + 'lang/', + theme: 'default', + themePath: _url + 'themes/', + allHtmlEnabled: false, + scaleEnabled: false, + tableNativeEditInFF: false, + autoSyncData : true, + fileNameFormat: '{time}{rand:6}' + } +}; \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/Editor.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/Editor.js new file mode 100644 index 000000000..cb5c629ff --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/Editor.js @@ -0,0 +1,1527 @@ +/** + * 编辑器主类,包含编辑器提供的大部分公用接口 + * @file + * @module UE + * @class Editor + * @since 1.2.6.1 + */ + +/** + * UEditor公用空间,UEditor所有的功能都挂载在该空间下 + * @unfile + * @module UE + */ + +/** + * UEditor的核心类,为用户提供与编辑器交互的接口。 + * @unfile + * @module UE + * @class Editor + */ + +(function () { + var uid = 0, _selectionChangeTimer; + + /** + * 获取编辑器的html内容,赋值到编辑器所在表单的textarea文本域里面 + * @private + * @method setValue + * @param { UE.Editor } editor 编辑器事例 + */ + function setValue(form, editor) { + var textarea; + if (editor.textarea) { + if (utils.isString(editor.textarea)) { + for (var i = 0, ti, tis = domUtils.getElementsByTagName(form, 'textarea'); ti = tis[i++];) { + if (ti.id == 'ueditor_textarea_' + editor.options.textarea) { + textarea = ti; + break; + } + } + } else { + textarea = editor.textarea; + } + } + if (!textarea) { + form.appendChild(textarea = domUtils.createElement(document, 'textarea', { + 'name': editor.options.textarea, + 'id': 'ueditor_textarea_' + editor.options.textarea, + 'style': "display:none" + })); + //不要产生多个textarea + editor.textarea = textarea; + } + !textarea.getAttribute('name') && textarea.setAttribute('name', editor.options.textarea ); + textarea.value = editor.hasContents() ? + (editor.options.allHtmlEnabled ? editor.getAllHtml() : editor.getContent(null, null, true)) : + '' + } + function loadPlugins(me){ + //初始化插件 + for (var pi in UE.plugins) { + UE.plugins[pi].call(me); + } + + } + function checkCurLang(I18N){ + for(var lang in I18N){ + return lang + } + } + + function langReadied(me){ + me.langIsReady = true; + + me.fireEvent("langReady"); + } + + /** + * 编辑器准备就绪后会触发该事件 + * @module UE + * @class Editor + * @event ready + * @remind render方法执行完成之后,会触发该事件 + * @remind + * @example + * ```javascript + * editor.addListener( 'ready', function( editor ) { + * editor.execCommand( 'focus' ); //编辑器家在完成后,让编辑器拿到焦点 + * } ); + * ``` + */ + /** + * 执行destroy方法,会触发该事件 + * @module UE + * @class Editor + * @event destroy + * @see UE.Editor:destroy() + */ + /** + * 执行reset方法,会触发该事件 + * @module UE + * @class Editor + * @event reset + * @see UE.Editor:reset() + */ + /** + * 执行focus方法,会触发该事件 + * @module UE + * @class Editor + * @event focus + * @see UE.Editor:focus(Boolean) + */ + /** + * 语言加载完成会触发该事件 + * @module UE + * @class Editor + * @event langReady + */ + /** + * 运行命令之后会触发该命令 + * @module UE + * @class Editor + * @event beforeExecCommand + */ + /** + * 运行命令之后会触发该命令 + * @module UE + * @class Editor + * @event afterExecCommand + */ + /** + * 运行命令之前会触发该命令 + * @module UE + * @class Editor + * @event firstBeforeExecCommand + */ + /** + * 在getContent方法执行之前会触发该事件 + * @module UE + * @class Editor + * @event beforeGetContent + * @see UE.Editor:getContent() + */ + /** + * 在getContent方法执行之后会触发该事件 + * @module UE + * @class Editor + * @event afterGetContent + * @see UE.Editor:getContent() + */ + /** + * 在getAllHtml方法执行时会触发该事件 + * @module UE + * @class Editor + * @event getAllHtml + * @see UE.Editor:getAllHtml() + */ + /** + * 在setContent方法执行之前会触发该事件 + * @module UE + * @class Editor + * @event beforeSetContent + * @see UE.Editor:setContent(String) + */ + /** + * 在setContent方法执行之后会触发该事件 + * @module UE + * @class Editor + * @event afterSetContent + * @see UE.Editor:setContent(String) + */ + /** + * 每当编辑器内部选区发生改变时,将触发该事件 + * @event selectionchange + * @warning 该事件的触发非常频繁,不建议在该事件的处理过程中做重量级的处理 + * @example + * ```javascript + * editor.addListener( 'selectionchange', function( editor ) { + * console.log('选区发生改变'); + * } + */ + /** + * 在所有selectionchange的监听函数执行之前,会触发该事件 + * @module UE + * @class Editor + * @event beforeSelectionChange + * @see UE.Editor:selectionchange + */ + /** + * 在所有selectionchange的监听函数执行完之后,会触发该事件 + * @module UE + * @class Editor + * @event afterSelectionChange + * @see UE.Editor:selectionchange + */ + /** + * 编辑器内容发生改变时会触发该事件 + * @module UE + * @class Editor + * @event contentChange + */ + + + /** + * 以默认参数构建一个编辑器实例 + * @constructor + * @remind 通过 改构造方法实例化的编辑器,不带ui层.需要render到一个容器,编辑器实例才能正常渲染到页面 + * @example + * ```javascript + * var editor = new UE.Editor(); + * editor.execCommand('blod'); + * ``` + * @see UE.Config + */ + + /** + * 以给定的参数集合创建一个编辑器实例,对于未指定的参数,将应用默认参数。 + * @constructor + * @remind 通过 改构造方法实例化的编辑器,不带ui层.需要render到一个容器,编辑器实例才能正常渲染到页面 + * @param { Object } setting 创建编辑器的参数 + * @example + * ```javascript + * var editor = new UE.Editor(); + * editor.execCommand('blod'); + * ``` + * @see UE.Config + */ + var Editor = UE.Editor = function (options) { + var me = this; + me.uid = uid++; + EventBase.call(me); + me.commands = {}; + me.options = utils.extend(utils.clone(options || {}), UEDITOR_CONFIG, true); + me.shortcutkeys = {}; + me.inputRules = []; + me.outputRules = []; + //设置默认的常用属性 + me.setOpt(Editor.defaultOptions(me)); + + /* 尝试异步加载后台配置 */ + me.loadServerConfig(); + + if(!utils.isEmptyObject(UE.I18N)){ + //修改默认的语言类型 + me.options.lang = checkCurLang(UE.I18N); + UE.plugin.load(me); + langReadied(me); + + }else{ + utils.loadFile(document, { + src: me.options.langPath + me.options.lang + "/" + me.options.lang + ".js", + tag: "script", + type: "text/javascript", + defer: "defer" + }, function () { + UE.plugin.load(me); + langReadied(me); + }); + } + + UE.instants['ueditorInstant' + me.uid] = me; + }; + Editor.prototype = { + registerCommand : function(name,obj){ + this.commands[name] = obj; + }, + /** + * 编辑器对外提供的监听ready事件的接口, 通过调用该方法,达到的效果与监听ready事件是一致的 + * @method ready + * @param { Function } fn 编辑器ready之后所执行的回调, 如果在注册事件之前编辑器已经ready,将会 + * 立即触发该回调。 + * @remind 需要等待编辑器加载完成后才能执行的代码,可以使用该方法传入 + * @example + * ```javascript + * editor.ready( function( editor ) { + * editor.setContent('初始化完毕'); + * } ); + * ``` + * @see UE.Editor.event:ready + */ + ready: function (fn) { + var me = this; + if (fn) { + me.isReady ? fn.apply(me) : me.addListener('ready', fn); + } + }, + + /** + * 该方法是提供给插件里面使用,设置配置项默认值 + * @method setOpt + * @warning 三处设置配置项的优先级: 实例化时传入参数 > setOpt()设置 > config文件里设置 + * @warning 该方法仅供编辑器插件内部和编辑器初始化时调用,其他地方不能调用。 + * @param { String } key 编辑器的可接受的选项名称 + * @param { * } val 该选项可接受的值 + * @example + * ```javascript + * editor.setOpt( 'initContent', '欢迎使用编辑器' ); + * ``` + */ + + /** + * 该方法是提供给插件里面使用,以{key:value}集合的方式设置插件内用到的配置项默认值 + * @method setOpt + * @warning 三处设置配置项的优先级: 实例化时传入参数 > setOpt()设置 > config文件里设置 + * @warning 该方法仅供编辑器插件内部和编辑器初始化时调用,其他地方不能调用。 + * @param { Object } options 将要设置的选项的键值对对象 + * @example + * ```javascript + * editor.setOpt( { + * 'initContent': '欢迎使用编辑器' + * } ); + * ``` + */ + setOpt: function (key, val) { + var obj = {}; + if (utils.isString(key)) { + obj[key] = val + } else { + obj = key; + } + utils.extend(this.options, obj, true); + }, + getOpt:function(key){ + return this.options[key] + }, + /** + * 销毁编辑器实例,使用textarea代替 + * @method destroy + * @example + * ```javascript + * editor.destroy(); + * ``` + */ + destroy: function () { + + var me = this; + me.fireEvent('destroy'); + var container = me.container.parentNode; + var textarea = me.textarea; + if (!textarea) { + textarea = document.createElement('textarea'); + container.parentNode.insertBefore(textarea, container); + } else { + textarea.style.display = '' + } + + textarea.style.width = me.iframe.offsetWidth + 'px'; + textarea.style.height = me.iframe.offsetHeight + 'px'; + textarea.value = me.getContent(); + textarea.id = me.key; + container.innerHTML = ''; + domUtils.remove(container); + var key = me.key; + //trace:2004 + for (var p in me) { + if (me.hasOwnProperty(p)) { + delete this[p]; + } + } + UE.delEditor(key); + }, + + /** + * 渲染编辑器的DOM到指定容器 + * @method render + * @param { String } containerId 指定一个容器ID + * @remind 执行该方法,会触发ready事件 + * @warning 必须且只能调用一次 + */ + + /** + * 渲染编辑器的DOM到指定容器 + * @method render + * @param { Element } containerDom 直接指定容器对象 + * @remind 执行该方法,会触发ready事件 + * @warning 必须且只能调用一次 + */ + render: function (container) { + var me = this, + options = me.options, + getStyleValue=function(attr){ + return parseInt(domUtils.getComputedStyle(container,attr)); + }; + if (utils.isString(container)) { + container = document.getElementById(container); + } + if (container) { + if(options.initialFrameWidth){ + options.minFrameWidth = options.initialFrameWidth + }else{ + options.minFrameWidth = options.initialFrameWidth = container.offsetWidth; + } + if(options.initialFrameHeight){ + options.minFrameHeight = options.initialFrameHeight + }else{ + options.initialFrameHeight = options.minFrameHeight = container.offsetHeight; + } + + container.style.width = /%$/.test(options.initialFrameWidth) ? '100%' : options.initialFrameWidth- + getStyleValue("padding-left")- getStyleValue("padding-right") +'px'; + container.style.height = /%$/.test(options.initialFrameHeight) ? '100%' : options.initialFrameHeight - + getStyleValue("padding-top")- getStyleValue("padding-bottom") +'px'; + + container.style.zIndex = options.zIndex; + + var html = ( ie && browser.version < 9 ? '' : '') + + '' + + '' + + ( options.iframeCssUrl ? '' : '' ) + + (options.initialStyle ? '' : '') + + '' + + ''; + container.appendChild(domUtils.createElement(document, 'iframe', { + id: 'ueditor_' + me.uid, + width: "100%", + height: "100%", + frameborder: "0", + //先注释掉了,加的原因忘记了,但开启会直接导致全屏模式下内容多时不会出现滚动条 +// scrolling :'no', + src: 'javascript:void(function(){document.open();' + (options.customDomain && document.domain != location.hostname ? 'document.domain="' + document.domain + '";' : '') + + 'document.write("' + html + '");document.close();}())' + })); + container.style.overflow = 'hidden'; + //解决如果是给定的百分比,会导致高度算不对的问题 + setTimeout(function(){ + if( /%$/.test(options.initialFrameWidth)){ + options.minFrameWidth = options.initialFrameWidth = container.offsetWidth; + //如果这里给定宽度,会导致ie在拖动窗口大小时,编辑区域不随着变化 +// container.style.width = options.initialFrameWidth + 'px'; + } + if(/%$/.test(options.initialFrameHeight)){ + options.minFrameHeight = options.initialFrameHeight = container.offsetHeight; + container.style.height = options.initialFrameHeight + 'px'; + } + }) + } + }, + + /** + * 编辑器初始化 + * @method _setup + * @private + * @param { Element } doc 编辑器Iframe中的文档对象 + */ + _setup: function (doc) { + + var me = this, + options = me.options; + if (ie) { + doc.body.disabled = true; + doc.body.contentEditable = true; + doc.body.disabled = false; + } else { + doc.body.contentEditable = true; + } + doc.body.spellcheck = false; + me.document = doc; + me.window = doc.defaultView || doc.parentWindow; + me.iframe = me.window.frameElement; + me.body = doc.body; + me.selection = new dom.Selection(doc); + //gecko初始化就能得到range,无法判断isFocus了 + var geckoSel; + if (browser.gecko && (geckoSel = this.selection.getNative())) { + geckoSel.removeAllRanges(); + } + this._initEvents(); + //为form提交提供一个隐藏的textarea + for (var form = this.iframe.parentNode; !domUtils.isBody(form); form = form.parentNode) { + if (form.tagName == 'FORM') { + me.form = form; + if(me.options.autoSyncData){ + domUtils.on(me.window,'blur',function(){ + setValue(form,me); + }); + }else{ + domUtils.on(form, 'submit', function () { + setValue(this, me); + }); + } + break; + } + } + if (options.initialContent) { + if (options.autoClearinitialContent) { + var oldExecCommand = me.execCommand; + me.execCommand = function () { + me.fireEvent('firstBeforeExecCommand'); + return oldExecCommand.apply(me, arguments); + }; + this._setDefaultContent(options.initialContent); + } else + this.setContent(options.initialContent, false, true); + } + + //编辑器不能为空内容 + + if (domUtils.isEmptyNode(me.body)) { + me.body.innerHTML = '

' + (browser.ie ? '' : '
') + '

'; + } + //如果要求focus, 就把光标定位到内容开始 + if (options.focus) { + setTimeout(function () { + me.focus(me.options.focusInEnd); + //如果自动清除开着,就不需要做selectionchange; + !me.options.autoClearinitialContent && me._selectionChange(); + }, 0); + } + if (!me.container) { + me.container = this.iframe.parentNode; + } + if (options.fullscreen && me.ui) { + me.ui.setFullScreen(true); + } + + try { + me.document.execCommand('2D-position', false, false); + } catch (e) { + } + try { + me.document.execCommand('enableInlineTableEditing', false, false); + } catch (e) { + } + try { + me.document.execCommand('enableObjectResizing', false, false); + } catch (e) { + } + + //挂接快捷键 + me._bindshortcutKeys(); + me.isReady = 1; + me.fireEvent('ready'); + options.onready && options.onready.call(me); + if (!browser.ie9below) { + domUtils.on(me.window, ['blur', 'focus'], function (e) { + //chrome下会出现alt+tab切换时,导致选区位置不对 + if (e.type == 'blur') { + me._bakRange = me.selection.getRange(); + try { + me._bakNativeRange = me.selection.getNative().getRangeAt(0); + me.selection.getNative().removeAllRanges(); + } catch (e) { + me._bakNativeRange = null; + } + + } else { + try { + me._bakRange && me._bakRange.select(); + } catch (e) { + } + } + }); + } + //trace:1518 ff3.6body不够寛,会导致点击空白处无法获得焦点 + if (browser.gecko && browser.version <= 10902) { + //修复ff3.6初始化进来,不能点击获得焦点 + me.body.contentEditable = false; + setTimeout(function () { + me.body.contentEditable = true; + }, 100); + setInterval(function () { + me.body.style.height = me.iframe.offsetHeight - 20 + 'px' + }, 100) + } + + !options.isShow && me.setHide(); + options.readonly && me.setDisabled(); + }, + + /** + * 同步数据到编辑器所在的form + * 从编辑器的容器节点向上查找form元素,若找到,就同步编辑内容到找到的form里,为提交数据做准备,主要用于是手动提交的情况 + * 后台取得数据的键值,使用你容器上的name属性,如果没有就使用参数里的textarea项 + * @method sync + * @example + * ```javascript + * editor.sync(); + * form.sumbit(); //form变量已经指向了form元素 + * ``` + */ + + /** + * 根据传入的formId,在页面上查找要同步数据的表单,若找到,就同步编辑内容到找到的form里,为提交数据做准备 + * 后台取得数据的键值,该键值默认使用给定的编辑器容器的name属性,如果没有name属性则使用参数项里给定的“textarea”项 + * @method sync + * @param { String } formID 指定一个要同步数据的form的id,编辑器的数据会同步到你指定form下 + */ + sync: function (formId) { + var me = this, + form = formId ? document.getElementById(formId) : + domUtils.findParent(me.iframe.parentNode, function (node) { + return node.tagName == 'FORM' + }, true); + form && setValue(form, me); + }, + + /** + * 设置编辑器高度 + * @method setHeight + * @remind 当配置项autoHeightEnabled为真时,该方法无效 + * @param { Number } number 设置的高度值,纯数值,不带单位 + * @example + * ```javascript + * editor.setHeight(number); + * ``` + */ + setHeight: function (height,notSetHeight) { + if (height !== parseInt(this.iframe.parentNode.style.height)) { + this.iframe.parentNode.style.height = height + 'px'; + } + !notSetHeight && (this.options.minFrameHeight = this.options.initialFrameHeight = height); + this.body.style.height = height + 'px'; + !notSetHeight && this.trigger('setHeight') + }, + + /** + * 为编辑器的编辑命令提供快捷键 + * 这个接口是为插件扩展提供的接口,主要是为新添加的插件,如果需要添加快捷键,所提供的接口 + * @method addshortcutkey + * @param { Object } keyset 命令名和快捷键键值对对象,多个按钮的快捷键用“+”分隔 + * @example + * ```javascript + * editor.addshortcutkey({ + * "Bold" : "ctrl+66",//^B + * "Italic" : "ctrl+73", //^I + * }); + * ``` + */ + /** + * 这个接口是为插件扩展提供的接口,主要是为新添加的插件,如果需要添加快捷键,所提供的接口 + * @method addshortcutkey + * @param { String } cmd 触发快捷键时,响应的命令 + * @param { String } keys 快捷键的字符串,多个按钮用“+”分隔 + * @example + * ```javascript + * editor.addshortcutkey("Underline", "ctrl+85"); //^U + * ``` + */ + addshortcutkey: function (cmd, keys) { + var obj = {}; + if (keys) { + obj[cmd] = keys + } else { + obj = cmd; + } + utils.extend(this.shortcutkeys, obj) + }, + + /** + * 对编辑器设置keydown事件监听,绑定快捷键和命令,当快捷键组合触发成功,会响应对应的命令 + * @method _bindshortcutKeys + * @private + */ + _bindshortcutKeys: function () { + var me = this, shortcutkeys = this.shortcutkeys; + me.addListener('keydown', function (type, e) { + var keyCode = e.keyCode || e.which; + for (var i in shortcutkeys) { + var tmp = shortcutkeys[i].split(','); + for (var t = 0, ti; ti = tmp[t++];) { + ti = ti.split(':'); + var key = ti[0], param = ti[1]; + if (/^(ctrl)(\+shift)?\+(\d+)$/.test(key.toLowerCase()) || /^(\d+)$/.test(key)) { + if (( (RegExp.$1 == 'ctrl' ? (e.ctrlKey || e.metaKey) : 0) + && (RegExp.$2 != "" ? e[RegExp.$2.slice(1) + "Key"] : 1) + && keyCode == RegExp.$3 + ) || + keyCode == RegExp.$1 + ) { + if (me.queryCommandState(i,param) != -1) + me.execCommand(i, param); + domUtils.preventDefault(e); + } + } + } + + } + }); + }, + + /** + * 获取编辑器的内容 + * @method getContent + * @warning 该方法获取到的是经过编辑器内置的过滤规则进行过滤后得到的内容 + * @return { String } 编辑器的内容字符串, 如果编辑器的内容为空,或者是空的标签内容(如:”<p><br/></p>“), 则返回空字符串 + * @example + * ```javascript + * //编辑器html内容:

123456

+ * var content = editor.getContent(); //返回值:

123456

+ * ``` + */ + + /** + * 获取编辑器的内容。 可以通过参数定义编辑器内置的判空规则 + * @method getContent + * @param { Function } fn 自定的判空规则, 要求该方法返回一个boolean类型的值, + * 代表当前编辑器的内容是否空, + * 如果返回true, 则该方法将直接返回空字符串;如果返回false,则编辑器将返回 + * 经过内置过滤规则处理后的内容。 + * @remind 该方法在处理包含有初始化内容的时候能起到很好的作用。 + * @warning 该方法获取到的是经过编辑器内置的过滤规则进行过滤后得到的内容 + * @return { String } 编辑器的内容字符串 + * @example + * ```javascript + * // editor 是一个编辑器的实例 + * var content = editor.getContent( function ( editor ) { + * return editor.body.innerHTML === '欢迎使用UEditor'; //返回空字符串 + * } ); + * ``` + */ + getContent: function (cmd, fn,notSetCursor,ignoreBlank,formatter) { + var me = this; + if (cmd && utils.isFunction(cmd)) { + fn = cmd; + cmd = ''; + } + if (fn ? !fn() : !this.hasContents()) { + return ''; + } + me.fireEvent('beforegetcontent'); + var root = UE.htmlparser(me.body.innerHTML,ignoreBlank); + me.filterOutputRule(root); + me.fireEvent('aftergetcontent', cmd,root); + return root.toHtml(formatter); + }, + + /** + * 取得完整的html代码,可以直接显示成完整的html文档 + * @method getAllHtml + * @return { String } 编辑器的内容html文档字符串 + * @eaxmple + * ```javascript + * editor.getAllHtml(); //返回格式大致是: ...... + * ``` + */ + getAllHtml: function () { + var me = this, + headHtml = [], + html = ''; + me.fireEvent('getAllHtml', headHtml); + if (browser.ie && browser.version > 8) { + var headHtmlForIE9 = ''; + utils.each(me.document.styleSheets, function (si) { + headHtmlForIE9 += ( si.href ? '' : ''); + }); + utils.each(me.document.getElementsByTagName('script'), function (si) { + headHtmlForIE9 += si.outerHTML; + }); + + } + return '' + (me.options.charset ? '' : '') + + (headHtmlForIE9 || me.document.getElementsByTagName('head')[0].innerHTML) + headHtml.join('\n') + '' + + '' + me.getContent(null, null, true) + ''; + }, + + /** + * 得到编辑器的纯文本内容,但会保留段落格式 + * @method getPlainTxt + * @return { String } 编辑器带段落格式的纯文本内容字符串 + * @example + * ```javascript + * //编辑器html内容:

1

2

+ * console.log(editor.getPlainTxt()); //输出:"1\n2\n + * ``` + */ + getPlainTxt: function () { + var reg = new RegExp(domUtils.fillChar, 'g'), + html = this.body.innerHTML.replace(/[\n\r]/g, '');//ie要先去了\n在处理 + html = html.replace(/<(p|div)[^>]*>(| )<\/\1>/gi, '\n') + .replace(//gi, '\n') + .replace(/<[^>/]+>/g, '') + .replace(/(\n)?<\/([^>]+)>/g, function (a, b, c) { + return dtd.$block[c] ? '\n' : b ? b : ''; + }); + //取出来的空格会有c2a0会变成乱码,处理这种情况\u00a0 + return html.replace(reg, '').replace(/\u00a0/g, ' ').replace(/ /g, ' '); + }, + + /** + * 获取编辑器中的纯文本内容,没有段落格式 + * @method getContentTxt + * @return { String } 编辑器不带段落格式的纯文本内容字符串 + * @example + * ```javascript + * //编辑器html内容:

1

2

+ * console.log(editor.getPlainTxt()); //输出:"12 + * ``` + */ + getContentTxt: function () { + var reg = new RegExp(domUtils.fillChar, 'g'); + //取出来的空格会有c2a0会变成乱码,处理这种情况\u00a0 + return this.body[browser.ie ? 'innerText' : 'textContent'].replace(reg, '').replace(/\u00a0/g, ' '); + }, + + /** + * 设置编辑器的内容,可修改编辑器当前的html内容 + * @method setContent + * @warning 通过该方法插入的内容,是经过编辑器内置的过滤规则进行过滤后得到的内容 + * @warning 该方法会触发selectionchange事件 + * @param { String } html 要插入的html内容 + * @example + * ```javascript + * editor.getContent('

test

'); + * ``` + */ + + /** + * 设置编辑器的内容,可修改编辑器当前的html内容 + * @method setContent + * @warning 通过该方法插入的内容,是经过编辑器内置的过滤规则进行过滤后得到的内容 + * @warning 该方法会触发selectionchange事件 + * @param { String } html 要插入的html内容 + * @param { Boolean } isAppendTo 若传入true,不清空原来的内容,在最后插入内容,否则,清空内容再插入 + * @example + * ```javascript + * //假设设置前的编辑器内容是

old text

+ * editor.setContent('

new text

', true); //插入的结果是

old text

new text

+ * ``` + */ + setContent: function (html, isAppendTo, notFireSelectionchange) { + var me = this; + + me.fireEvent('beforesetcontent', html); + var root = UE.htmlparser(html); + me.filterInputRule(root); + html = root.toHtml(); + + me.body.innerHTML = (isAppendTo ? me.body.innerHTML : '') + html; + + + function isCdataDiv(node){ + return node.tagName == 'DIV' && node.getAttribute('cdata_tag'); + } + //给文本或者inline节点套p标签 + if (me.options.enterTag == 'p') { + + var child = this.body.firstChild, tmpNode; + if (!child || child.nodeType == 1 && + (dtd.$cdata[child.tagName] || isCdataDiv(child) || + domUtils.isCustomeNode(child) + ) + && child === this.body.lastChild) { + this.body.innerHTML = '

' + (browser.ie ? ' ' : '
') + '

' + this.body.innerHTML; + + } else { + var p = me.document.createElement('p'); + while (child) { + while (child && (child.nodeType == 3 || child.nodeType == 1 && dtd.p[child.tagName] && !dtd.$cdata[child.tagName])) { + tmpNode = child.nextSibling; + p.appendChild(child); + child = tmpNode; + } + if (p.firstChild) { + if (!child) { + me.body.appendChild(p); + break; + } else { + child.parentNode.insertBefore(p, child); + p = me.document.createElement('p'); + } + } + child = child.nextSibling; + } + } + } + me.fireEvent('aftersetcontent'); + me.fireEvent('contentchange'); + + !notFireSelectionchange && me._selectionChange(); + //清除保存的选区 + me._bakRange = me._bakIERange = me._bakNativeRange = null; + //trace:1742 setContent后gecko能得到焦点问题 + var geckoSel; + if (browser.gecko && (geckoSel = this.selection.getNative())) { + geckoSel.removeAllRanges(); + } + if(me.options.autoSyncData){ + me.form && setValue(me.form,me); + } + }, + + /** + * 让编辑器获得焦点,默认focus到编辑器头部 + * @method focus + * @example + * ```javascript + * editor.focus() + * ``` + */ + + /** + * 让编辑器获得焦点,toEnd确定focus位置 + * @method focus + * @param { Boolean } toEnd 默认focus到编辑器头部,toEnd为true时focus到内容尾部 + * @example + * ```javascript + * editor.focus(true) + * ``` + */ + focus: function (toEnd) { + try { + var me = this, + rng = me.selection.getRange(); + if (toEnd) { + var node = me.body.lastChild; + if(node && node.nodeType == 1 && !dtd.$empty[node.tagName]){ + if(domUtils.isEmptyBlock(node)){ + rng.setStartAtFirst(node) + }else{ + rng.setStartAtLast(node) + } + rng.collapse(true); + } + rng.setCursor(true); + } else { + if(!rng.collapsed && domUtils.isBody(rng.startContainer) && rng.startOffset == 0){ + + var node = me.body.firstChild; + if(node && node.nodeType == 1 && !dtd.$empty[node.tagName]){ + rng.setStartAtFirst(node).collapse(true); + } + } + + rng.select(true); + + } + this.fireEvent('focus selectionchange'); + } catch (e) { + } + + }, + isFocus:function(){ + return this.selection.isFocus(); + }, + blur:function(){ + var sel = this.selection.getNative(); + if(sel.empty && browser.ie){ + var nativeRng = document.body.createTextRange(); + nativeRng.moveToElementText(document.body); + nativeRng.collapse(true); + nativeRng.select(); + sel.empty() + }else{ + sel.removeAllRanges() + } + + //this.fireEvent('blur selectionchange'); + }, + /** + * 初始化UE事件及部分事件代理 + * @method _initEvents + * @private + */ + _initEvents: function () { + var me = this, + doc = me.document, + win = me.window; + me._proxyDomEvent = utils.bind(me._proxyDomEvent, me); + domUtils.on(doc, ['click', 'contextmenu', 'mousedown', 'keydown', 'keyup', 'keypress', 'mouseup', 'mouseover', 'mouseout', 'selectstart'], me._proxyDomEvent); + domUtils.on(win, ['focus', 'blur'], me._proxyDomEvent); + domUtils.on(me.body,'drop',function(e){ + //阻止ff下默认的弹出新页面打开图片 + if(browser.gecko && e.stopPropagation) { e.stopPropagation(); } + me.fireEvent('contentchange') + }); + domUtils.on(doc, ['mouseup', 'keydown'], function (evt) { + //特殊键不触发selectionchange + if (evt.type == 'keydown' && (evt.ctrlKey || evt.metaKey || evt.shiftKey || evt.altKey)) { + return; + } + if (evt.button == 2)return; + me._selectionChange(250, evt); + }); + }, + /** + * 触发事件代理 + * @method _proxyDomEvent + * @private + * @return { * } fireEvent的返回值 + * @see UE.EventBase:fireEvent(String) + */ + _proxyDomEvent: function (evt) { + if(this.fireEvent('before' + evt.type.replace(/^on/, '').toLowerCase()) === false){ + return false; + } + if(this.fireEvent(evt.type.replace(/^on/, ''), evt) === false){ + return false; + } + return this.fireEvent('after' + evt.type.replace(/^on/, '').toLowerCase()) + }, + /** + * 变化选区 + * @method _selectionChange + * @private + */ + _selectionChange: function (delay, evt) { + var me = this; + //有光标才做selectionchange 为了解决未focus时点击source不能触发更改工具栏状态的问题(source命令notNeedUndo=1) +// if ( !me.selection.isFocus() ){ +// return; +// } + + + var hackForMouseUp = false; + var mouseX, mouseY; + if (browser.ie && browser.version < 9 && evt && evt.type == 'mouseup') { + var range = this.selection.getRange(); + if (!range.collapsed) { + hackForMouseUp = true; + mouseX = evt.clientX; + mouseY = evt.clientY; + } + } + clearTimeout(_selectionChangeTimer); + _selectionChangeTimer = setTimeout(function () { + if (!me.selection || !me.selection.getNative()) { + return; + } + //修复一个IE下的bug: 鼠标点击一段已选择的文本中间时,可能在mouseup后的一段时间内取到的range是在selection的type为None下的错误值. + //IE下如果用户是拖拽一段已选择文本,则不会触发mouseup事件,所以这里的特殊处理不会对其有影响 + var ieRange; + if (hackForMouseUp && me.selection.getNative().type == 'None') { + ieRange = me.document.body.createTextRange(); + try { + ieRange.moveToPoint(mouseX, mouseY); + } catch (ex) { + ieRange = null; + } + } + var bakGetIERange; + if (ieRange) { + bakGetIERange = me.selection.getIERange; + me.selection.getIERange = function () { + return ieRange; + }; + } + me.selection.cache(); + if (bakGetIERange) { + me.selection.getIERange = bakGetIERange; + } + if (me.selection._cachedRange && me.selection._cachedStartElement) { + me.fireEvent('beforeselectionchange'); + // 第二个参数causeByUi为true代表由用户交互造成的selectionchange. + me.fireEvent('selectionchange', !!evt); + me.fireEvent('afterselectionchange'); + me.selection.clear(); + } + }, delay || 50); + }, + + /** + * 执行编辑命令 + * @method _callCmdFn + * @private + * @param { String } fnName 函数名称 + * @param { * } args 传给命令函数的参数 + * @return { * } 返回命令函数运行的返回值 + */ + _callCmdFn: function (fnName, args) { + var cmdName = args[0].toLowerCase(), + cmd, cmdFn; + cmd = this.commands[cmdName] || UE.commands[cmdName]; + cmdFn = cmd && cmd[fnName]; + //没有querycommandstate或者没有command的都默认返回0 + if ((!cmd || !cmdFn) && fnName == 'queryCommandState') { + return 0; + } else if (cmdFn) { + return cmdFn.apply(this, args); + } + }, + + /** + * 执行编辑命令cmdName,完成富文本编辑效果 + * @method execCommand + * @param { String } cmdName 需要执行的命令 + * @remind 具体命令的使用请参考命令列表 + * @return { * } 返回命令函数运行的返回值 + * @example + * ```javascript + * editor.execCommand(cmdName); + * ``` + */ + execCommand: function (cmdName) { + cmdName = cmdName.toLowerCase(); + var me = this, + result, + cmd = me.commands[cmdName] || UE.commands[cmdName]; + if (!cmd || !cmd.execCommand) { + return null; + } + if (!cmd.notNeedUndo && !me.__hasEnterExecCommand) { + me.__hasEnterExecCommand = true; + if (me.queryCommandState.apply(me,arguments) != -1) { + me.fireEvent('saveScene'); + me.fireEvent.apply(me, ['beforeexeccommand', cmdName].concat(arguments)); + result = this._callCmdFn('execCommand', arguments); + //保存场景时,做了内容对比,再看是否进行contentchange触发,这里多触发了一次,去掉 +// (!cmd.ignoreContentChange && !me._ignoreContentChange) && me.fireEvent('contentchange'); + me.fireEvent.apply(me, ['afterexeccommand', cmdName].concat(arguments)); + me.fireEvent('saveScene'); + } + me.__hasEnterExecCommand = false; + } else { + result = this._callCmdFn('execCommand', arguments); + (!me.__hasEnterExecCommand && !cmd.ignoreContentChange && !me._ignoreContentChange) && me.fireEvent('contentchange') + } + (!me.__hasEnterExecCommand && !cmd.ignoreContentChange && !me._ignoreContentChange) && me._selectionChange(); + return result; + }, + + /** + * 根据传入的command命令,查选编辑器当前的选区,返回命令的状态 + * @method queryCommandState + * @param { String } cmdName 需要查询的命令名称 + * @remind 具体命令的使用请参考命令列表 + * @return { Number } number 返回放前命令的状态,返回值三种情况:(-1|0|1) + * @example + * ```javascript + * editor.queryCommandState(cmdName) => (-1|0|1) + * ``` + * @see COMMAND.LIST + */ + queryCommandState: function (cmdName) { + return this._callCmdFn('queryCommandState', arguments); + }, + + /** + * 根据传入的command命令,查选编辑器当前的选区,根据命令返回相关的值 + * @method queryCommandValue + * @param { String } cmdName 需要查询的命令名称 + * @remind 具体命令的使用请参考命令列表 + * @remind 只有部分插件有此方法 + * @return { * } 返回每个命令特定的当前状态值 + * @grammar editor.queryCommandValue(cmdName) => {*} + * @see COMMAND.LIST + */ + queryCommandValue: function (cmdName) { + return this._callCmdFn('queryCommandValue', arguments); + }, + + /** + * 检查编辑区域中是否有内容 + * @method hasContents + * @remind 默认有文本内容,或者有以下节点都不认为是空 + * table,ul,ol,dl,iframe,area,base,col,hr,img,embed,input,link,meta,param + * @return { Boolean } 检查有内容返回true,否则返回false + * @example + * ```javascript + * editor.hasContents() + * ``` + */ + + /** + * 检查编辑区域中是否有内容,若包含参数tags中的节点类型,直接返回true + * @method hasContents + * @param { Array } tags 传入数组判断时用到的节点类型 + * @return { Boolean } 若文档中包含tags数组里对应的tag,返回true,否则返回false + * @example + * ```javascript + * editor.hasContents(['span']); + * ``` + */ + hasContents: function (tags) { + if (tags) { + for (var i = 0, ci; ci = tags[i++];) { + if (this.document.getElementsByTagName(ci).length > 0) { + return true; + } + } + } + if (!domUtils.isEmptyBlock(this.body)) { + return true + } + //随时添加,定义的特殊标签如果存在,不能认为是空 + tags = ['div']; + for (i = 0; ci = tags[i++];) { + var nodes = domUtils.getElementsByTagName(this.document, ci); + for (var n = 0, cn; cn = nodes[n++];) { + if (domUtils.isCustomeNode(cn)) { + return true; + } + } + } + return false; + }, + + /** + * 重置编辑器,可用来做多个tab使用同一个编辑器实例 + * @method reset + * @remind 此方法会清空编辑器内容,清空回退列表,会触发reset事件 + * @example + * ```javascript + * editor.reset() + * ``` + */ + reset: function () { + this.fireEvent('reset'); + }, + + /** + * 设置当前编辑区域可以编辑 + * @method setEnabled + * @example + * ```javascript + * editor.setEnabled() + * ``` + */ + setEnabled: function () { + var me = this, range; + if (me.body.contentEditable == 'false') { + me.body.contentEditable = true; + range = me.selection.getRange(); + //有可能内容丢失了 + try { + range.moveToBookmark(me.lastBk); + delete me.lastBk + } catch (e) { + range.setStartAtFirst(me.body).collapse(true) + } + range.select(true); + if (me.bkqueryCommandState) { + me.queryCommandState = me.bkqueryCommandState; + delete me.bkqueryCommandState; + } + if (me.bkqueryCommandValue) { + me.queryCommandValue = me.bkqueryCommandValue; + delete me.bkqueryCommandValue; + } + me.fireEvent('selectionchange'); + } + }, + enable: function () { + return this.setEnabled(); + }, + + /** 设置当前编辑区域不可编辑 + * @method setDisabled + */ + + /** 设置当前编辑区域不可编辑,except中的命令除外 + * @method setDisabled + * @param { String } except 例外命令的字符串 + * @remind 即使设置了disable,此处配置的例外命令仍然可以执行 + * @example + * ```javascript + * editor.setDisabled('bold'); //禁用工具栏中除加粗之外的所有功能 + * ``` + */ + + /** 设置当前编辑区域不可编辑,except中的命令除外 + * @method setDisabled + * @param { Array } except 例外命令的字符串数组,数组中的命令仍然可以执行 + * @remind 即使设置了disable,此处配置的例外命令仍然可以执行 + * @example + * ```javascript + * editor.setDisabled(['bold','insertimage']); //禁用工具栏中除加粗和插入图片之外的所有功能 + * ``` + */ + setDisabled: function (except) { + var me = this; + except = except ? utils.isArray(except) ? except : [except] : []; + if (me.body.contentEditable == 'true') { + if (!me.lastBk) { + me.lastBk = me.selection.getRange().createBookmark(true); + } + me.body.contentEditable = false; + me.bkqueryCommandState = me.queryCommandState; + me.bkqueryCommandValue = me.queryCommandValue; + me.queryCommandState = function (type) { + if (utils.indexOf(except, type) != -1) { + return me.bkqueryCommandState.apply(me, arguments); + } + return -1; + }; + me.queryCommandValue = function (type) { + if (utils.indexOf(except, type) != -1) { + return me.bkqueryCommandValue.apply(me, arguments); + } + return null; + }; + me.fireEvent('selectionchange'); + } + }, + disable: function (except) { + return this.setDisabled(except); + }, + + /** + * 设置默认内容 + * @method _setDefaultContent + * @private + * @param { String } cont 要存入的内容 + */ + _setDefaultContent: function () { + function clear() { + var me = this; + if (me.document.getElementById('initContent')) { + me.body.innerHTML = '

' + (ie ? '' : '
') + '

'; + me.removeListener('firstBeforeExecCommand focus', clear); + setTimeout(function () { + me.focus(); + me._selectionChange(); + }, 0) + } + } + + return function (cont) { + var me = this; + me.body.innerHTML = '

' + cont + '

'; + + me.addListener('firstBeforeExecCommand focus', clear); + } + }(), + + /** + * 显示编辑器 + * @method setShow + * @example + * ```javascript + * editor.setShow() + * ``` + */ + setShow: function () { + var me = this, range = me.selection.getRange(); + if (me.container.style.display == 'none') { + //有可能内容丢失了 + try { + range.moveToBookmark(me.lastBk); + delete me.lastBk + } catch (e) { + range.setStartAtFirst(me.body).collapse(true) + } + //ie下focus实效,所以做了个延迟 + setTimeout(function () { + range.select(true); + }, 100); + me.container.style.display = ''; + } + + }, + show: function () { + return this.setShow(); + }, + /** + * 隐藏编辑器 + * @method setHide + * @example + * ```javascript + * editor.setHide() + * ``` + */ + setHide: function () { + var me = this; + if (!me.lastBk) { + me.lastBk = me.selection.getRange().createBookmark(true); + } + me.container.style.display = 'none' + }, + hide: function () { + return this.setHide(); + }, + + /** + * 根据指定的路径,获取对应的语言资源 + * @method getLang + * @param { String } path 路径根据的是lang目录下的语言文件的路径结构 + * @return { Object | String } 根据路径返回语言资源的Json格式对象或者语言字符串 + * @example + * ```javascript + * editor.getLang('contextMenu.delete'); //如果当前是中文,那返回是的是'删除' + * ``` + */ + getLang: function (path) { + var lang = UE.I18N[this.options.lang]; + if (!lang) { + throw Error("not import language file"); + } + path = (path || "").split("."); + for (var i = 0, ci; ci = path[i++];) { + lang = lang[ci]; + if (!lang)break; + } + return lang; + }, + + /** + * 计算编辑器html内容字符串的长度 + * @method getContentLength + * @return { Number } 返回计算的长度 + * @example + * ```javascript + * //编辑器html内容

132

+ * editor.getContentLength() //返回27 + * ``` + */ + /** + * 计算编辑器当前纯文本内容的长度 + * @method getContentLength + * @param { Boolean } ingoneHtml 传入true时,只按照纯文本来计算 + * @return { Number } 返回计算的长度,内容中有hr/img/iframe标签,长度加1 + * @example + * ```javascript + * //编辑器html内容

132

+ * editor.getContentLength() //返回3 + * ``` + */ + getContentLength: function (ingoneHtml, tagNames) { + var count = this.getContent(false,false,true).length; + if (ingoneHtml) { + tagNames = (tagNames || []).concat([ 'hr', 'img', 'iframe']); + count = this.getContentTxt().replace(/[\t\r\n]+/g, '').length; + for (var i = 0, ci; ci = tagNames[i++];) { + count += this.document.getElementsByTagName(ci).length; + } + } + return count; + }, + + /** + * 注册输入过滤规则 + * @method addInputRule + * @param { Function } rule 要添加的过滤规则 + * @example + * ```javascript + * editor.addInputRule(function(root){ + * $.each(root.getNodesByTagName('div'),function(i,node){ + * node.tagName="p"; + * }); + * }); + * ``` + */ + addInputRule: function (rule) { + this.inputRules.push(rule); + }, + + /** + * 执行注册的过滤规则 + * @method filterInputRule + * @param { UE.uNode } root 要过滤的uNode节点 + * @remind 执行editor.setContent方法和执行'inserthtml'命令后,会运行该过滤函数 + * @example + * ```javascript + * editor.filterInputRule(editor.body); + * ``` + * @see UE.Editor:addInputRule + */ + filterInputRule: function (root) { + for (var i = 0, ci; ci = this.inputRules[i++];) { + ci.call(this, root) + } + }, + + /** + * 注册输出过滤规则 + * @method addOutputRule + * @param { Function } rule 要添加的过滤规则 + * @example + * ```javascript + * editor.addOutputRule(function(root){ + * $.each(root.getNodesByTagName('p'),function(i,node){ + * node.tagName="div"; + * }); + * }); + * ``` + */ + addOutputRule: function (rule) { + this.outputRules.push(rule) + }, + + /** + * 根据输出过滤规则,过滤编辑器内容 + * @method filterOutputRule + * @remind 执行editor.getContent方法的时候,会先运行该过滤函数 + * @param { UE.uNode } root 要过滤的uNode节点 + * @example + * ```javascript + * editor.filterOutputRule(editor.body); + * ``` + * @see UE.Editor:addOutputRule + */ + filterOutputRule: function (root) { + for (var i = 0, ci; ci = this.outputRules[i++];) { + ci.call(this, root) + } + }, + + /** + * 根据action名称获取请求的路径 + * @method getActionUrl + * @remind 假如没有设置serverUrl,会根据imageUrl设置默认的controller路径 + * @param { String } action action名称 + * @example + * ```javascript + * editor.getActionUrl('config'); //返回 "/ueditor/php/controller.php?action=config" + * editor.getActionUrl('image'); //返回 "/ueditor/php/controller.php?action=uplaodimage" + * editor.getActionUrl('scrawl'); //返回 "/ueditor/php/controller.php?action=uplaodscrawl" + * editor.getActionUrl('imageManager'); //返回 "/ueditor/php/controller.php?action=listimage" + * ``` + */ + getActionUrl: function(action){ + var actionName = this.getOpt(action) || action, + imageUrl = this.getOpt('imageUrl'), + serverUrl = this.getOpt('serverUrl'); + + if(!serverUrl && imageUrl) { + serverUrl = imageUrl.replace(/^(.*[\/]).+([\.].+)$/, '$1controller$2'); + } + + if(serverUrl) { + serverUrl = serverUrl + (serverUrl.indexOf('?') == -1 ? '?':'&') + 'action=' + (actionName || ''); + return utils.formatUrl(serverUrl); + } else { + return ''; + } + } + }; + utils.inherits(Editor, EventBase); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/EventBase.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/EventBase.js new file mode 100644 index 000000000..0b77406fc --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/EventBase.js @@ -0,0 +1,167 @@ +/** + * UE采用的事件基类 + * @file + * @module UE + * @class EventBase + * @since 1.2.6.1 + */ + +/** + * UEditor公用空间,UEditor所有的功能都挂载在该空间下 + * @unfile + * @module UE + */ + +/** + * UE采用的事件基类,继承此类的对应类将获取addListener,removeListener,fireEvent方法。 + * 在UE中,Editor以及所有ui实例都继承了该类,故可以在对应的ui对象以及editor对象上使用上述方法。 + * @unfile + * @module UE + * @class EventBase + */ + +/** + * 通过此构造器,子类可以继承EventBase获取事件监听的方法 + * @constructor + * @example + * ```javascript + * UE.EventBase.call(editor); + * ``` + */ +var EventBase = UE.EventBase = function () {}; + +EventBase.prototype = { + + /** + * 注册事件监听器 + * @method addListener + * @param { String } types 监听的事件名称,同时监听多个事件使用空格分隔 + * @param { Function } fn 监听的事件被触发时,会执行该回调函数 + * @waining 事件被触发时,监听的函数假如返回的值恒等于true,回调函数的队列中后面的函数将不执行 + * @example + * ```javascript + * editor.addListener('selectionchange',function(){ + * console.log("选区已经变化!"); + * }) + * editor.addListener('beforegetcontent aftergetcontent',function(type){ + * if(type == 'beforegetcontent'){ + * //do something + * }else{ + * //do something + * } + * console.log(this.getContent) // this是注册的事件的编辑器实例 + * }) + * ``` + * @see UE.EventBase:fireEvent(String) + */ + addListener:function (types, listener) { + types = utils.trim(types).split(/\s+/); + for (var i = 0, ti; ti = types[i++];) { + getListener(this, ti, true).push(listener); + } + }, + + on : function(types, listener){ + return this.addListener(types,listener); + }, + off : function(types, listener){ + return this.removeListener(types, listener) + }, + trigger:function(){ + return this.fireEvent.apply(this,arguments); + }, + /** + * 移除事件监听器 + * @method removeListener + * @param { String } types 移除的事件名称,同时移除多个事件使用空格分隔 + * @param { Function } fn 移除监听事件的函数引用 + * @example + * ```javascript + * //changeCallback为方法体 + * editor.removeListener("selectionchange",changeCallback); + * ``` + */ + removeListener:function (types, listener) { + types = utils.trim(types).split(/\s+/); + for (var i = 0, ti; ti = types[i++];) { + utils.removeItem(getListener(this, ti) || [], listener); + } + }, + + /** + * 触发事件 + * @method fireEvent + * @param { String } types 触发的事件名称,同时触发多个事件使用空格分隔 + * @remind 该方法会触发addListener + * @return { * } 返回触发事件的队列中,最后执行的回调函数的返回值 + * @example + * ```javascript + * editor.fireEvent("selectionchange"); + * ``` + */ + + /** + * 触发事件 + * @method fireEvent + * @param { String } types 触发的事件名称,同时触发多个事件使用空格分隔 + * @param { *... } options 可选参数,可以传入一个或多个参数,会传给事件触发的回调函数 + * @return { * } 返回触发事件的队列中,最后执行的回调函数的返回值 + * @example + * ```javascript + * + * editor.addListener( "selectionchange", function ( type, arg1, arg2 ) { + * + * console.log( arg1 + " " + arg2 ); + * + * } ); + * + * //触发selectionchange事件, 会执行上面的事件监听器 + * //output: Hello World + * editor.fireEvent("selectionchange", "Hello", "World"); + * ``` + */ + fireEvent:function () { + var types = arguments[0]; + types = utils.trim(types).split(' '); + for (var i = 0, ti; ti = types[i++];) { + var listeners = getListener(this, ti), + r, t, k; + if (listeners) { + k = listeners.length; + while (k--) { + if(!listeners[k])continue; + t = listeners[k].apply(this, arguments); + if(t === true){ + return t; + } + if (t !== undefined) { + r = t; + } + } + } + if (t = this['on' + ti.toLowerCase()]) { + r = t.apply(this, arguments); + } + } + return r; + } +}; +/** + * 获得对象所拥有监听类型的所有监听器 + * @unfile + * @module UE + * @since 1.2.6.1 + * @method getListener + * @public + * @param { Object } obj 查询监听器的对象 + * @param { String } type 事件类型 + * @param { Boolean } force 为true且当前所有type类型的侦听器不存在时,创建一个空监听器数组 + * @return { Array } 监听器数组 + */ +function getListener(obj, type, force) { + var allListeners; + type = type.toLowerCase(); + return ( ( allListeners = ( obj.__allListeners || force && ( obj.__allListeners = {} ) ) ) + && ( allListeners[type] || force && ( allListeners[type] = [] ) ) ); +} + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/Range.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/Range.js new file mode 100644 index 000000000..8e331b30b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/Range.js @@ -0,0 +1,1845 @@ +/** + * Range封装 + * @file + * @module UE.dom + * @class Range + * @since 1.2.6.1 + */ + +/** + * dom操作封装 + * @unfile + * @module UE.dom + */ + +/** + * Range实现类,本类是UEditor底层核心类,封装不同浏览器之间的Range操作。 + * @unfile + * @module UE.dom + * @class Range + */ + + +(function () { + var guid = 0, + fillChar = domUtils.fillChar, + fillData; + + /** + * 更新range的collapse状态 + * @param {Range} range range对象 + */ + function updateCollapse(range) { + range.collapsed = + range.startContainer && range.endContainer && + range.startContainer === range.endContainer && + range.startOffset == range.endOffset; + } + + function selectOneNode(rng){ + return !rng.collapsed && rng.startContainer.nodeType == 1 && rng.startContainer === rng.endContainer && rng.endOffset - rng.startOffset == 1 + } + function setEndPoint(toStart, node, offset, range) { + //如果node是自闭合标签要处理 + if (node.nodeType == 1 && (dtd.$empty[node.tagName] || dtd.$nonChild[node.tagName])) { + offset = domUtils.getNodeIndex(node) + (toStart ? 0 : 1); + node = node.parentNode; + } + if (toStart) { + range.startContainer = node; + range.startOffset = offset; + if (!range.endContainer) { + range.collapse(true); + } + } else { + range.endContainer = node; + range.endOffset = offset; + if (!range.startContainer) { + range.collapse(false); + } + } + updateCollapse(range); + return range; + } + + function execContentsAction(range, action) { + //调整边界 + //range.includeBookmark(); + var start = range.startContainer, + end = range.endContainer, + startOffset = range.startOffset, + endOffset = range.endOffset, + doc = range.document, + frag = doc.createDocumentFragment(), + tmpStart, tmpEnd; + if (start.nodeType == 1) { + start = start.childNodes[startOffset] || (tmpStart = start.appendChild(doc.createTextNode(''))); + } + if (end.nodeType == 1) { + end = end.childNodes[endOffset] || (tmpEnd = end.appendChild(doc.createTextNode(''))); + } + if (start === end && start.nodeType == 3) { + frag.appendChild(doc.createTextNode(start.substringData(startOffset, endOffset - startOffset))); + //is not clone + if (action) { + start.deleteData(startOffset, endOffset - startOffset); + range.collapse(true); + } + return frag; + } + var current, currentLevel, clone = frag, + startParents = domUtils.findParents(start, true), endParents = domUtils.findParents(end, true); + for (var i = 0; startParents[i] == endParents[i];) { + i++; + } + for (var j = i, si; si = startParents[j]; j++) { + current = si.nextSibling; + if (si == start) { + if (!tmpStart) { + if (range.startContainer.nodeType == 3) { + clone.appendChild(doc.createTextNode(start.nodeValue.slice(startOffset))); + //is not clone + if (action) { + start.deleteData(startOffset, start.nodeValue.length - startOffset); + } + } else { + clone.appendChild(!action ? start.cloneNode(true) : start); + } + } + } else { + currentLevel = si.cloneNode(false); + clone.appendChild(currentLevel); + } + while (current) { + if (current === end || current === endParents[j]) { + break; + } + si = current.nextSibling; + clone.appendChild(!action ? current.cloneNode(true) : current); + current = si; + } + clone = currentLevel; + } + clone = frag; + if (!startParents[i]) { + clone.appendChild(startParents[i - 1].cloneNode(false)); + clone = clone.firstChild; + } + for (var j = i, ei; ei = endParents[j]; j++) { + current = ei.previousSibling; + if (ei == end) { + if (!tmpEnd && range.endContainer.nodeType == 3) { + clone.appendChild(doc.createTextNode(end.substringData(0, endOffset))); + //is not clone + if (action) { + end.deleteData(0, endOffset); + } + } + } else { + currentLevel = ei.cloneNode(false); + clone.appendChild(currentLevel); + } + //如果两端同级,右边第一次已经被开始做了 + if (j != i || !startParents[i]) { + while (current) { + if (current === start) { + break; + } + ei = current.previousSibling; + clone.insertBefore(!action ? current.cloneNode(true) : current, clone.firstChild); + current = ei; + } + } + clone = currentLevel; + } + if (action) { + range.setStartBefore(!endParents[i] ? endParents[i - 1] : !startParents[i] ? startParents[i - 1] : endParents[i]).collapse(true); + } + tmpStart && domUtils.remove(tmpStart); + tmpEnd && domUtils.remove(tmpEnd); + return frag; + } + + /** + * 创建一个跟document绑定的空的Range实例 + * @constructor + * @param { Document } document 新建的选区所属的文档对象 + */ + + /** + * @property { Node } startContainer 当前Range的开始边界的容器节点, 可以是一个元素节点或者是文本节点 + */ + + /** + * @property { Node } startOffset 当前Range的开始边界容器节点的偏移量, 如果是元素节点, + * 该值就是childNodes中的第几个节点, 如果是文本节点就是文本内容的第几个字符 + */ + + /** + * @property { Node } endContainer 当前Range的结束边界的容器节点, 可以是一个元素节点或者是文本节点 + */ + + /** + * @property { Node } endOffset 当前Range的结束边界容器节点的偏移量, 如果是元素节点, + * 该值就是childNodes中的第几个节点, 如果是文本节点就是文本内容的第几个字符 + */ + + /** + * @property { Boolean } collapsed 当前Range是否闭合 + * @default true + * @remind Range是闭合的时候, startContainer === endContainer && startOffset === endOffset + */ + + /** + * @property { Document } document 当前Range所属的Document对象 + * @remind 不同range的的document属性可以是不同的 + */ + var Range = dom.Range = function (document) { + var me = this; + me.startContainer = + me.startOffset = + me.endContainer = + me.endOffset = null; + me.document = document; + me.collapsed = true; + }; + + /** + * 删除fillData + * @param doc + * @param excludeNode + */ + function removeFillData(doc, excludeNode) { + try { + if (fillData && domUtils.inDoc(fillData, doc)) { + if (!fillData.nodeValue.replace(fillCharReg, '').length) { + var tmpNode = fillData.parentNode; + domUtils.remove(fillData); + while (tmpNode && domUtils.isEmptyInlineElement(tmpNode) && + //safari的contains有bug + (browser.safari ? !(domUtils.getPosition(tmpNode,excludeNode) & domUtils.POSITION_CONTAINS) : !tmpNode.contains(excludeNode)) + ) { + fillData = tmpNode.parentNode; + domUtils.remove(tmpNode); + tmpNode = fillData; + } + } else { + fillData.nodeValue = fillData.nodeValue.replace(fillCharReg, ''); + } + } + } catch (e) { + } + } + + /** + * @param node + * @param dir + */ + function mergeSibling(node, dir) { + var tmpNode; + node = node[dir]; + while (node && domUtils.isFillChar(node)) { + tmpNode = node[dir]; + domUtils.remove(node); + node = tmpNode; + } + } + + Range.prototype = { + + /** + * 克隆选区的内容到一个DocumentFragment里 + * @method cloneContents + * @return { DocumentFragment | NULL } 如果选区是闭合的将返回null, 否则, 返回包含所clone内容的DocumentFragment元素 + * @example + * ```html + * + * + * xx[xxx]x + * + * + * + * ``` + */ + cloneContents:function () { + return this.collapsed ? null : execContentsAction(this, 0); + }, + + /** + * 删除当前选区范围中的所有内容 + * @method deleteContents + * @remind 执行完该操作后, 当前Range对象变成了闭合状态 + * @return { UE.dom.Range } 当前操作的Range对象 + * @example + * ```html + * + * + * xx[xxx]x + * + * + * + * ``` + */ + deleteContents:function () { + var txt; + if (!this.collapsed) { + execContentsAction(this, 1); + } + if (browser.webkit) { + txt = this.startContainer; + if (txt.nodeType == 3 && !txt.nodeValue.length) { + this.setStartBefore(txt).collapse(true); + domUtils.remove(txt); + } + } + return this; + }, + + /** + * 将当前选区的内容提取到一个DocumentFragment里 + * @method extractContents + * @remind 执行该操作后, 选区将变成闭合状态 + * @warning 执行该操作后, 原来选区所选中的内容将从dom树上剥离出来 + * @return { DocumentFragment } 返回包含所提取内容的DocumentFragment对象 + * @example + * ```html + * + * + * xx[xxx]x + * + * + * + */ + extractContents:function () { + return this.collapsed ? null : execContentsAction(this, 2); + }, + + /** + * 设置Range的开始容器节点和偏移量 + * @method setStart + * @remind 如果给定的节点是元素节点,那么offset指的是其子元素中索引为offset的元素, + * 如果是文本节点,那么offset指的是其文本内容的第offset个字符 + * @remind 如果提供的容器节点是一个不能包含子元素的节点, 则该选区的开始容器将被设置 + * 为该节点的父节点, 此时, 其距离开始容器的偏移量也变成了该节点在其父节点 + * 中的索引 + * @param { Node } node 将被设为当前选区开始边界容器的节点对象 + * @param { int } offset 选区的开始位置偏移量 + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * + * xxxxxxxxxxxxx[xxx] + * + * + * ``` + * @example + * ```html + * + * xxx[xx]x + * + * + * ``` + */ + setStart:function (node, offset) { + return setEndPoint(true, node, offset, this); + }, + + /** + * 设置Range的结束容器和偏移量 + * @method setEnd + * @param { Node } node 作为当前选区结束边界容器的节点对象 + * @param { int } offset 结束边界的偏移量 + * @see UE.dom.Range:setStart(Node,int) + * @return { UE.dom.Range } 当前range对象 + */ + setEnd:function (node, offset) { + return setEndPoint(false, node, offset, this); + }, + + /** + * 将Range开始位置设置到node节点之后 + * @method setStartAfter + * @remind 该操作将会把给定节点的父节点作为range的开始容器, 且偏移量是该节点在其父节点中的位置索引+1 + * @param { Node } node 选区的开始边界将紧接着该节点之后 + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * + * xxxxxxx[xxxx] + * + * + * ``` + */ + setStartAfter:function (node) { + return this.setStart(node.parentNode, domUtils.getNodeIndex(node) + 1); + }, + + /** + * 将Range开始位置设置到node节点之前 + * @method setStartBefore + * @remind 该操作将会把给定节点的父节点作为range的开始容器, 且偏移量是该节点在其父节点中的位置索引 + * @param { Node } node 新的选区开始位置在该节点之前 + * @see UE.dom.Range:setStartAfter(Node) + * @return { UE.dom.Range } 当前range对象 + */ + setStartBefore:function (node) { + return this.setStart(node.parentNode, domUtils.getNodeIndex(node)); + }, + + /** + * 将Range结束位置设置到node节点之后 + * @method setEndAfter + * @remind 该操作将会把给定节点的父节点作为range的结束容器, 且偏移量是该节点在其父节点中的位置索引+1 + * @param { Node } node 目标节点 + * @see UE.dom.Range:setStartAfter(Node) + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * + * [xxxxxxx]xxxx + * + * + * ``` + */ + setEndAfter:function (node) { + return this.setEnd(node.parentNode, domUtils.getNodeIndex(node) + 1); + }, + + /** + * 将Range结束位置设置到node节点之前 + * @method setEndBefore + * @remind 该操作将会把给定节点的父节点作为range的结束容器, 且偏移量是该节点在其父节点中的位置索引 + * @param { Node } node 目标节点 + * @see UE.dom.Range:setEndAfter(Node) + * @return { UE.dom.Range } 当前range对象 + */ + setEndBefore:function (node) { + return this.setEnd(node.parentNode, domUtils.getNodeIndex(node)); + }, + + /** + * 设置Range的开始位置到node节点内的第一个子节点之前 + * @method setStartAtFirst + * @remind 选区的开始容器将变成给定的节点, 且偏移量为0 + * @remind 如果给定的节点是元素节点, 则该节点必须是允许包含子节点的元素。 + * @param { Node } node 目标节点 + * @see UE.dom.Range:setStartBefore(Node) + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * + * xxxxx[xx]xxxx + * + * + * ``` + */ + setStartAtFirst:function (node) { + return this.setStart(node, 0); + }, + + /** + * 设置Range的开始位置到node节点内的最后一个节点之后 + * @method setStartAtLast + * @remind 选区的开始容器将变成给定的节点, 且偏移量为该节点的子节点数 + * @remind 如果给定的节点是元素节点, 则该节点必须是允许包含子节点的元素。 + * @param { Node } node 目标节点 + * @see UE.dom.Range:setStartAtFirst(Node) + * @return { UE.dom.Range } 当前range对象 + */ + setStartAtLast:function (node) { + return this.setStart(node, node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length); + }, + + /** + * 设置Range的结束位置到node节点内的第一个节点之前 + * @method setEndAtFirst + * @param { Node } node 目标节点 + * @remind 选区的结束容器将变成给定的节点, 且偏移量为0 + * @remind node必须是一个元素节点, 且必须是允许包含子节点的元素。 + * @see UE.dom.Range:setStartAtFirst(Node) + * @return { UE.dom.Range } 当前range对象 + */ + setEndAtFirst:function (node) { + return this.setEnd(node, 0); + }, + + /** + * 设置Range的结束位置到node节点内的最后一个节点之后 + * @method setEndAtLast + * @param { Node } node 目标节点 + * @remind 选区的结束容器将变成给定的节点, 且偏移量为该节点的子节点数量 + * @remind node必须是一个元素节点, 且必须是允许包含子节点的元素。 + * @see UE.dom.Range:setStartAtFirst(Node) + * @return { UE.dom.Range } 当前range对象 + */ + setEndAtLast:function (node) { + return this.setEnd(node, node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length); + }, + + /** + * 选中给定节点 + * @method selectNode + * @remind 此时, 选区的开始容器和结束容器都是该节点的父节点, 其startOffset是该节点在父节点中的位置索引, + * 而endOffset为startOffset+1 + * @param { Node } node 需要选中的节点 + * @return { UE.dom.Range } 当前range对象,此时的range仅包含当前给定的节点对象 + * @example + * ```html + * + * xxxxx[xx]xxxx + * + * + * ``` + */ + selectNode:function (node) { + return this.setStartBefore(node).setEndAfter(node); + }, + + /** + * 选中给定节点内部的所有节点 + * @method selectNodeContents + * @remind 此时, 选区的开始容器和结束容器都是该节点, 其startOffset为0, + * 而endOffset是该节点的子节点数。 + * @param { Node } node 目标节点, 当前range将包含该节点内的所有节点 + * @return { UE.dom.Range } 当前range对象, 此时range仅包含给定节点的所有子节点 + * @example + * ```html + * + * xxxxx[xx]xxxx + * + * + * ``` + */ + selectNodeContents:function (node) { + return this.setStart(node, 0).setEndAtLast(node); + }, + + /** + * clone当前Range对象 + * @method cloneRange + * @remind 返回的range是一个全新的range对象, 其内部所有属性与当前被clone的range相同。 + * @return { UE.dom.Range } 当前range对象的一个副本 + */ + cloneRange:function () { + var me = this; + return new Range(me.document).setStart(me.startContainer, me.startOffset).setEnd(me.endContainer, me.endOffset); + + }, + + /** + * 向当前选区的结束处闭合选区 + * @method collapse + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * + * xxxxx[xx]xxxx + * + * + * ``` + */ + + /** + * 闭合当前选区,根据给定的toStart参数项决定是向当前选区开始处闭合还是向结束处闭合, + * 如果toStart的值为true,则向开始位置闭合, 反之,向结束位置闭合。 + * @method collapse + * @param { Boolean } toStart 是否向选区开始处闭合 + * @return { UE.dom.Range } 当前range对象,此时range对象处于闭合状态 + * @see UE.dom.Range:collapse() + * @example + * ```html + * + * xxxxx[xx]xxxx + * + * + * ``` + */ + collapse:function (toStart) { + var me = this; + if (toStart) { + me.endContainer = me.startContainer; + me.endOffset = me.startOffset; + } else { + me.startContainer = me.endContainer; + me.startOffset = me.endOffset; + } + me.collapsed = true; + return me; + }, + + /** + * 调整range的开始位置和结束位置,使其"收缩"到最小的位置 + * @method shrinkBoundary + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * xxxx[xxxxx] => xxxx[xxxxx] + * ``` + * + * @example + * ```html + * + * x[xx]xxx + * + * + * ``` + * + * @example + * ```html + * [xxxxxxxxxxx] => [xxxxxxxxxxx] + * ``` + */ + + /** + * 调整range的开始位置和结束位置,使其"收缩"到最小的位置, + * 如果ignoreEnd的值为true,则忽略对结束位置的调整 + * @method shrinkBoundary + * @param { Boolean } ignoreEnd 是否忽略对结束位置的调整 + * @return { UE.dom.Range } 当前range对象 + * @see UE.dom.domUtils.Range:shrinkBoundary() + */ + shrinkBoundary:function (ignoreEnd) { + var me = this, child, + collapsed = me.collapsed; + function check(node){ + return node.nodeType == 1 && !domUtils.isBookmarkNode(node) && !dtd.$empty[node.tagName] && !dtd.$nonChild[node.tagName] + } + while (me.startContainer.nodeType == 1 //是element + && (child = me.startContainer.childNodes[me.startOffset]) //子节点也是element + && check(child)) { + me.setStart(child, 0); + } + if (collapsed) { + return me.collapse(true); + } + if (!ignoreEnd) { + while (me.endContainer.nodeType == 1//是element + && me.endOffset > 0 //如果是空元素就退出 endOffset=0那么endOffst-1为负值,childNodes[endOffset]报错 + && (child = me.endContainer.childNodes[me.endOffset - 1]) //子节点也是element + && check(child)) { + me.setEnd(child, child.childNodes.length); + } + } + return me; + }, + + /** + * 获取离当前选区内包含的所有节点最近的公共祖先节点, + * @method getCommonAncestor + * @remind 返回的公共祖先节点一定不是range自身的容器节点, 但有可能是一个文本节点 + * @return { Node } 当前range对象内所有节点的公共祖先节点 + * @example + * ```html + * //选区示例 + * xxxx[xxx]xxxxxx + * + * ``` + */ + + /** + * 获取当前选区所包含的所有节点的公共祖先节点, 可以根据给定的参数 includeSelf 决定获取到 + * 的公共祖先节点是否可以是当前选区的startContainer或endContainer节点, 如果 includeSelf + * 的取值为true, 则返回的节点可以是自身的容器节点, 否则, 则不能是容器节点 + * @method getCommonAncestor + * @param { Boolean } includeSelf 是否允许获取到的公共祖先节点是当前range对象的容器节点 + * @return { Node } 当前range对象内所有节点的公共祖先节点 + * @see UE.dom.Range:getCommonAncestor() + * @example + * ```html + * + * + * + * xxxxxxxxx[xxx]xxxxxxxx + * + * + * + * + * ``` + */ + + /** + * 获取当前选区所包含的所有节点的公共祖先节点, 可以根据给定的参数 includeSelf 决定获取到 + * 的公共祖先节点是否可以是当前选区的startContainer或endContainer节点, 如果 includeSelf + * 的取值为true, 则返回的节点可以是自身的容器节点, 否则, 则不能是容器节点; 同时可以根据 + * ignoreTextNode 参数的取值决定是否忽略类型为文本节点的祖先节点。 + * @method getCommonAncestor + * @param { Boolean } includeSelf 是否允许获取到的公共祖先节点是当前range对象的容器节点 + * @param { Boolean } ignoreTextNode 获取祖先节点的过程中是否忽略类型为文本节点的祖先节点 + * @return { Node } 当前range对象内所有节点的公共祖先节点 + * @see UE.dom.Range:getCommonAncestor() + * @see UE.dom.Range:getCommonAncestor(Boolean) + * @example + * ```html + * + * + * + * xxxxxxxx[x]xxxxxxxxxxx + * + * + * + * + * ``` + */ + getCommonAncestor:function (includeSelf, ignoreTextNode) { + var me = this, + start = me.startContainer, + end = me.endContainer; + if (start === end) { + if (includeSelf && selectOneNode(this)) { + start = start.childNodes[me.startOffset]; + if(start.nodeType == 1) + return start; + } + //只有在上来就相等的情况下才会出现是文本的情况 + return ignoreTextNode && start.nodeType == 3 ? start.parentNode : start; + } + return domUtils.getCommonAncestor(start, end); + }, + + /** + * 调整当前Range的开始和结束边界容器,如果是容器节点是文本节点,就调整到包含该文本节点的父节点上 + * @method trimBoundary + * @remind 该操作有可能会引起文本节点被切开 + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * + * //选区示例 + * xxx[xxxxx]xxx + * + * + * ``` + */ + + /** + * 调整当前Range的开始和结束边界容器,如果是容器节点是文本节点,就调整到包含该文本节点的父节点上, + * 可以根据 ignoreEnd 参数的值决定是否调整对结束边界的调整 + * @method trimBoundary + * @param { Boolean } ignoreEnd 是否忽略对结束边界的调整 + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * + * //选区示例 + * xxx[xxxxx]xxx + * + * + * ``` + */ + trimBoundary:function (ignoreEnd) { + this.txtToElmBoundary(); + var start = this.startContainer, + offset = this.startOffset, + collapsed = this.collapsed, + end = this.endContainer; + if (start.nodeType == 3) { + if (offset == 0) { + this.setStartBefore(start); + } else { + if (offset >= start.nodeValue.length) { + this.setStartAfter(start); + } else { + var textNode = domUtils.split(start, offset); + //跟新结束边界 + if (start === end) { + this.setEnd(textNode, this.endOffset - offset); + } else if (start.parentNode === end) { + this.endOffset += 1; + } + this.setStartBefore(textNode); + } + } + if (collapsed) { + return this.collapse(true); + } + } + if (!ignoreEnd) { + offset = this.endOffset; + end = this.endContainer; + if (end.nodeType == 3) { + if (offset == 0) { + this.setEndBefore(end); + } else { + offset < end.nodeValue.length && domUtils.split(end, offset); + this.setEndAfter(end); + } + } + } + return this; + }, + + /** + * 如果选区在文本的边界上,就扩展选区到文本的父节点上, 如果当前选区是闭合的, 则什么也不做 + * @method txtToElmBoundary + * @remind 该操作不会修改dom节点 + * @return { UE.dom.Range } 当前range对象 + */ + + /** + * 如果选区在文本的边界上,就扩展选区到文本的父节点上, 如果当前选区是闭合的, 则根据参数项 + * ignoreCollapsed 的值决定是否执行该调整 + * @method txtToElmBoundary + * @param { Boolean } ignoreCollapsed 是否忽略选区的闭合状态, 如果该参数取值为true, 则 + * 不论选区是否闭合, 都会执行该操作, 反之, 则不会对闭合的选区执行该操作 + * @return { UE.dom.Range } 当前range对象 + */ + txtToElmBoundary:function (ignoreCollapsed) { + function adjust(r, c) { + var container = r[c + 'Container'], + offset = r[c + 'Offset']; + if (container.nodeType == 3) { + if (!offset) { + r['set' + c.replace(/(\w)/, function (a) { + return a.toUpperCase(); + }) + 'Before'](container); + } else if (offset >= container.nodeValue.length) { + r['set' + c.replace(/(\w)/, function (a) { + return a.toUpperCase(); + }) + 'After' ](container); + } + } + } + + if (ignoreCollapsed || !this.collapsed) { + adjust(this, 'start'); + adjust(this, 'end'); + } + return this; + }, + + /** + * 在当前选区的开始位置前插入节点,新插入的节点会被该range包含 + * @method insertNode + * @param { Node } node 需要插入的节点 + * @remind 插入的节点可以是一个DocumentFragment依次插入多个节点 + * @return { UE.dom.Range } 当前range对象 + */ + insertNode:function (node) { + var first = node, length = 1; + if (node.nodeType == 11) { + first = node.firstChild; + length = node.childNodes.length; + } + this.trimBoundary(true); + var start = this.startContainer, + offset = this.startOffset; + var nextNode = start.childNodes[ offset ]; + if (nextNode) { + start.insertBefore(node, nextNode); + } else { + start.appendChild(node); + } + if (first.parentNode === this.endContainer) { + this.endOffset = this.endOffset + length; + } + return this.setStartBefore(first); + }, + + /** + * 闭合选区到当前选区的开始位置, 并且定位光标到闭合后的位置 + * @method setCursor + * @return { UE.dom.Range } 当前range对象 + * @see UE.dom.Range:collapse() + */ + + /** + * 闭合选区,可以根据参数toEnd的值控制选区是向前闭合还是向后闭合, 并且定位光标到闭合后的位置。 + * @method setCursor + * @param { Boolean } toEnd 是否向后闭合, 如果为true, 则闭合选区时, 将向结束容器方向闭合, + * 反之,则向开始容器方向闭合 + * @return { UE.dom.Range } 当前range对象 + * @see UE.dom.Range:collapse(Boolean) + */ + setCursor:function (toEnd, noFillData) { + return this.collapse(!toEnd).select(noFillData); + }, + + /** + * 创建当前range的一个书签,记录下当前range的位置,方便当dom树改变时,还能找回原来的选区位置 + * @method createBookmark + * @param { Boolean } serialize 控制返回的标记位置是对当前位置的引用还是ID,如果该值为true,则 + * 返回标记位置的ID, 反之则返回标记位置节点的引用 + * @return { Object } 返回一个书签记录键值对, 其包含的key有: start => 开始标记的ID或者引用, + * end => 结束标记的ID或引用, id => 当前标记的类型, 如果为true,则表示 + * 返回的记录的类型为ID, 反之则为引用 + */ + createBookmark:function (serialize, same) { + var endNode, + startNode = this.document.createElement('span'); + startNode.style.cssText = 'display:none;line-height:0px;'; + startNode.appendChild(this.document.createTextNode('\u200D')); + startNode.id = '_baidu_bookmark_start_' + (same ? '' : guid++); + + if (!this.collapsed) { + endNode = startNode.cloneNode(true); + endNode.id = '_baidu_bookmark_end_' + (same ? '' : guid++); + } + this.insertNode(startNode); + if (endNode) { + this.collapse().insertNode(endNode).setEndBefore(endNode); + } + this.setStartAfter(startNode); + return { + start:serialize ? startNode.id : startNode, + end:endNode ? serialize ? endNode.id : endNode : null, + id:serialize + } + }, + + /** + * 调整当前range的边界到书签位置,并删除该书签对象所标记的位置内的节点 + * @method moveToBookmark + * @param { BookMark } bookmark createBookmark所创建的标签对象 + * @return { UE.dom.Range } 当前range对象 + * @see UE.dom.Range:createBookmark(Boolean) + */ + moveToBookmark:function (bookmark) { + var start = bookmark.id ? this.document.getElementById(bookmark.start) : bookmark.start, + end = bookmark.end && bookmark.id ? this.document.getElementById(bookmark.end) : bookmark.end; + this.setStartBefore(start); + domUtils.remove(start); + if (end) { + this.setEndBefore(end); + domUtils.remove(end); + } else { + this.collapse(true); + } + return this; + }, + + /** + * 调整range的边界,使其"放大"到最近的父节点 + * @method enlarge + * @remind 会引起选区的变化 + * @return { UE.dom.Range } 当前range对象 + */ + + /** + * 调整range的边界,使其"放大"到最近的父节点,根据参数 toBlock 的取值, 可以 + * 要求扩大之后的父节点是block节点 + * @method enlarge + * @param { Boolean } toBlock 是否要求扩大之后的父节点必须是block节点 + * @return { UE.dom.Range } 当前range对象 + */ + enlarge:function (toBlock, stopFn) { + var isBody = domUtils.isBody, + pre, node, tmp = this.document.createTextNode(''); + if (toBlock) { + node = this.startContainer; + if (node.nodeType == 1) { + if (node.childNodes[this.startOffset]) { + pre = node = node.childNodes[this.startOffset] + } else { + node.appendChild(tmp); + pre = node = tmp; + } + } else { + pre = node; + } + while (1) { + if (domUtils.isBlockElm(node)) { + node = pre; + while ((pre = node.previousSibling) && !domUtils.isBlockElm(pre)) { + node = pre; + } + this.setStartBefore(node); + break; + } + pre = node; + node = node.parentNode; + } + node = this.endContainer; + if (node.nodeType == 1) { + if (pre = node.childNodes[this.endOffset]) { + node.insertBefore(tmp, pre); + } else { + node.appendChild(tmp); + } + pre = node = tmp; + } else { + pre = node; + } + while (1) { + if (domUtils.isBlockElm(node)) { + node = pre; + while ((pre = node.nextSibling) && !domUtils.isBlockElm(pre)) { + node = pre; + } + this.setEndAfter(node); + break; + } + pre = node; + node = node.parentNode; + } + if (tmp.parentNode === this.endContainer) { + this.endOffset--; + } + domUtils.remove(tmp); + } + + // 扩展边界到最大 + if (!this.collapsed) { + while (this.startOffset == 0) { + if (stopFn && stopFn(this.startContainer)) { + break; + } + if (isBody(this.startContainer)) { + break; + } + this.setStartBefore(this.startContainer); + } + while (this.endOffset == (this.endContainer.nodeType == 1 ? this.endContainer.childNodes.length : this.endContainer.nodeValue.length)) { + if (stopFn && stopFn(this.endContainer)) { + break; + } + if (isBody(this.endContainer)) { + break; + } + this.setEndAfter(this.endContainer); + } + } + return this; + }, + enlargeToBlockElm:function(ignoreEnd){ + while(!domUtils.isBlockElm(this.startContainer)){ + this.setStartBefore(this.startContainer); + } + if(!ignoreEnd){ + while(!domUtils.isBlockElm(this.endContainer)){ + this.setEndAfter(this.endContainer); + } + } + return this; + }, + /** + * 调整Range的边界,使其"缩小"到最合适的位置 + * @method adjustmentBoundary + * @return { UE.dom.Range } 当前range对象 + * @see UE.dom.Range:shrinkBoundary() + */ + adjustmentBoundary:function () { + if (!this.collapsed) { + while (!domUtils.isBody(this.startContainer) && + this.startOffset == this.startContainer[this.startContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length && + this.startContainer[this.startContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length + ) { + + this.setStartAfter(this.startContainer); + } + while (!domUtils.isBody(this.endContainer) && !this.endOffset && + this.endContainer[this.endContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length + ) { + this.setEndBefore(this.endContainer); + } + } + return this; + }, + + /** + * 给range选区中的内容添加给定的inline标签 + * @method applyInlineStyle + * @param { String } tagName 需要添加的标签名 + * @example + * ```html + *

xxxx[xxxx]x

==> range.applyInlineStyle("strong") ==>

xxxx[xxxx]x

+ * ``` + */ + + /** + * 给range选区中的内容添加给定的inline标签, 并且为标签附加上一些初始化属性。 + * @method applyInlineStyle + * @param { String } tagName 需要添加的标签名 + * @param { Object } attrs 跟随新添加的标签的属性 + * @return { UE.dom.Range } 当前选区 + * @example + * ```html + *

xxxx[xxxx]x

+ * + * ==> + * + * + * range.applyInlineStyle("strong",{"style":"font-size:12px"}) + * + * ==> + * + *

xxxx[xxxx]x

+ * ``` + */ + applyInlineStyle:function (tagName, attrs, list) { + if (this.collapsed)return this; + this.trimBoundary().enlarge(false, + function (node) { + return node.nodeType == 1 && domUtils.isBlockElm(node) + }).adjustmentBoundary(); + var bookmark = this.createBookmark(), + end = bookmark.end, + filterFn = function (node) { + return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' : !domUtils.isWhitespace(node); + }, + current = domUtils.getNextDomNode(bookmark.start, false, filterFn), + node, + pre, + range = this.cloneRange(); + while (current && (domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING)) { + if (current.nodeType == 3 || dtd[tagName][current.tagName]) { + range.setStartBefore(current); + node = current; + while (node && (node.nodeType == 3 || dtd[tagName][node.tagName]) && node !== end) { + pre = node; + node = domUtils.getNextDomNode(node, node.nodeType == 1, null, function (parent) { + return dtd[tagName][parent.tagName]; + }); + } + var frag = range.setEndAfter(pre).extractContents(), elm; + if (list && list.length > 0) { + var level, top; + top = level = list[0].cloneNode(false); + for (var i = 1, ci; ci = list[i++];) { + level.appendChild(ci.cloneNode(false)); + level = level.firstChild; + } + elm = level; + } else { + elm = range.document.createElement(tagName); + } + if (attrs) { + domUtils.setAttributes(elm, attrs); + } + elm.appendChild(frag); + range.insertNode(list ? top : elm); + //处理下滑线在a上的情况 + var aNode; + if (tagName == 'span' && attrs.style && /text\-decoration/.test(attrs.style) && (aNode = domUtils.findParentByTagName(elm, 'a', true))) { + domUtils.setAttributes(aNode, attrs); + domUtils.remove(elm, true); + elm = aNode; + } else { + domUtils.mergeSibling(elm); + domUtils.clearEmptySibling(elm); + } + //去除子节点相同的 + domUtils.mergeChild(elm, attrs); + current = domUtils.getNextDomNode(elm, false, filterFn); + domUtils.mergeToParent(elm); + if (node === end) { + break; + } + } else { + current = domUtils.getNextDomNode(current, true, filterFn); + } + } + return this.moveToBookmark(bookmark); + }, + + /** + * 移除当前选区内指定的inline标签,但保留其中的内容 + * @method removeInlineStyle + * @param { String } tagName 需要移除的标签名 + * @return { UE.dom.Range } 当前的range对象 + * @example + * ```html + * xx[xxxxyyyzz]z => range.removeInlineStyle(["em"]) => xx[xxxxyyyzz]z + * ``` + */ + + /** + * 移除当前选区内指定的一组inline标签,但保留其中的内容 + * @method removeInlineStyle + * @param { Array } tagNameArr 需要移除的标签名的数组 + * @return { UE.dom.Range } 当前的range对象 + * @see UE.dom.Range:removeInlineStyle(String) + */ + removeInlineStyle:function (tagNames) { + if (this.collapsed)return this; + tagNames = utils.isArray(tagNames) ? tagNames : [tagNames]; + this.shrinkBoundary().adjustmentBoundary(); + var start = this.startContainer, end = this.endContainer; + while (1) { + if (start.nodeType == 1) { + if (utils.indexOf(tagNames, start.tagName.toLowerCase()) > -1) { + break; + } + if (start.tagName.toLowerCase() == 'body') { + start = null; + break; + } + } + start = start.parentNode; + } + while (1) { + if (end.nodeType == 1) { + if (utils.indexOf(tagNames, end.tagName.toLowerCase()) > -1) { + break; + } + if (end.tagName.toLowerCase() == 'body') { + end = null; + break; + } + } + end = end.parentNode; + } + var bookmark = this.createBookmark(), + frag, + tmpRange; + if (start) { + tmpRange = this.cloneRange().setEndBefore(bookmark.start).setStartBefore(start); + frag = tmpRange.extractContents(); + tmpRange.insertNode(frag); + domUtils.clearEmptySibling(start, true); + start.parentNode.insertBefore(bookmark.start, start); + } + if (end) { + tmpRange = this.cloneRange().setStartAfter(bookmark.end).setEndAfter(end); + frag = tmpRange.extractContents(); + tmpRange.insertNode(frag); + domUtils.clearEmptySibling(end, false, true); + end.parentNode.insertBefore(bookmark.end, end.nextSibling); + } + var current = domUtils.getNextDomNode(bookmark.start, false, function (node) { + return node.nodeType == 1; + }), next; + while (current && current !== bookmark.end) { + next = domUtils.getNextDomNode(current, true, function (node) { + return node.nodeType == 1; + }); + if (utils.indexOf(tagNames, current.tagName.toLowerCase()) > -1) { + domUtils.remove(current, true); + } + current = next; + } + return this.moveToBookmark(bookmark); + }, + + /** + * 获取当前选中的自闭合的节点 + * @method getClosedNode + * @return { Node | NULL } 如果当前选中的是自闭合节点, 则返回该节点, 否则返回NULL + */ + getClosedNode:function () { + var node; + if (!this.collapsed) { + var range = this.cloneRange().adjustmentBoundary().shrinkBoundary(); + if (selectOneNode(range)) { + var child = range.startContainer.childNodes[range.startOffset]; + if (child && child.nodeType == 1 && (dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName])) { + node = child; + } + } + } + return node; + }, + + /** + * 在页面上高亮range所表示的选区 + * @method select + * @return { UE.dom.Range } 返回当前Range对象 + */ + //这里不区分ie9以上,trace:3824 + select:browser.ie ? function (noFillData, textRange) { + var nativeRange; + if (!this.collapsed) + this.shrinkBoundary(); + var node = this.getClosedNode(); + if (node && !textRange) { + try { + nativeRange = this.document.body.createControlRange(); + nativeRange.addElement(node); + nativeRange.select(); + } catch (e) {} + return this; + } + var bookmark = this.createBookmark(), + start = bookmark.start, + end; + nativeRange = this.document.body.createTextRange(); + nativeRange.moveToElementText(start); + nativeRange.moveStart('character', 1); + if (!this.collapsed) { + var nativeRangeEnd = this.document.body.createTextRange(); + end = bookmark.end; + nativeRangeEnd.moveToElementText(end); + nativeRange.setEndPoint('EndToEnd', nativeRangeEnd); + } else { + if (!noFillData && this.startContainer.nodeType != 3) { + //使用|x固定住光标 + var tmpText = this.document.createTextNode(fillChar), + tmp = this.document.createElement('span'); + tmp.appendChild(this.document.createTextNode(fillChar)); + start.parentNode.insertBefore(tmp, start); + start.parentNode.insertBefore(tmpText, start); + //当点b,i,u时,不能清除i上边的b + removeFillData(this.document, tmpText); + fillData = tmpText; + mergeSibling(tmp, 'previousSibling'); + mergeSibling(start, 'nextSibling'); + nativeRange.moveStart('character', -1); + nativeRange.collapse(true); + } + } + this.moveToBookmark(bookmark); + tmp && domUtils.remove(tmp); + //IE在隐藏状态下不支持range操作,catch一下 + try { + nativeRange.select(); + } catch (e) { + } + return this; + } : function (notInsertFillData) { + function checkOffset(rng){ + + function check(node,offset,dir){ + if(node.nodeType == 3 && node.nodeValue.length < offset){ + rng[dir + 'Offset'] = node.nodeValue.length + } + } + check(rng.startContainer,rng.startOffset,'start'); + check(rng.endContainer,rng.endOffset,'end'); + } + var win = domUtils.getWindow(this.document), + sel = win.getSelection(), + txtNode; + //FF下关闭自动长高时滚动条在关闭dialog时会跳 + //ff下如果不body.focus将不能定位闭合光标到编辑器内 + browser.gecko ? this.document.body.focus() : win.focus(); + if (sel) { + sel.removeAllRanges(); + // trace:870 chrome/safari后边是br对于闭合得range不能定位 所以去掉了判断 + // this.startContainer.nodeType != 3 &&! ((child = this.startContainer.childNodes[this.startOffset]) && child.nodeType == 1 && child.tagName == 'BR' + if (this.collapsed && !notInsertFillData) { +// //opear如果没有节点接着,原生的不能够定位,不能在body的第一级插入空白节点 +// if (notInsertFillData && browser.opera && !domUtils.isBody(this.startContainer) && this.startContainer.nodeType == 1) { +// var tmp = this.document.createTextNode(''); +// this.insertNode(tmp).setStart(tmp, 0).collapse(true); +// } +// + //处理光标落在文本节点的情况 + //处理以下的情况 + //|xxxx + //xxxx|xxxx + //xxxx| + var start = this.startContainer,child = start; + if(start.nodeType == 1){ + child = start.childNodes[this.startOffset]; + + } + if( !(start.nodeType == 3 && this.startOffset) && + (child ? + (!child.previousSibling || child.previousSibling.nodeType != 3) + : + (!start.lastChild || start.lastChild.nodeType != 3) + ) + ){ + txtNode = this.document.createTextNode(fillChar); + //跟着前边走 + this.insertNode(txtNode); + removeFillData(this.document, txtNode); + mergeSibling(txtNode, 'previousSibling'); + mergeSibling(txtNode, 'nextSibling'); + fillData = txtNode; + this.setStart(txtNode, browser.webkit ? 1 : 0).collapse(true); + } + } + var nativeRange = this.document.createRange(); + if(this.collapsed && browser.opera && this.startContainer.nodeType == 1){ + var child = this.startContainer.childNodes[this.startOffset]; + if(!child){ + //往前靠拢 + child = this.startContainer.lastChild; + if( child && domUtils.isBr(child)){ + this.setStartBefore(child).collapse(true); + } + }else{ + //向后靠拢 + while(child && domUtils.isBlockElm(child)){ + if(child.nodeType == 1 && child.childNodes[0]){ + child = child.childNodes[0] + }else{ + break; + } + } + child && this.setStartBefore(child).collapse(true) + } + + } + //是createAddress最后一位算的不准,现在这里进行微调 + checkOffset(this); + nativeRange.setStart(this.startContainer, this.startOffset); + nativeRange.setEnd(this.endContainer, this.endOffset); + sel.addRange(nativeRange); + } + return this; + }, + + /** + * 滚动到当前range开始的位置 + * @method scrollToView + * @param { Window } win 当前range对象所属的window对象 + * @return { UE.dom.Range } 当前Range对象 + */ + + /** + * 滚动到距离当前range开始位置 offset 的位置处 + * @method scrollToView + * @param { Window } win 当前range对象所属的window对象 + * @param { Number } offset 距离range开始位置处的偏移量, 如果为正数, 则向下偏移, 反之, 则向上偏移 + * @return { UE.dom.Range } 当前Range对象 + */ + scrollToView:function (win, offset) { + win = win ? window : domUtils.getWindow(this.document); + var me = this, + span = me.document.createElement('span'); + //trace:717 + span.innerHTML = ' '; + me.cloneRange().insertNode(span); + domUtils.scrollToView(span, win, offset); + domUtils.remove(span); + return me; + }, + + /** + * 判断当前选区内容是否占位符 + * @private + * @method inFillChar + * @return { Boolean } 如果是占位符返回true,否则返回false + */ + inFillChar : function(){ + var start = this.startContainer; + if(this.collapsed && start.nodeType == 3 + && start.nodeValue.replace(new RegExp('^' + domUtils.fillChar),'').length + 1 == start.nodeValue.length + ){ + return true; + } + return false; + }, + + /** + * 保存 + * @method createAddress + * @private + * @return { Boolean } 返回开始和结束的位置 + * @example + * ```html + * + *

+ * aaaa + * + * + * bbbb + * + * + *

+ * + * + * + * ``` + */ + createAddress : function(ignoreEnd,ignoreTxt){ + var addr = {},me = this; + + function getAddress(isStart){ + var node = isStart ? me.startContainer : me.endContainer; + var parents = domUtils.findParents(node,true,function(node){return !domUtils.isBody(node)}), + addrs = []; + for(var i = 0,ci;ci = parents[i++];){ + addrs.push(domUtils.getNodeIndex(ci,ignoreTxt)); + } + var firstIndex = 0; + + if(ignoreTxt){ + if(node.nodeType == 3){ + var tmpNode = node.previousSibling; + while(tmpNode && tmpNode.nodeType == 3){ + firstIndex += tmpNode.nodeValue.replace(fillCharReg,'').length; + tmpNode = tmpNode.previousSibling; + } + firstIndex += (isStart ? me.startOffset : me.endOffset)// - (fillCharReg.test(node.nodeValue) ? 1 : 0 ) + }else{ + node = node.childNodes[ isStart ? me.startOffset : me.endOffset]; + if(node){ + firstIndex = domUtils.getNodeIndex(node,ignoreTxt); + }else{ + node = isStart ? me.startContainer : me.endContainer; + var first = node.firstChild; + while(first){ + if(domUtils.isFillChar(first)){ + first = first.nextSibling; + continue; + } + firstIndex++; + if(first.nodeType == 3){ + while( first && first.nodeType == 3){ + first = first.nextSibling; + } + }else{ + first = first.nextSibling; + } + } + } + } + + }else{ + firstIndex = isStart ? domUtils.isFillChar(node) ? 0 : me.startOffset : me.endOffset + } + if(firstIndex < 0){ + firstIndex = 0; + } + addrs.push(firstIndex); + return addrs; + } + addr.startAddress = getAddress(true); + if(!ignoreEnd){ + addr.endAddress = me.collapsed ? [].concat(addr.startAddress) : getAddress(); + } + return addr; + }, + + /** + * 保存 + * @method createAddress + * @private + * @return { Boolean } 返回开始和结束的位置 + * @example + * ```html + * + *

+ * aaaa + * + * + * bbbb + * + * + *

+ * + * + * + * ``` + */ + moveToAddress : function(addr,ignoreEnd){ + var me = this; + function getNode(address,isStart){ + var tmpNode = me.document.body, + parentNode,offset; + for(var i= 0,ci,l=address.length;i + * + * + * + * + * + * + * + * + * ``` + */ + + /** + * 遍历range内的节点。 + * 每当遍历一个节点时, 都会执行参数项 doFn 指定的函数, 该函数的接受当前遍历的节点 + * 作为其参数。 + * 可以通过参数项 filterFn 来指定一个过滤器, 只有符合该过滤器过滤规则的节点才会触 + * 发doFn函数的执行 + * @method traversal + * @param { Function } doFn 对每个遍历的节点要执行的方法, 该方法接受当前遍历的节点作为其参数 + * @param { Function } filterFn 过滤器, 该函数接受当前遍历的节点作为参数, 如果该节点满足过滤 + * 规则, 请返回true, 该节点会触发doFn, 否则, 请返回false, 则该节点不 + * 会触发doFn。 + * @return { UE.dom.Range } 当前range对象 + * @see UE.dom.Range:traversal(Function) + * @example + * ```html + * + * + * + * + * + * + * + * + * + * + * ``` + */ + traversal:function(doFn,filterFn){ + if (this.collapsed) + return this; + var bookmark = this.createBookmark(), + end = bookmark.end, + current = domUtils.getNextDomNode(bookmark.start, false, filterFn); + while (current && current !== end && (domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING)) { + var tmpNode = domUtils.getNextDomNode(current,false,filterFn); + doFn(current); + current = tmpNode; + } + return this.moveToBookmark(bookmark); + } + }; +})(); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/Selection.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/Selection.js new file mode 100644 index 000000000..7c7db300b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/Selection.js @@ -0,0 +1,389 @@ +/** + * 选集 + * @file + * @module UE.dom + * @class Selection + * @since 1.2.6.1 + */ + +/** + * 选区集合 + * @unfile + * @module UE.dom + * @class Selection + */ +(function () { + + function getBoundaryInformation( range, start ) { + var getIndex = domUtils.getNodeIndex; + range = range.duplicate(); + range.collapse( start ); + var parent = range.parentElement(); + //如果节点里没有子节点,直接退出 + if ( !parent.hasChildNodes() ) { + return {container:parent, offset:0}; + } + var siblings = parent.children, + child, + testRange = range.duplicate(), + startIndex = 0, endIndex = siblings.length - 1, index = -1, + distance; + while ( startIndex <= endIndex ) { + index = Math.floor( (startIndex + endIndex) / 2 ); + child = siblings[index]; + testRange.moveToElementText( child ); + var position = testRange.compareEndPoints( 'StartToStart', range ); + if ( position > 0 ) { + endIndex = index - 1; + } else if ( position < 0 ) { + startIndex = index + 1; + } else { + //trace:1043 + return {container:parent, offset:getIndex( child )}; + } + } + if ( index == -1 ) { + testRange.moveToElementText( parent ); + testRange.setEndPoint( 'StartToStart', range ); + distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length; + siblings = parent.childNodes; + if ( !distance ) { + child = siblings[siblings.length - 1]; + return {container:child, offset:child.nodeValue.length}; + } + + var i = siblings.length; + while ( distance > 0 ){ + distance -= siblings[ --i ].nodeValue.length; + } + return {container:siblings[i], offset:-distance}; + } + testRange.collapse( position > 0 ); + testRange.setEndPoint( position > 0 ? 'StartToStart' : 'EndToStart', range ); + distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length; + if ( !distance ) { + return dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName] ? + {container:parent, offset:getIndex( child ) + (position > 0 ? 0 : 1)} : + {container:child, offset:position > 0 ? 0 : child.childNodes.length} + } + while ( distance > 0 ) { + try { + var pre = child; + child = child[position > 0 ? 'previousSibling' : 'nextSibling']; + distance -= child.nodeValue.length; + } catch ( e ) { + return {container:parent, offset:getIndex( pre )}; + } + } + return {container:child, offset:position > 0 ? -distance : child.nodeValue.length + distance} + } + + /** + * 将ieRange转换为Range对象 + * @param {Range} ieRange ieRange对象 + * @param {Range} range Range对象 + * @return {Range} range 返回转换后的Range对象 + */ + function transformIERangeToRange( ieRange, range ) { + if ( ieRange.item ) { + range.selectNode( ieRange.item( 0 ) ); + } else { + var bi = getBoundaryInformation( ieRange, true ); + range.setStart( bi.container, bi.offset ); + if ( ieRange.compareEndPoints( 'StartToEnd', ieRange ) != 0 ) { + bi = getBoundaryInformation( ieRange, false ); + range.setEnd( bi.container, bi.offset ); + } + } + return range; + } + + /** + * 获得ieRange + * @param {Selection} sel Selection对象 + * @return {ieRange} 得到ieRange + */ + function _getIERange( sel ) { + var ieRange; + //ie下有可能报错 + try { + ieRange = sel.getNative().createRange(); + } catch ( e ) { + return null; + } + var el = ieRange.item ? ieRange.item( 0 ) : ieRange.parentElement(); + if ( ( el.ownerDocument || el ) === sel.document ) { + return ieRange; + } + return null; + } + + var Selection = dom.Selection = function ( doc ) { + var me = this, iframe; + me.document = doc; + if ( browser.ie9below ) { + iframe = domUtils.getWindow( doc ).frameElement; + domUtils.on( iframe, 'beforedeactivate', function () { + me._bakIERange = me.getIERange(); + } ); + domUtils.on( iframe, 'activate', function () { + try { + if ( !_getIERange( me ) && me._bakIERange ) { + me._bakIERange.select(); + } + } catch ( ex ) { + } + me._bakIERange = null; + } ); + } + iframe = doc = null; + }; + + Selection.prototype = { + + rangeInBody : function(rng,txtRange){ + var node = browser.ie9below || txtRange ? rng.item ? rng.item() : rng.parentElement() : rng.startContainer; + + return node === this.document.body || domUtils.inDoc(node,this.document); + }, + + /** + * 获取原生seleciton对象 + * @method getNative + * @return { Object } 获得selection对象 + * @example + * ```javascript + * editor.selection.getNative(); + * ``` + */ + getNative:function () { + var doc = this.document; + try { + return !doc ? null : browser.ie9below ? doc.selection : domUtils.getWindow( doc ).getSelection(); + } catch ( e ) { + return null; + } + }, + + /** + * 获得ieRange + * @method getIERange + * @return { Object } 返回ie原生的Range + * @example + * ```javascript + * editor.selection.getIERange(); + * ``` + */ + getIERange:function () { + var ieRange = _getIERange( this ); + if ( !ieRange ) { + if ( this._bakIERange ) { + return this._bakIERange; + } + } + return ieRange; + }, + + /** + * 缓存当前选区的range和选区的开始节点 + * @method cache + */ + cache:function () { + this.clear(); + this._cachedRange = this.getRange(); + this._cachedStartElement = this.getStart(); + this._cachedStartElementPath = this.getStartElementPath(); + }, + + /** + * 获取选区开始位置的父节点到body + * @method getStartElementPath + * @return { Array } 返回父节点集合 + * @example + * ```javascript + * editor.selection.getStartElementPath(); + * ``` + */ + getStartElementPath:function () { + if ( this._cachedStartElementPath ) { + return this._cachedStartElementPath; + } + var start = this.getStart(); + if ( start ) { + return domUtils.findParents( start, true, null, true ) + } + return []; + }, + + /** + * 清空缓存 + * @method clear + */ + clear:function () { + this._cachedStartElementPath = this._cachedRange = this._cachedStartElement = null; + }, + + /** + * 编辑器是否得到了选区 + * @method isFocus + */ + isFocus:function () { + try { + if(browser.ie9below){ + + var nativeRange = _getIERange(this); + return !!(nativeRange && this.rangeInBody(nativeRange)); + }else{ + return !!this.getNative().rangeCount; + } + } catch ( e ) { + return false; + } + + }, + + /** + * 获取选区对应的Range + * @method getRange + * @return { Object } 得到Range对象 + * @example + * ```javascript + * editor.selection.getRange(); + * ``` + */ + getRange:function () { + var me = this; + function optimze( range ) { + var child = me.document.body.firstChild, + collapsed = range.collapsed; + while ( child && child.firstChild ) { + range.setStart( child, 0 ); + child = child.firstChild; + } + if ( !range.startContainer ) { + range.setStart( me.document.body, 0 ) + } + if ( collapsed ) { + range.collapse( true ); + } + } + + if ( me._cachedRange != null ) { + return this._cachedRange; + } + var range = new baidu.editor.dom.Range( me.document ); + + if ( browser.ie9below ) { + var nativeRange = me.getIERange(); + if ( nativeRange ) { + //备份的_bakIERange可能已经实效了,dom树发生了变化比如从源码模式切回来,所以try一下,实效就放到body开始位置 + try{ + transformIERangeToRange( nativeRange, range ); + }catch(e){ + optimze( range ); + } + + } else { + optimze( range ); + } + } else { + var sel = me.getNative(); + if ( sel && sel.rangeCount ) { + var firstRange = sel.getRangeAt( 0 ); + var lastRange = sel.getRangeAt( sel.rangeCount - 1 ); + range.setStart( firstRange.startContainer, firstRange.startOffset ).setEnd( lastRange.endContainer, lastRange.endOffset ); + if ( range.collapsed && domUtils.isBody( range.startContainer ) && !range.startOffset ) { + optimze( range ); + } + } else { + //trace:1734 有可能已经不在dom树上了,标识的节点 + if ( this._bakRange && domUtils.inDoc( this._bakRange.startContainer, this.document ) ){ + return this._bakRange; + } + optimze( range ); + } + } + return this._bakRange = range; + }, + + /** + * 获取开始元素,用于状态反射 + * @method getStart + * @return { Element } 获得开始元素 + * @example + * ```javascript + * editor.selection.getStart(); + * ``` + */ + getStart:function () { + if ( this._cachedStartElement ) { + return this._cachedStartElement; + } + var range = browser.ie9below ? this.getIERange() : this.getRange(), + tmpRange, + start, tmp, parent; + if ( browser.ie9below ) { + if ( !range ) { + //todo 给第一个值可能会有问题 + return this.document.body.firstChild; + } + //control元素 + if ( range.item ){ + return range.item( 0 ); + } + tmpRange = range.duplicate(); + //修正ie下x[xx] 闭合后 x|xx + tmpRange.text.length > 0 && tmpRange.moveStart( 'character', 1 ); + tmpRange.collapse( 1 ); + start = tmpRange.parentElement(); + parent = tmp = range.parentElement(); + while ( tmp = tmp.parentNode ) { + if ( tmp == start ) { + start = parent; + break; + } + } + } else { + range.shrinkBoundary(); + start = range.startContainer; + if ( start.nodeType == 1 && start.hasChildNodes() ){ + start = start.childNodes[Math.min( start.childNodes.length - 1, range.startOffset )]; + } + if ( start.nodeType == 3 ){ + return start.parentNode; + } + } + return start; + }, + + /** + * 得到选区中的文本 + * @method getText + * @return { String } 选区中包含的文本 + * @example + * ```javascript + * editor.selection.getText(); + * ``` + */ + getText:function () { + var nativeSel, nativeRange; + if ( this.isFocus() && (nativeSel = this.getNative()) ) { + nativeRange = browser.ie9below ? nativeSel.createRange() : nativeSel.getRangeAt( 0 ); + return browser.ie9below ? nativeRange.text : nativeRange.toString(); + } + return ''; + }, + + /** + * 清除选区 + * @method clearRange + * @example + * ```javascript + * editor.selection.clearRange(); + * ``` + */ + clearRange : function(){ + this.getNative()[browser.ie9below ? 'empty' : 'removeAllRanges'](); + } + }; +})(); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/ajax.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/ajax.js new file mode 100644 index 000000000..6a1bad9d9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/ajax.js @@ -0,0 +1,262 @@ +/** + * @file + * @module UE.ajax + * @since 1.2.6.1 + */ + +/** + * 提供对ajax请求的支持 + * @module UE.ajax + */ +UE.ajax = function() { + + //创建一个ajaxRequest对象 + var fnStr = 'XMLHttpRequest()'; + try { + new ActiveXObject("Msxml2.XMLHTTP"); + fnStr = 'ActiveXObject(\'Msxml2.XMLHTTP\')'; + } catch (e) { + try { + new ActiveXObject("Microsoft.XMLHTTP"); + fnStr = 'ActiveXObject(\'Microsoft.XMLHTTP\')' + } catch (e) { + } + } + var creatAjaxRequest = new Function('return new ' + fnStr); + + + /** + * 将json参数转化成适合ajax提交的参数列表 + * @param json + */ + function json2str(json) { + var strArr = []; + for (var i in json) { + //忽略默认的几个参数 + if(i=="method" || i=="timeout" || i=="async" || i=="dataType" || i=="callback") continue; + //忽略控制 + if(json[i] == undefined || json[i] == null) continue; + //传递过来的对象和函数不在提交之列 + if (!((typeof json[i]).toLowerCase() == "function" || (typeof json[i]).toLowerCase() == "object")) { + strArr.push( encodeURIComponent(i) + "="+encodeURIComponent(json[i]) ); + } else if (utils.isArray(json[i])) { + //支持传数组内容 + for(var j = 0; j < json[i].length; j++) { + strArr.push( encodeURIComponent(i) + "[]="+encodeURIComponent(json[i][j]) ); + } + } + } + return strArr.join("&"); + } + + function doAjax(url, ajaxOptions) { + var xhr = creatAjaxRequest(), + //是否超时 + timeIsOut = false, + //默认参数 + defaultAjaxOptions = { + method:"POST", + timeout:5000, + async:true, + data:{},//需要传递对象的话只能覆盖 + onsuccess:function() { + }, + onerror:function() { + } + }; + + if (typeof url === "object") { + ajaxOptions = url; + url = ajaxOptions.url; + } + if (!xhr || !url) return; + var ajaxOpts = ajaxOptions ? utils.extend(defaultAjaxOptions,ajaxOptions) : defaultAjaxOptions; + + var submitStr = json2str(ajaxOpts); // { name:"Jim",city:"Beijing" } --> "name=Jim&city=Beijing" + //如果用户直接通过data参数传递json对象过来,则也要将此json对象转化为字符串 + if (!utils.isEmptyObject(ajaxOpts.data)){ + submitStr += (submitStr? "&":"") + json2str(ajaxOpts.data); + } + //超时检测 + var timerID = setTimeout(function() { + if (xhr.readyState != 4) { + timeIsOut = true; + xhr.abort(); + clearTimeout(timerID); + } + }, ajaxOpts.timeout); + + var method = ajaxOpts.method.toUpperCase(); + var str = url + (url.indexOf("?")==-1?"?":"&") + (method=="POST"?"":submitStr+ "&noCache=" + +new Date); + xhr.open(method, str, ajaxOpts.async); + xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + if (!timeIsOut && xhr.status == 200) { + ajaxOpts.onsuccess(xhr); + } else { + ajaxOpts.onerror(xhr); + } + } + }; + if (method == "POST") { + xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + xhr.send(submitStr); + } else { + xhr.send(null); + } + } + + function doJsonp(url, opts) { + + var successhandler = opts.onsuccess || function(){}, + scr = document.createElement('SCRIPT'), + options = opts || {}, + charset = options['charset'], + callbackField = options['jsonp'] || 'callback', + callbackFnName, + timeOut = options['timeOut'] || 0, + timer, + reg = new RegExp('(\\?|&)' + callbackField + '=([^&]*)'), + matches; + + if (utils.isFunction(successhandler)) { + callbackFnName = 'bd__editor__' + Math.floor(Math.random() * 2147483648).toString(36); + window[callbackFnName] = getCallBack(0); + } else if(utils.isString(successhandler)){ + callbackFnName = successhandler; + } else { + if (matches = reg.exec(url)) { + callbackFnName = matches[2]; + } + } + + url = url.replace(reg, '\x241' + callbackField + '=' + callbackFnName); + + if (url.search(reg) < 0) { + url += (url.indexOf('?') < 0 ? '?' : '&') + callbackField + '=' + callbackFnName; + } + + var queryStr = json2str(opts); // { name:"Jim",city:"Beijing" } --> "name=Jim&city=Beijing" + //如果用户直接通过data参数传递json对象过来,则也要将此json对象转化为字符串 + if (!utils.isEmptyObject(opts.data)){ + queryStr += (queryStr? "&":"") + json2str(opts.data); + } + if (queryStr) { + url = url.replace(/\?/, '?' + queryStr + '&'); + } + + scr.onerror = getCallBack(1); + if( timeOut ){ + timer = setTimeout(getCallBack(1), timeOut); + } + createScriptTag(scr, url, charset); + + function createScriptTag(scr, url, charset) { + scr.setAttribute('type', 'text/javascript'); + scr.setAttribute('defer', 'defer'); + charset && scr.setAttribute('charset', charset); + scr.setAttribute('src', url); + document.getElementsByTagName('head')[0].appendChild(scr); + } + + function getCallBack(onTimeOut){ + return function(){ + try { + if(onTimeOut){ + options.onerror && options.onerror(); + }else{ + try{ + clearTimeout(timer); + successhandler.apply(window, arguments); + } catch (e){} + } + } catch (exception) { + options.onerror && options.onerror.call(window, exception); + } finally { + options.oncomplete && options.oncomplete.apply(window, arguments); + scr.parentNode && scr.parentNode.removeChild(scr); + window[callbackFnName] = null; + try { + delete window[callbackFnName]; + }catch(e){} + } + } + } + } + + return { + /** + * 根据给定的参数项,向指定的url发起一个ajax请求。 ajax请求完成后,会根据请求结果调用相应回调: 如果请求 + * 成功, 则调用onsuccess回调, 失败则调用 onerror 回调 + * @method request + * @param { URLString } url ajax请求的url地址 + * @param { Object } ajaxOptions ajax请求选项的键值对,支持的选项如下: + * @example + * ```javascript + * //向sayhello.php发起一个异步的Ajax GET请求, 请求超时时间为10s, 请求完成后执行相应的回调。 + * UE.ajax.requeset( 'sayhello.php', { + * + * //请求方法。可选值: 'GET', 'POST',默认值是'POST' + * method: 'GET', + * + * //超时时间。 默认为5000, 单位是ms + * timeout: 10000, + * + * //是否是异步请求。 true为异步请求, false为同步请求 + * async: true, + * + * //请求携带的数据。如果请求为GET请求, data会经过stringify后附加到请求url之后。 + * data: { + * name: 'ueditor' + * }, + * + * //请求成功后的回调, 该回调接受当前的XMLHttpRequest对象作为参数。 + * onsuccess: function ( xhr ) { + * console.log( xhr.responseText ); + * }, + * + * //请求失败或者超时后的回调。 + * onerror: function ( xhr ) { + * alert( 'Ajax请求失败' ); + * } + * + * } ); + * ``` + */ + + /** + * 根据给定的参数项发起一个ajax请求, 参数项里必须包含一个url地址。 ajax请求完成后,会根据请求结果调用相应回调: 如果请求 + * 成功, 则调用onsuccess回调, 失败则调用 onerror 回调。 + * @method request + * @warning 如果在参数项里未提供一个key为“url”的地址值,则该请求将直接退出。 + * @param { Object } ajaxOptions ajax请求选项的键值对,支持的选项如下: + * @example + * ```javascript + * + * //向sayhello.php发起一个异步的Ajax POST请求, 请求超时时间为5s, 请求完成后不执行任何回调。 + * UE.ajax.requeset( 'sayhello.php', { + * + * //请求的地址, 该项是必须的。 + * url: 'sayhello.php' + * + * } ); + * ``` + */ + request:function(url, opts) { + if (opts && opts.dataType == 'jsonp') { + doJsonp(url, opts); + } else { + doAjax(url, opts); + } + }, + getJSONP:function(url, data, fn) { + var opts = { + 'data': data, + 'oncomplete': fn + }; + doJsonp(url, opts); + } + }; + + +}(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/browser.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/browser.js new file mode 100644 index 000000000..b82b77fda --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/browser.js @@ -0,0 +1,258 @@ +/** + * 浏览器判断模块 + * @file + * @module UE.browser + * @since 1.2.6.1 + */ + +/** + * 提供浏览器检测的模块 + * @unfile + * @module UE.browser + */ +var browser = UE.browser = function(){ + var agent = navigator.userAgent.toLowerCase(), + opera = window.opera, + browser = { + /** + * @property {boolean} ie 检测当前浏览器是否为IE + * @example + * ```javascript + * if ( UE.browser.ie ) { + * console.log( '当前浏览器是IE' ); + * } + * ``` + */ + ie : /(msie\s|trident.*rv:)([\w.]+)/.test(agent), + + /** + * @property {boolean} opera 检测当前浏览器是否为Opera + * @example + * ```javascript + * if ( UE.browser.opera ) { + * console.log( '当前浏览器是Opera' ); + * } + * ``` + */ + opera : ( !!opera && opera.version ), + + /** + * @property {boolean} webkit 检测当前浏览器是否是webkit内核的浏览器 + * @example + * ```javascript + * if ( UE.browser.webkit ) { + * console.log( '当前浏览器是webkit内核浏览器' ); + * } + * ``` + */ + webkit : ( agent.indexOf( ' applewebkit/' ) > -1 ), + + /** + * @property {boolean} mac 检测当前浏览器是否是运行在mac平台下 + * @example + * ```javascript + * if ( UE.browser.mac ) { + * console.log( '当前浏览器运行在mac平台下' ); + * } + * ``` + */ + mac : ( agent.indexOf( 'macintosh' ) > -1 ), + + /** + * @property {boolean} quirks 检测当前浏览器是否处于“怪异模式”下 + * @example + * ```javascript + * if ( UE.browser.quirks ) { + * console.log( '当前浏览器运行处于“怪异模式”' ); + * } + * ``` + */ + quirks : ( document.compatMode == 'BackCompat' ) + }; + + /** + * @property {boolean} gecko 检测当前浏览器内核是否是gecko内核 + * @example + * ```javascript + * if ( UE.browser.gecko ) { + * console.log( '当前浏览器内核是gecko内核' ); + * } + * ``` + */ + browser.gecko =( navigator.product == 'Gecko' && !browser.webkit && !browser.opera && !browser.ie); + + var version = 0; + + // Internet Explorer 6.0+ + if ( browser.ie ){ + + var v1 = agent.match(/(?:msie\s([\w.]+))/); + var v2 = agent.match(/(?:trident.*rv:([\w.]+))/); + if(v1 && v2 && v1[1] && v2[1]){ + version = Math.max(v1[1]*1,v2[1]*1); + }else if(v1 && v1[1]){ + version = v1[1]*1; + }else if(v2 && v2[1]){ + version = v2[1]*1; + }else{ + version = 0; + } + + browser.ie11Compat = document.documentMode == 11; + /** + * @property { boolean } ie9Compat 检测浏览器模式是否为 IE9 兼容模式 + * @warning 如果浏览器不是IE, 则该值为undefined + * @example + * ```javascript + * if ( UE.browser.ie9Compat ) { + * console.log( '当前浏览器运行在IE9兼容模式下' ); + * } + * ``` + */ + browser.ie9Compat = document.documentMode == 9; + + /** + * @property { boolean } ie8 检测浏览器是否是IE8浏览器 + * @warning 如果浏览器不是IE, 则该值为undefined + * @example + * ```javascript + * if ( UE.browser.ie8 ) { + * console.log( '当前浏览器是IE8浏览器' ); + * } + * ``` + */ + browser.ie8 = !!document.documentMode; + + /** + * @property { boolean } ie8Compat 检测浏览器模式是否为 IE8 兼容模式 + * @warning 如果浏览器不是IE, 则该值为undefined + * @example + * ```javascript + * if ( UE.browser.ie8Compat ) { + * console.log( '当前浏览器运行在IE8兼容模式下' ); + * } + * ``` + */ + browser.ie8Compat = document.documentMode == 8; + + /** + * @property { boolean } ie7Compat 检测浏览器模式是否为 IE7 兼容模式 + * @warning 如果浏览器不是IE, 则该值为undefined + * @example + * ```javascript + * if ( UE.browser.ie7Compat ) { + * console.log( '当前浏览器运行在IE7兼容模式下' ); + * } + * ``` + */ + browser.ie7Compat = ( ( version == 7 && !document.documentMode ) + || document.documentMode == 7 ); + + /** + * @property { boolean } ie6Compat 检测浏览器模式是否为 IE6 模式 或者怪异模式 + * @warning 如果浏览器不是IE, 则该值为undefined + * @example + * ```javascript + * if ( UE.browser.ie6Compat ) { + * console.log( '当前浏览器运行在IE6模式或者怪异模式下' ); + * } + * ``` + */ + browser.ie6Compat = ( version < 7 || browser.quirks ); + + browser.ie9above = version > 8; + + browser.ie9below = version < 9; + + browser.ie11above = version > 10; + + browser.ie11below = version < 11; + + } + + // Gecko. + if ( browser.gecko ){ + var geckoRelease = agent.match( /rv:([\d\.]+)/ ); + if ( geckoRelease ) + { + geckoRelease = geckoRelease[1].split( '.' ); + version = geckoRelease[0] * 10000 + ( geckoRelease[1] || 0 ) * 100 + ( geckoRelease[2] || 0 ) * 1; + } + } + + /** + * @property { Number } chrome 检测当前浏览器是否为Chrome, 如果是,则返回Chrome的大版本号 + * @warning 如果浏览器不是chrome, 则该值为undefined + * @example + * ```javascript + * if ( UE.browser.chrome ) { + * console.log( '当前浏览器是Chrome' ); + * } + * ``` + */ + if (/chrome\/(\d+\.\d)/i.test(agent)) { + browser.chrome = + RegExp['\x241']; + } + + /** + * @property { Number } safari 检测当前浏览器是否为Safari, 如果是,则返回Safari的大版本号 + * @warning 如果浏览器不是safari, 则该值为undefined + * @example + * ```javascript + * if ( UE.browser.safari ) { + * console.log( '当前浏览器是Safari' ); + * } + * ``` + */ + if(/(\d+\.\d)?(?:\.\d)?\s+safari\/?(\d+\.\d+)?/i.test(agent) && !/chrome/i.test(agent)){ + browser.safari = + (RegExp['\x241'] || RegExp['\x242']); + } + + + // Opera 9.50+ + if ( browser.opera ) + version = parseFloat( opera.version() ); + + // WebKit 522+ (Safari 3+) + if ( browser.webkit ) + version = parseFloat( agent.match( / applewebkit\/(\d+)/ )[1] ); + + /** + * @property { Number } version 检测当前浏览器版本号 + * @remind + *
    + *
  • IE系列返回值为5,6,7,8,9,10等
  • + *
  • gecko系列会返回10900,158900等
  • + *
  • webkit系列会返回其build号 (如 522等)
  • + *
+ * @example + * ```javascript + * console.log( '当前浏览器版本号是: ' + UE.browser.version ); + * ``` + */ + browser.version = version; + + /** + * @property { boolean } isCompatible 检测当前浏览器是否能够与UEditor良好兼容 + * @example + * ```javascript + * if ( UE.browser.isCompatible ) { + * console.log( '浏览器与UEditor能够良好兼容' ); + * } + * ``` + */ + browser.isCompatible = + !browser.mobile && ( + ( browser.ie && version >= 6 ) || + ( browser.gecko && version >= 10801 ) || + ( browser.opera && version >= 9.5 ) || + ( browser.air && version >= 1 ) || + ( browser.webkit && version >= 522 ) || + false ); + return browser; +}(); +//快捷方式 +var ie = browser.ie, + webkit = browser.webkit, + gecko = browser.gecko, + opera = browser.opera; \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/domUtils.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/domUtils.js new file mode 100644 index 000000000..fcfb50a03 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/domUtils.js @@ -0,0 +1,2413 @@ +/** + * Dom操作工具包 + * @file + * @module UE.dom.domUtils + * @since 1.2.6.1 + */ + +/** + * Dom操作工具包 + * @unfile + * @module UE.dom.domUtils + */ +function getDomNode(node, start, ltr, startFromChild, fn, guard) { + var tmpNode = startFromChild && node[start], + parent; + !tmpNode && (tmpNode = node[ltr]); + while (!tmpNode && (parent = (parent || node).parentNode)) { + if (parent.tagName == 'BODY' || guard && !guard(parent)) { + return null; + } + tmpNode = parent[ltr]; + } + if (tmpNode && fn && !fn(tmpNode)) { + return getDomNode(tmpNode, start, ltr, false, fn); + } + return tmpNode; +} +var attrFix = ie && browser.version < 9 ? { + tabindex:"tabIndex", + readonly:"readOnly", + "for":"htmlFor", + "class":"className", + maxlength:"maxLength", + cellspacing:"cellSpacing", + cellpadding:"cellPadding", + rowspan:"rowSpan", + colspan:"colSpan", + usemap:"useMap", + frameborder:"frameBorder" + } : { + tabindex:"tabIndex", + readonly:"readOnly" + }, + styleBlock = utils.listToMap([ + '-webkit-box', '-moz-box', 'block' , + 'list-item' , 'table' , 'table-row-group' , + 'table-header-group', 'table-footer-group' , + 'table-row' , 'table-column-group' , 'table-column' , + 'table-cell' , 'table-caption' + ]); +var domUtils = dom.domUtils = { + //节点常量 + NODE_ELEMENT:1, + NODE_DOCUMENT:9, + NODE_TEXT:3, + NODE_COMMENT:8, + NODE_DOCUMENT_FRAGMENT:11, + + //位置关系 + POSITION_IDENTICAL:0, + POSITION_DISCONNECTED:1, + POSITION_FOLLOWING:2, + POSITION_PRECEDING:4, + POSITION_IS_CONTAINED:8, + POSITION_CONTAINS:16, + //ie6使用其他的会有一段空白出现 + fillChar:ie && browser.version == '6' ? '\ufeff' : '\u200B', + //-------------------------Node部分-------------------------------- + keys:{ + /*Backspace*/ 8:1, /*Delete*/ 46:1, + /*Shift*/ 16:1, /*Ctrl*/ 17:1, /*Alt*/ 18:1, + 37:1, 38:1, 39:1, 40:1, + 13:1 /*enter*/ + }, + /** + * 获取节点A相对于节点B的位置关系 + * @method getPosition + * @param { Node } nodeA 需要查询位置关系的节点A + * @param { Node } nodeB 需要查询位置关系的节点B + * @return { Number } 节点A与节点B的关系 + * @example + * ```javascript + * //output: 20 + * var position = UE.dom.domUtils.getPosition( document.documentElement, document.body ); + * + * switch ( position ) { + * + * //0 + * case UE.dom.domUtils.POSITION_IDENTICAL: + * console.log('元素相同'); + * break; + * //1 + * case UE.dom.domUtils.POSITION_DISCONNECTED: + * console.log('两个节点在不同的文档中'); + * break; + * //2 + * case UE.dom.domUtils.POSITION_FOLLOWING: + * console.log('节点A在节点B之后'); + * break; + * //4 + * case UE.dom.domUtils.POSITION_PRECEDING; + * console.log('节点A在节点B之前'); + * break; + * //8 + * case UE.dom.domUtils.POSITION_IS_CONTAINED: + * console.log('节点A被节点B包含'); + * break; + * case 10: + * console.log('节点A被节点B包含且节点A在节点B之后'); + * break; + * //16 + * case UE.dom.domUtils.POSITION_CONTAINS: + * console.log('节点A包含节点B'); + * break; + * case 20: + * console.log('节点A包含节点B且节点A在节点B之前'); + * break; + * + * } + * ``` + */ + getPosition:function (nodeA, nodeB) { + // 如果两个节点是同一个节点 + if (nodeA === nodeB) { + // domUtils.POSITION_IDENTICAL + return 0; + } + var node, + parentsA = [nodeA], + parentsB = [nodeB]; + node = nodeA; + while (node = node.parentNode) { + // 如果nodeB是nodeA的祖先节点 + if (node === nodeB) { + // domUtils.POSITION_IS_CONTAINED + domUtils.POSITION_FOLLOWING + return 10; + } + parentsA.push(node); + } + node = nodeB; + while (node = node.parentNode) { + // 如果nodeA是nodeB的祖先节点 + if (node === nodeA) { + // domUtils.POSITION_CONTAINS + domUtils.POSITION_PRECEDING + return 20; + } + parentsB.push(node); + } + parentsA.reverse(); + parentsB.reverse(); + if (parentsA[0] !== parentsB[0]) { + // domUtils.POSITION_DISCONNECTED + return 1; + } + var i = -1; + while (i++, parentsA[i] === parentsB[i]) { + } + nodeA = parentsA[i]; + nodeB = parentsB[i]; + while (nodeA = nodeA.nextSibling) { + if (nodeA === nodeB) { + // domUtils.POSITION_PRECEDING + return 4 + } + } + // domUtils.POSITION_FOLLOWING + return 2; + }, + + /** + * 检测节点node在父节点中的索引位置 + * @method getNodeIndex + * @param { Node } node 需要检测的节点对象 + * @return { Number } 该节点在父节点中的位置 + * @see UE.dom.domUtils.getNodeIndex(Node,Boolean) + */ + + /** + * 检测节点node在父节点中的索引位置, 根据给定的mergeTextNode参数决定是否要合并多个连续的文本节点为一个节点 + * @method getNodeIndex + * @param { Node } node 需要检测的节点对象 + * @param { Boolean } mergeTextNode 是否合并多个连续的文本节点为一个节点 + * @return { Number } 该节点在父节点中的位置 + * @example + * ```javascript + * + * var node = document.createElement("div"); + * + * node.appendChild( document.createTextNode( "hello" ) ); + * node.appendChild( document.createTextNode( "world" ) ); + * node.appendChild( node = document.createElement( "div" ) ); + * + * //output: 2 + * console.log( UE.dom.domUtils.getNodeIndex( node ) ); + * + * //output: 1 + * console.log( UE.dom.domUtils.getNodeIndex( node, true ) ); + * + * ``` + */ + getNodeIndex:function (node, ignoreTextNode) { + var preNode = node, + i = 0; + while (preNode = preNode.previousSibling) { + if (ignoreTextNode && preNode.nodeType == 3) { + if(preNode.nodeType != preNode.nextSibling.nodeType ){ + i++; + } + continue; + } + i++; + } + return i; + }, + + /** + * 检测节点node是否在给定的document对象上 + * @method inDoc + * @param { Node } node 需要检测的节点对象 + * @param { DomDocument } doc 需要检测的document对象 + * @return { Boolean } 该节点node是否在给定的document的dom树上 + * @example + * ```javascript + * + * var node = document.createElement("div"); + * + * //output: false + * console.log( UE.do.domUtils.inDoc( node, document ) ); + * + * document.body.appendChild( node ); + * + * //output: true + * console.log( UE.do.domUtils.inDoc( node, document ) ); + * + * ``` + */ + inDoc:function (node, doc) { + return domUtils.getPosition(node, doc) == 10; + }, + /** + * 根据给定的过滤规则filterFn, 查找符合该过滤规则的node节点的第一个祖先节点, + * 查找的起点是给定node节点的父节点。 + * @method findParent + * @param { Node } node 需要查找的节点 + * @param { Function } filterFn 自定义的过滤方法。 + * @warning 查找的终点是到body节点为止 + * @remind 自定义的过滤方法filterFn接受一个Node对象作为参数, 该对象代表当前执行检测的祖先节点。 如果该 + * 节点满足过滤条件, 则要求返回true, 这时将直接返回该节点作为findParent()的结果, 否则, 请返回false。 + * @return { Node | Null } 如果找到符合过滤条件的节点, 就返回该节点, 否则返回NULL + * @example + * ```javascript + * var filterNode = UE.dom.domUtils.findParent( document.body.firstChild, function ( node ) { + * + * //由于查找的终点是body节点, 所以永远也不会匹配当前过滤器的条件, 即这里永远会返回false + * return node.tagName === "HTML"; + * + * } ); + * + * //output: true + * console.log( filterNode === null ); + * ``` + */ + + /** + * 根据给定的过滤规则filterFn, 查找符合该过滤规则的node节点的第一个祖先节点, + * 如果includeSelf的值为true,则查找的起点是给定的节点node, 否则, 起点是node的父节点 + * @method findParent + * @param { Node } node 需要查找的节点 + * @param { Function } filterFn 自定义的过滤方法。 + * @param { Boolean } includeSelf 查找过程是否包含自身 + * @warning 查找的终点是到body节点为止 + * @remind 自定义的过滤方法filterFn接受一个Node对象作为参数, 该对象代表当前执行检测的祖先节点。 如果该 + * 节点满足过滤条件, 则要求返回true, 这时将直接返回该节点作为findParent()的结果, 否则, 请返回false。 + * @remind 如果includeSelf为true, 则过滤器第一次执行时的参数会是节点本身。 + * 反之, 过滤器第一次执行时的参数将是该节点的父节点。 + * @return { Node | Null } 如果找到符合过滤条件的节点, 就返回该节点, 否则返回NULL + * @example + * ```html + * + * + *
+ *
+ * + * + * + * ``` + */ + findParent:function (node, filterFn, includeSelf) { + if (node && !domUtils.isBody(node)) { + node = includeSelf ? node : node.parentNode; + while (node) { + if (!filterFn || filterFn(node) || domUtils.isBody(node)) { + return filterFn && !filterFn(node) && domUtils.isBody(node) ? null : node; + } + node = node.parentNode; + } + } + return null; + }, + /** + * 查找node的节点名为tagName的第一个祖先节点, 查找的起点是node节点的父节点。 + * @method findParentByTagName + * @param { Node } node 需要查找的节点对象 + * @param { Array } tagNames 需要查找的父节点的名称数组 + * @warning 查找的终点是到body节点为止 + * @return { Node | NULL } 如果找到符合条件的节点, 则返回该节点, 否则返回NULL + * @example + * ```javascript + * var node = UE.dom.domUtils.findParentByTagName( document.getElementsByTagName("div")[0], [ "BODY" ] ); + * //output: BODY + * console.log( node.tagName ); + * ``` + */ + + /** + * 查找node的节点名为tagName的祖先节点, 如果includeSelf的值为true,则查找的起点是给定的节点node, + * 否则, 起点是node的父节点。 + * @method findParentByTagName + * @param { Node } node 需要查找的节点对象 + * @param { Array } tagNames 需要查找的父节点的名称数组 + * @param { Boolean } includeSelf 查找过程是否包含node节点自身 + * @warning 查找的终点是到body节点为止 + * @return { Node | NULL } 如果找到符合条件的节点, 则返回该节点, 否则返回NULL + * @example + * ```javascript + * var queryTarget = document.getElementsByTagName("div")[0]; + * var node = UE.dom.domUtils.findParentByTagName( queryTarget, [ "DIV" ], true ); + * //output: true + * console.log( queryTarget === node ); + * ``` + */ + findParentByTagName:function (node, tagNames, includeSelf, excludeFn) { + tagNames = utils.listToMap(utils.isArray(tagNames) ? tagNames : [tagNames]); + return domUtils.findParent(node, function (node) { + return tagNames[node.tagName] && !(excludeFn && excludeFn(node)); + }, includeSelf); + }, + /** + * 查找节点node的祖先节点集合, 查找的起点是给定节点的父节点,结果集中不包含给定的节点。 + * @method findParents + * @param { Node } node 需要查找的节点对象 + * @return { Array } 给定节点的祖先节点数组 + * @grammar UE.dom.domUtils.findParents(node) => Array //返回一个祖先节点数组集合,不包含自身 + * @grammar UE.dom.domUtils.findParents(node,includeSelf) => Array //返回一个祖先节点数组集合,includeSelf指定是否包含自身 + * @grammar UE.dom.domUtils.findParents(node,includeSelf,filterFn) => Array //返回一个祖先节点数组集合,filterFn指定过滤条件,返回true的node将被选取 + * @grammar UE.dom.domUtils.findParents(node,includeSelf,filterFn,closerFirst) => Array //返回一个祖先节点数组集合,closerFirst为true的话,node的直接父亲节点是数组的第0个 + */ + + /** + * 查找节点node的祖先节点集合, 如果includeSelf的值为true, + * 则返回的结果集中允许出现当前给定的节点, 否则, 该节点不会出现在其结果集中。 + * @method findParents + * @param { Node } node 需要查找的节点对象 + * @param { Boolean } includeSelf 查找的结果中是否允许包含当前查找的节点对象 + * @return { Array } 给定节点的祖先节点数组 + */ + findParents:function (node, includeSelf, filterFn, closerFirst) { + var parents = includeSelf && ( filterFn && filterFn(node) || !filterFn ) ? [node] : []; + while (node = domUtils.findParent(node, filterFn)) { + parents.push(node); + } + return closerFirst ? parents : parents.reverse(); + }, + + /** + * 在节点node后面插入新节点newNode + * @method insertAfter + * @param { Node } node 目标节点 + * @param { Node } newNode 新插入的节点, 该节点将置于目标节点之后 + * @return { Node } 新插入的节点 + */ + insertAfter:function (node, newNode) { + return node.nextSibling ? node.parentNode.insertBefore(newNode, node.nextSibling): + node.parentNode.appendChild(newNode); + }, + + /** + * 删除节点node及其下属的所有节点 + * @method remove + * @param { Node } node 需要删除的节点对象 + * @return { Node } 返回刚删除的节点对象 + * @example + * ```html + *
+ *
你好
+ *
+ * + * ``` + */ + + /** + * 删除节点node,并根据keepChildren的值决定是否保留子节点 + * @method remove + * @param { Node } node 需要删除的节点对象 + * @param { Boolean } keepChildren 是否需要保留子节点 + * @return { Node } 返回刚删除的节点对象 + * @example + * ```html + *
+ *
你好
+ *
+ * + * ``` + */ + remove:function (node, keepChildren) { + var parent = node.parentNode, + child; + if (parent) { + if (keepChildren && node.hasChildNodes()) { + while (child = node.firstChild) { + parent.insertBefore(child, node); + } + } + parent.removeChild(node); + } + return node; + }, + + /** + * 取得node节点的下一个兄弟节点, 如果该节点其后没有兄弟节点, 则递归查找其父节点之后的第一个兄弟节点, + * 直到找到满足条件的节点或者递归到BODY节点之后才会结束。 + * @method getNextDomNode + * @param { Node } node 需要获取其后的兄弟节点的节点对象 + * @return { Node | NULL } 如果找满足条件的节点, 则返回该节点, 否则返回NULL + * @example + * ```html + * + *
+ * + *
+ * xxx + * + * + * ``` + * @example + * ```html + * + *
+ * + * xxx + *
+ * xxx + * + * + * ``` + */ + + /** + * 取得node节点的下一个兄弟节点, 如果startFromChild的值为ture,则先获取其子节点, + * 如果有子节点则直接返回第一个子节点;如果没有子节点或者startFromChild的值为false, + * 则执行getNextDomNode(Node node)的查找过程。 + * @method getNextDomNode + * @param { Node } node 需要获取其后的兄弟节点的节点对象 + * @param { Boolean } startFromChild 查找过程是否从其子节点开始 + * @return { Node | NULL } 如果找满足条件的节点, 则返回该节点, 否则返回NULL + * @see UE.dom.domUtils.getNextDomNode(Node) + */ + getNextDomNode:function (node, startFromChild, filterFn, guard) { + return getDomNode(node, 'firstChild', 'nextSibling', startFromChild, filterFn, guard); + }, + getPreDomNode:function (node, startFromChild, filterFn, guard) { + return getDomNode(node, 'lastChild', 'previousSibling', startFromChild, filterFn, guard); + }, + /** + * 检测节点node是否属是UEditor定义的bookmark节点 + * @method isBookmarkNode + * @private + * @param { Node } node 需要检测的节点对象 + * @return { Boolean } 是否是bookmark节点 + * @example + * ```html + * + * + * ``` + */ + isBookmarkNode:function (node) { + return node.nodeType == 1 && node.id && /^_baidu_bookmark_/i.test(node.id); + }, + /** + * 获取节点node所属的window对象 + * @method getWindow + * @param { Node } node 节点对象 + * @return { Window } 当前节点所属的window对象 + * @example + * ```javascript + * //output: true + * console.log( UE.dom.domUtils.getWindow( document.body ) === window ); + * ``` + */ + getWindow:function (node) { + var doc = node.ownerDocument || node; + return doc.defaultView || doc.parentWindow; + }, + /** + * 获取离nodeA与nodeB最近的公共的祖先节点 + * @method getCommonAncestor + * @param { Node } nodeA 第一个节点 + * @param { Node } nodeB 第二个节点 + * @remind 如果给定的两个节点是同一个节点, 将直接返回该节点。 + * @return { Node | NULL } 如果未找到公共节点, 返回NULL, 否则返回最近的公共祖先节点。 + * @example + * ```javascript + * var commonAncestor = UE.dom.domUtils.getCommonAncestor( document.body, document.body.firstChild ); + * //output: true + * console.log( commonAncestor.tagName.toLowerCase() === 'body' ); + * ``` + */ + getCommonAncestor:function (nodeA, nodeB) { + if (nodeA === nodeB) + return nodeA; + var parentsA = [nodeA] , parentsB = [nodeB], parent = nodeA, i = -1; + while (parent = parent.parentNode) { + if (parent === nodeB) { + return parent; + } + parentsA.push(parent); + } + parent = nodeB; + while (parent = parent.parentNode) { + if (parent === nodeA) + return parent; + parentsB.push(parent); + } + parentsA.reverse(); + parentsB.reverse(); + while (i++, parentsA[i] === parentsB[i]) { + } + return i == 0 ? null : parentsA[i - 1]; + + }, + /** + * 清除node节点左右连续为空的兄弟inline节点 + * @method clearEmptySibling + * @param { Node } node 执行的节点对象, 如果该节点的左右连续的兄弟节点是空的inline节点, + * 则这些兄弟节点将被删除 + * @grammar UE.dom.domUtils.clearEmptySibling(node,ignoreNext) //ignoreNext指定是否忽略右边空节点 + * @grammar UE.dom.domUtils.clearEmptySibling(node,ignoreNext,ignorePre) //ignorePre指定是否忽略左边空节点 + * @example + * ```html + * + *
+ * + * + * + * xxx + * + * + * + * ``` + */ + + /** + * 清除node节点左右连续为空的兄弟inline节点, 如果ignoreNext的值为true, + * 则忽略对右边兄弟节点的操作。 + * @method clearEmptySibling + * @param { Node } node 执行的节点对象, 如果该节点的左右连续的兄弟节点是空的inline节点, + * @param { Boolean } ignoreNext 是否忽略忽略对右边的兄弟节点的操作 + * 则这些兄弟节点将被删除 + * @see UE.dom.domUtils.clearEmptySibling(Node) + */ + + /** + * 清除node节点左右连续为空的兄弟inline节点, 如果ignoreNext的值为true, + * 则忽略对右边兄弟节点的操作, 如果ignorePre的值为true,则忽略对左边兄弟节点的操作。 + * @method clearEmptySibling + * @param { Node } node 执行的节点对象, 如果该节点的左右连续的兄弟节点是空的inline节点, + * @param { Boolean } ignoreNext 是否忽略忽略对右边的兄弟节点的操作 + * @param { Boolean } ignorePre 是否忽略忽略对左边的兄弟节点的操作 + * 则这些兄弟节点将被删除 + * @see UE.dom.domUtils.clearEmptySibling(Node) + */ + clearEmptySibling:function (node, ignoreNext, ignorePre) { + function clear(next, dir) { + var tmpNode; + while (next && !domUtils.isBookmarkNode(next) && (domUtils.isEmptyInlineElement(next) + //这里不能把空格算进来会吧空格干掉,出现文字间的空格丢掉了 + || !new RegExp('[^\t\n\r' + domUtils.fillChar + ']').test(next.nodeValue) )) { + tmpNode = next[dir]; + domUtils.remove(next); + next = tmpNode; + } + } + !ignoreNext && clear(node.nextSibling, 'nextSibling'); + !ignorePre && clear(node.previousSibling, 'previousSibling'); + }, + /** + * 将一个文本节点textNode拆分成两个文本节点,offset指定拆分位置 + * @method split + * @param { Node } textNode 需要拆分的文本节点对象 + * @param { int } offset 需要拆分的位置, 位置计算从0开始 + * @return { Node } 拆分后形成的新节点 + * @example + * ```html + *
abcdef
+ * + * ``` + */ + split:function (node, offset) { + var doc = node.ownerDocument; + if (browser.ie && offset == node.nodeValue.length) { + var next = doc.createTextNode(''); + return domUtils.insertAfter(node, next); + } + var retval = node.splitText(offset); + //ie8下splitText不会跟新childNodes,我们手动触发他的更新 + if (browser.ie8) { + var tmpNode = doc.createTextNode(''); + domUtils.insertAfter(retval, tmpNode); + domUtils.remove(tmpNode); + } + return retval; + }, + + /** + * 检测文本节点textNode是否为空节点(包括空格、换行、占位符等字符) + * @method isWhitespace + * @param { Node } node 需要检测的节点对象 + * @return { Boolean } 检测的节点是否为空 + * @example + * ```html + *
+ * + *
+ * + * ``` + */ + isWhitespace:function (node) { + return !new RegExp('[^ \t\n\r' + domUtils.fillChar + ']').test(node.nodeValue); + }, + /** + * 获取元素element相对于viewport的位置坐标 + * @method getXY + * @param { Node } element 需要计算位置的节点对象 + * @return { Object } 返回形如{x:left,y:top}的一个key-value映射对象, 其中键x代表水平偏移距离, + * y代表垂直偏移距离。 + * + * @example + * ```javascript + * var location = UE.dom.domUtils.getXY( document.getElementById("test") ); + * //output: test的坐标为: 12, 24 + * console.log( 'test的坐标为: ', location.x, ',', location.y ); + * ``` + */ + getXY:function (element) { + var x = 0, y = 0; + while (element.offsetParent) { + y += element.offsetTop; + x += element.offsetLeft; + element = element.offsetParent; + } + return { 'x':x, 'y':y}; + }, + /** + * 为元素element绑定原生DOM事件,type为事件类型,handler为处理函数 + * @method on + * @param { Node } element 需要绑定事件的节点对象 + * @param { String } type 绑定的事件类型 + * @param { Function } handler 事件处理器 + * @example + * ```javascript + * UE.dom.domUtils.on(document.body,"click",function(e){ + * //e为事件对象,this为被点击元素对戏那个 + * }); + * ``` + */ + + /** + * 为元素element绑定原生DOM事件,type为事件类型,handler为处理函数 + * @method on + * @param { Node } element 需要绑定事件的节点对象 + * @param { Array } type 绑定的事件类型数组 + * @param { Function } handler 事件处理器 + * @example + * ```javascript + * UE.dom.domUtils.on(document.body,["click","mousedown"],function(evt){ + * //evt为事件对象,this为被点击元素对象 + * }); + * ``` + */ + on:function (element, type, handler) { + + var types = utils.isArray(type) ? type : utils.trim(type).split(/\s+/), + k = types.length; + if (k) while (k--) { + type = types[k]; + if (element.addEventListener) { + element.addEventListener(type, handler, false); + } else { + if (!handler._d) { + handler._d = { + els : [] + }; + } + var key = type + handler.toString(),index = utils.indexOf(handler._d.els,element); + if (!handler._d[key] || index == -1) { + if(index == -1){ + handler._d.els.push(element); + } + if(!handler._d[key]){ + handler._d[key] = function (evt) { + return handler.call(evt.srcElement, evt || window.event); + }; + } + + + element.attachEvent('on' + type, handler._d[key]); + } + } + } + element = null; + }, + /** + * 解除DOM事件绑定 + * @method un + * @param { Node } element 需要解除事件绑定的节点对象 + * @param { String } type 需要接触绑定的事件类型 + * @param { Function } handler 对应的事件处理器 + * @example + * ```javascript + * UE.dom.domUtils.un(document.body,"click",function(evt){ + * //evt为事件对象,this为被点击元素对象 + * }); + * ``` + */ + + /** + * 解除DOM事件绑定 + * @method un + * @param { Node } element 需要解除事件绑定的节点对象 + * @param { Array } type 需要接触绑定的事件类型数组 + * @param { Function } handler 对应的事件处理器 + * @example + * ```javascript + * UE.dom.domUtils.un(document.body, ["click","mousedown"],function(evt){ + * //evt为事件对象,this为被点击元素对象 + * }); + * ``` + */ + un:function (element, type, handler) { + var types = utils.isArray(type) ? type : utils.trim(type).split(/\s+/), + k = types.length; + if (k) while (k--) { + type = types[k]; + if (element.removeEventListener) { + element.removeEventListener(type, handler, false); + } else { + var key = type + handler.toString(); + try{ + element.detachEvent('on' + type, handler._d ? handler._d[key] : handler); + }catch(e){} + if (handler._d && handler._d[key]) { + var index = utils.indexOf(handler._d.els,element); + if(index!=-1){ + handler._d.els.splice(index,1); + } + handler._d.els.length == 0 && delete handler._d[key]; + } + } + } + }, + + /** + * 比较节点nodeA与节点nodeB是否具有相同的标签名、属性名以及属性值 + * @method isSameElement + * @param { Node } nodeA 需要比较的节点 + * @param { Node } nodeB 需要比较的节点 + * @return { Boolean } 两个节点是否具有相同的标签名、属性名以及属性值 + * @example + * ```html + * ssss + * bbbbb + * ssss + * bbbbb + * + * + * ``` + */ + isSameElement:function (nodeA, nodeB) { + if (nodeA.tagName != nodeB.tagName) { + return false; + } + var thisAttrs = nodeA.attributes, + otherAttrs = nodeB.attributes; + if (!ie && thisAttrs.length != otherAttrs.length) { + return false; + } + var attrA, attrB, al = 0, bl = 0; + for (var i = 0; attrA = thisAttrs[i++];) { + if (attrA.nodeName == 'style') { + if (attrA.specified) { + al++; + } + if (domUtils.isSameStyle(nodeA, nodeB)) { + continue; + } else { + return false; + } + } + if (ie) { + if (attrA.specified) { + al++; + attrB = otherAttrs.getNamedItem(attrA.nodeName); + } else { + continue; + } + } else { + attrB = nodeB.attributes[attrA.nodeName]; + } + if (!attrB.specified || attrA.nodeValue != attrB.nodeValue) { + return false; + } + } + // 有可能attrB的属性包含了attrA的属性之外还有自己的属性 + if (ie) { + for (i = 0; attrB = otherAttrs[i++];) { + if (attrB.specified) { + bl++; + } + } + if (al != bl) { + return false; + } + } + return true; + }, + + /** + * 判断节点nodeA与节点nodeB的元素的style属性是否一致 + * @method isSameStyle + * @param { Node } nodeA 需要比较的节点 + * @param { Node } nodeB 需要比较的节点 + * @return { Boolean } 两个节点是否具有相同的style属性值 + * @example + * ```html + * ssss + * bbbbb + * ssss + * bbbbb + * + * + * ``` + */ + isSameStyle:function (nodeA, nodeB) { + var styleA = nodeA.style.cssText.replace(/( ?; ?)/g, ';').replace(/( ?: ?)/g, ':'), + styleB = nodeB.style.cssText.replace(/( ?; ?)/g, ';').replace(/( ?: ?)/g, ':'); + if (browser.opera) { + styleA = nodeA.style; + styleB = nodeB.style; + if (styleA.length != styleB.length) + return false; + for (var p in styleA) { + if (/^(\d+|csstext)$/i.test(p)) { + continue; + } + if (styleA[p] != styleB[p]) { + return false; + } + } + return true; + } + if (!styleA || !styleB) { + return styleA == styleB; + } + styleA = styleA.split(';'); + styleB = styleB.split(';'); + if (styleA.length != styleB.length) { + return false; + } + for (var i = 0, ci; ci = styleA[i++];) { + if (utils.indexOf(styleB, ci) == -1) { + return false; + } + } + return true; + }, + /** + * 检查节点node是否为block元素 + * @method isBlockElm + * @param { Node } node 需要检测的节点对象 + * @return { Boolean } 是否是block元素节点 + * @warning 该方法的判断规则如下: 如果该元素原本是block元素, 则不论该元素当前的css样式是什么都会返回true; + * 否则,检测该元素的css样式, 如果该元素当前是block元素, 则返回true。 其余情况下都返回false。 + * @example + * ```html + * + * + *
+ * + * + * ``` + */ + isBlockElm:function (node) { + return node.nodeType == 1 && (dtd.$block[node.tagName] || styleBlock[domUtils.getComputedStyle(node, 'display')]) && !dtd.$nonChild[node.tagName]; + }, + /** + * 检测node节点是否为body节点 + * @method isBody + * @param { Element } node 需要检测的dom元素 + * @return { Boolean } 给定的元素是否是body元素 + * @example + * ```javascript + * //output: true + * console.log( UE.dom.domUtils.isBody( document.body ) ); + * ``` + */ + isBody:function (node) { + return node && node.nodeType == 1 && node.tagName.toLowerCase() == 'body'; + }, + /** + * 以node节点为分界,将该节点的指定祖先节点parent拆分成两个独立的节点, + * 拆分形成的两个节点之间是node节点 + * @method breakParent + * @param { Node } node 作为分界的节点对象 + * @param { Node } parent 该节点必须是node节点的祖先节点, 且是block节点。 + * @return { Node } 给定的node分界节点 + * @example + * ```javascript + * + * var node = document.createElement("span"), + * wrapNode = document.createElement( "div" ), + * parent = document.createElement("p"); + * + * parent.appendChild( node ); + * wrapNode.appendChild( parent ); + * + * //拆分前 + * //output:

+ * console.log( wrapNode.innerHTML ); + * + * + * UE.dom.domUtils.breakParent( node, parent ); + * //拆分后 + * //output:

+ * console.log( wrapNode.innerHTML ); + * + * ``` + */ + breakParent:function (node, parent) { + var tmpNode, + parentClone = node, + clone = node, + leftNodes, + rightNodes; + do { + parentClone = parentClone.parentNode; + if (leftNodes) { + tmpNode = parentClone.cloneNode(false); + tmpNode.appendChild(leftNodes); + leftNodes = tmpNode; + tmpNode = parentClone.cloneNode(false); + tmpNode.appendChild(rightNodes); + rightNodes = tmpNode; + } else { + leftNodes = parentClone.cloneNode(false); + rightNodes = leftNodes.cloneNode(false); + } + while (tmpNode = clone.previousSibling) { + leftNodes.insertBefore(tmpNode, leftNodes.firstChild); + } + while (tmpNode = clone.nextSibling) { + rightNodes.appendChild(tmpNode); + } + clone = parentClone; + } while (parent !== parentClone); + tmpNode = parent.parentNode; + tmpNode.insertBefore(leftNodes, parent); + tmpNode.insertBefore(rightNodes, parent); + tmpNode.insertBefore(node, rightNodes); + domUtils.remove(parent); + return node; + }, + /** + * 检查节点node是否是空inline节点 + * @method isEmptyInlineElement + * @param { Node } node 需要检测的节点对象 + * @return { Number } 如果给定的节点是空的inline节点, 则返回1, 否则返回0。 + * @example + * ```html + * => 1 + * => 1 + * => 1 + * xx => 0 + * ``` + */ + isEmptyInlineElement:function (node) { + if (node.nodeType != 1 || !dtd.$removeEmpty[ node.tagName ]) { + return 0; + } + node = node.firstChild; + while (node) { + //如果是创建的bookmark就跳过 + if (domUtils.isBookmarkNode(node)) { + return 0; + } + if (node.nodeType == 1 && !domUtils.isEmptyInlineElement(node) || + node.nodeType == 3 && !domUtils.isWhitespace(node) + ) { + return 0; + } + node = node.nextSibling; + } + return 1; + + }, + + /** + * 删除node节点下首尾两端的空白文本子节点 + * @method trimWhiteTextNode + * @param { Element } node 需要执行删除操作的元素对象 + * @example + * ```javascript + * var node = document.createElement("div"); + * + * node.appendChild( document.createTextNode( "" ) ); + * + * node.appendChild( document.createElement("div") ); + * + * node.appendChild( document.createTextNode( "" ) ); + * + * //3 + * console.log( node.childNodes.length ); + * + * UE.dom.domUtils.trimWhiteTextNode( node ); + * + * //1 + * console.log( node.childNodes.length ); + * ``` + */ + trimWhiteTextNode:function (node) { + function remove(dir) { + var child; + while ((child = node[dir]) && child.nodeType == 3 && domUtils.isWhitespace(child)) { + node.removeChild(child); + } + } + remove('firstChild'); + remove('lastChild'); + }, + + /** + * 合并node节点下相同的子节点 + * @name mergeChild + * @desc + * UE.dom.domUtils.mergeChild(node,tagName) //tagName要合并的子节点的标签 + * @example + *

xxaaxx

+ * ==> UE.dom.domUtils.mergeChild(node,'span') + *

xxaaxx

+ */ + mergeChild:function (node, tagName, attrs) { + var list = domUtils.getElementsByTagName(node, node.tagName.toLowerCase()); + for (var i = 0, ci; ci = list[i++];) { + if (!ci.parentNode || domUtils.isBookmarkNode(ci)) { + continue; + } + //span单独处理 + if (ci.tagName.toLowerCase() == 'span') { + if (node === ci.parentNode) { + domUtils.trimWhiteTextNode(node); + if (node.childNodes.length == 1) { + node.style.cssText = ci.style.cssText + ";" + node.style.cssText; + domUtils.remove(ci, true); + continue; + } + } + ci.style.cssText = node.style.cssText + ';' + ci.style.cssText; + if (attrs) { + var style = attrs.style; + if (style) { + style = style.split(';'); + for (var j = 0, s; s = style[j++];) { + ci.style[utils.cssStyleToDomStyle(s.split(':')[0])] = s.split(':')[1]; + } + } + } + if (domUtils.isSameStyle(ci, node)) { + domUtils.remove(ci, true); + } + continue; + } + if (domUtils.isSameElement(node, ci)) { + domUtils.remove(ci, true); + } + } + }, + + /** + * 原生方法getElementsByTagName的封装 + * @method getElementsByTagName + * @param { Node } node 目标节点对象 + * @param { String } tagName 需要查找的节点的tagName, 多个tagName以空格分割 + * @return { Array } 符合条件的节点集合 + */ + getElementsByTagName:function (node, name,filter) { + if(filter && utils.isString(filter)){ + var className = filter; + filter = function(node){return domUtils.hasClass(node,className)} + } + name = utils.trim(name).replace(/[ ]{2,}/g,' ').split(' '); + var arr = []; + for(var n = 0,ni;ni=name[n++];){ + var list = node.getElementsByTagName(ni); + for (var i = 0, ci; ci = list[i++];) { + if(!filter || filter(ci)) + arr.push(ci); + } + } + + return arr; + }, + /** + * 将节点node提取到父节点上 + * @method mergeToParent + * @param { Element } node 需要提取的元素对象 + * @example + * ```html + *
+ *
+ * + *
+ *
+ * + * + * ``` + */ + mergeToParent:function (node) { + var parent = node.parentNode; + while (parent && dtd.$removeEmpty[parent.tagName]) { + if (parent.tagName == node.tagName || parent.tagName == 'A') {//针对a标签单独处理 + domUtils.trimWhiteTextNode(parent); + //span需要特殊处理 不处理这样的情况 xxxxxxxxx + if (parent.tagName == 'SPAN' && !domUtils.isSameStyle(parent, node) + || (parent.tagName == 'A' && node.tagName == 'SPAN')) { + if (parent.childNodes.length > 1 || parent !== node.parentNode) { + node.style.cssText = parent.style.cssText + ";" + node.style.cssText; + parent = parent.parentNode; + continue; + } else { + parent.style.cssText += ";" + node.style.cssText; + //trace:952 a标签要保持下划线 + if (parent.tagName == 'A') { + parent.style.textDecoration = 'underline'; + } + } + } + if (parent.tagName != 'A') { + parent === node.parentNode && domUtils.remove(node, true); + break; + } + } + parent = parent.parentNode; + } + }, + /** + * 合并节点node的左右兄弟节点 + * @method mergeSibling + * @param { Element } node 需要合并的目标节点 + * @example + * ```html + * xxxxoooxxxx + * + * + * ``` + */ + + /** + * 合并节点node的左右兄弟节点, 可以根据给定的条件选择是否忽略合并左节点。 + * @method mergeSibling + * @param { Element } node 需要合并的目标节点 + * @param { Boolean } ignorePre 是否忽略合并左节点 + * @example + * ```html + * xxxxoooxxxx + * + * + * ``` + */ + + /** + * 合并节点node的左右兄弟节点,可以根据给定的条件选择是否忽略合并左右节点。 + * @method mergeSibling + * @param { Element } node 需要合并的目标节点 + * @param { Boolean } ignorePre 是否忽略合并左节点 + * @param { Boolean } ignoreNext 是否忽略合并右节点 + * @remind 如果同时忽略左右节点, 则该操作什么也不会做 + * @example + * ```html + * xxxxoooxxxx + * + * + * ``` + */ + mergeSibling:function (node, ignorePre, ignoreNext) { + function merge(rtl, start, node) { + var next; + if ((next = node[rtl]) && !domUtils.isBookmarkNode(next) && next.nodeType == 1 && domUtils.isSameElement(node, next)) { + while (next.firstChild) { + if (start == 'firstChild') { + node.insertBefore(next.lastChild, node.firstChild); + } else { + node.appendChild(next.firstChild); + } + } + domUtils.remove(next); + } + } + !ignorePre && merge('previousSibling', 'firstChild', node); + !ignoreNext && merge('nextSibling', 'lastChild', node); + }, + + /** + * 设置节点node及其子节点不会被选中 + * @method unSelectable + * @param { Element } node 需要执行操作的dom元素 + * @remind 执行该操作后的节点, 将不能被鼠标选中 + * @example + * ```javascript + * UE.dom.domUtils.unSelectable( document.body ); + * ``` + */ + unSelectable:ie && browser.ie9below || browser.opera ? function (node) { + //for ie9 + node.onselectstart = function () { + return false; + }; + node.onclick = node.onkeyup = node.onkeydown = function () { + return false; + }; + node.unselectable = 'on'; + node.setAttribute("unselectable", "on"); + for (var i = 0, ci; ci = node.all[i++];) { + switch (ci.tagName.toLowerCase()) { + case 'iframe' : + case 'textarea' : + case 'input' : + case 'select' : + break; + default : + ci.unselectable = 'on'; + node.setAttribute("unselectable", "on"); + } + } + } : function (node) { + node.style.MozUserSelect = + node.style.webkitUserSelect = + node.style.msUserSelect = + node.style.KhtmlUserSelect = 'none'; + }, + /** + * 删除节点node上的指定属性名称的属性 + * @method removeAttributes + * @param { Node } node 需要删除属性的节点对象 + * @param { String } attrNames 可以是空格隔开的多个属性名称,该操作将会依次删除相应的属性 + * @example + * ```html + *
+ * xxxxx + *
+ * + * + * ``` + */ + + /** + * 删除节点node上的指定属性名称的属性 + * @method removeAttributes + * @param { Node } node 需要删除属性的节点对象 + * @param { Array } attrNames 需要删除的属性名数组 + * @example + * ```html + *
+ * xxxxx + *
+ * + * + * ``` + */ + removeAttributes:function (node, attrNames) { + attrNames = utils.isArray(attrNames) ? attrNames : utils.trim(attrNames).replace(/[ ]{2,}/g,' ').split(' '); + for (var i = 0, ci; ci = attrNames[i++];) { + ci = attrFix[ci] || ci; + switch (ci) { + case 'className': + node[ci] = ''; + break; + case 'style': + node.style.cssText = ''; + var val = node.getAttributeNode('style'); + !browser.ie && val && node.removeAttributeNode(val); + } + node.removeAttribute(ci); + } + }, + /** + * 在doc下创建一个标签名为tag,属性为attrs的元素 + * @method createElement + * @param { DomDocument } doc 新创建的元素属于该document节点创建 + * @param { String } tagName 需要创建的元素的标签名 + * @param { Object } attrs 新创建的元素的属性key-value集合 + * @return { Element } 新创建的元素对象 + * @example + * ```javascript + * var ele = UE.dom.domUtils.createElement( document, 'div', { + * id: 'test' + * } ); + * + * //output: DIV + * console.log( ele.tagName ); + * + * //output: test + * console.log( ele.id ); + * + * ``` + */ + createElement:function (doc, tag, attrs) { + return domUtils.setAttributes(doc.createElement(tag), attrs) + }, + /** + * 为节点node添加属性attrs,attrs为属性键值对 + * @method setAttributes + * @param { Element } node 需要设置属性的元素对象 + * @param { Object } attrs 需要设置的属性名-值对 + * @return { Element } 设置属性的元素对象 + * @example + * ```html + * + * + * + * + */ + setAttributes:function (node, attrs) { + for (var attr in attrs) { + if(attrs.hasOwnProperty(attr)){ + var value = attrs[attr]; + switch (attr) { + case 'class': + //ie下要这样赋值,setAttribute不起作用 + node.className = value; + break; + case 'style' : + node.style.cssText = node.style.cssText + ";" + value; + break; + case 'innerHTML': + node[attr] = value; + break; + case 'value': + node.value = value; + break; + default: + node.setAttribute(attrFix[attr] || attr, value); + } + } + } + return node; + }, + + /** + * 获取元素element经过计算后的样式值 + * @method getComputedStyle + * @param { Element } element 需要获取样式的元素对象 + * @param { String } styleName 需要获取的样式名 + * @return { String } 获取到的样式值 + * @example + * ```html + * + * + * + * + * + * ``` + */ + getComputedStyle:function (element, styleName) { + //一下的属性单独处理 + var pros = 'width height top left'; + + if(pros.indexOf(styleName) > -1){ + return element['offset' + styleName.replace(/^\w/,function(s){return s.toUpperCase()})] + 'px'; + } + //忽略文本节点 + if (element.nodeType == 3) { + element = element.parentNode; + } + //ie下font-size若body下定义了font-size,则从currentStyle里会取到这个font-size. 取不到实际值,故此修改. + if (browser.ie && browser.version < 9 && styleName == 'font-size' && !element.style.fontSize && + !dtd.$empty[element.tagName] && !dtd.$nonChild[element.tagName]) { + var span = element.ownerDocument.createElement('span'); + span.style.cssText = 'padding:0;border:0;font-family:simsun;'; + span.innerHTML = '.'; + element.appendChild(span); + var result = span.offsetHeight; + element.removeChild(span); + span = null; + return result + 'px'; + } + try { + var value = domUtils.getStyle(element, styleName) || + (window.getComputedStyle ? domUtils.getWindow(element).getComputedStyle(element, '').getPropertyValue(styleName) : + ( element.currentStyle || element.style )[utils.cssStyleToDomStyle(styleName)]); + + } catch (e) { + return ""; + } + return utils.transUnitToPx(utils.fixColor(styleName, value)); + }, + /** + * 删除元素element指定的className + * @method removeClasses + * @param { Element } ele 需要删除class的元素节点 + * @param { String } classNames 需要删除的className, 多个className之间以空格分开 + * @example + * ```html + * xxx + * + * + * ``` + */ + + /** + * 删除元素element指定的className + * @method removeClasses + * @param { Element } ele 需要删除class的元素节点 + * @param { Array } classNames 需要删除的className数组 + * @example + * ```html + * xxx + * + * + * ``` + */ + removeClasses:function (elm, classNames) { + classNames = utils.isArray(classNames) ? classNames : + utils.trim(classNames).replace(/[ ]{2,}/g,' ').split(' '); + for(var i = 0,ci,cls = elm.className;ci=classNames[i++];){ + cls = cls.replace(new RegExp('\\b' + ci + '\\b'),'') + } + cls = utils.trim(cls).replace(/[ ]{2,}/g,' '); + if(cls){ + elm.className = cls; + }else{ + domUtils.removeAttributes(elm,['class']); + } + }, + /** + * 给元素element添加className + * @method addClass + * @param { Node } ele 需要增加className的元素 + * @param { String } classNames 需要添加的className, 多个className之间以空格分割 + * @remind 相同的类名不会被重复添加 + * @example + * ```html + * + * + * + * ``` + */ + + /** + * 判断元素element是否包含给定的样式类名className + * @method hasClass + * @param { Node } ele 需要检测的元素 + * @param { Array } classNames 需要检测的className数组 + * @return { Boolean } 元素是否包含所有给定的className + * @example + * ```html + * + * + * + * ``` + */ + hasClass:function (element, className) { + if(utils.isRegExp(className)){ + return className.test(element.className) + } + className = utils.trim(className).replace(/[ ]{2,}/g,' ').split(' '); + for(var i = 0,ci,cls = element.className;ci=className[i++];){ + if(!new RegExp('\\b' + ci + '\\b','i').test(cls)){ + return false; + } + } + return i - 1 == className.length; + }, + + /** + * 阻止事件默认行为 + * @method preventDefault + * @param { Event } evt 需要阻止默认行为的事件对象 + * @example + * ```javascript + * UE.dom.domUtils.preventDefault( evt ); + * ``` + */ + preventDefault:function (evt) { + evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); + }, + /** + * 删除元素element指定的样式 + * @method removeStyle + * @param { Element } element 需要删除样式的元素 + * @param { String } styleName 需要删除的样式名 + * @example + * ```html + * + * + * + * ``` + */ + removeStyle:function (element, name) { + if(browser.ie ){ + //针对color先单独处理一下 + if(name == 'color'){ + name = '(^|;)' + name; + } + element.style.cssText = element.style.cssText.replace(new RegExp(name + '[^:]*:[^;]+;?','ig'),'') + }else{ + if (element.style.removeProperty) { + element.style.removeProperty (name); + }else { + element.style.removeAttribute (utils.cssStyleToDomStyle(name)); + } + } + + + if (!element.style.cssText) { + domUtils.removeAttributes(element, ['style']); + } + }, + /** + * 获取元素element的style属性的指定值 + * @method getStyle + * @param { Element } element 需要获取属性值的元素 + * @param { String } styleName 需要获取的style的名称 + * @warning 该方法仅获取元素style属性中所标明的值 + * @return { String } 该元素包含指定的style属性值 + * @example + * ```html + *
+ * + * + * ``` + */ + getStyle:function (element, name) { + var value = element.style[ utils.cssStyleToDomStyle(name) ]; + return utils.fixColor(name, value); + }, + /** + * 为元素element设置样式属性值 + * @method setStyle + * @param { Element } element 需要设置样式的元素 + * @param { String } styleName 样式名 + * @param { String } styleValue 样式值 + * @example + * ```html + *
+ * + * + * ``` + */ + setStyle:function (element, name, value) { + element.style[utils.cssStyleToDomStyle(name)] = value; + if(!utils.trim(element.style.cssText)){ + this.removeAttributes(element,'style') + } + }, + /** + * 为元素element设置多个样式属性值 + * @method setStyles + * @param { Element } element 需要设置样式的元素 + * @param { Object } styles 样式名值对 + * @example + * ```html + *
+ * + * + * ``` + */ + setStyles:function (element, styles) { + for (var name in styles) { + if (styles.hasOwnProperty(name)) { + domUtils.setStyle(element, name, styles[name]); + } + } + }, + /** + * 删除_moz_dirty属性 + * @private + * @method removeDirtyAttr + */ + removeDirtyAttr:function (node) { + for (var i = 0, ci, nodes = node.getElementsByTagName('*'); ci = nodes[i++];) { + ci.removeAttribute('_moz_dirty'); + } + node.removeAttribute('_moz_dirty'); + }, + /** + * 获取子节点的数量 + * @method getChildCount + * @param { Element } node 需要检测的元素 + * @return { Number } 给定的node元素的子节点数量 + * @example + * ```html + *
+ * + *
+ * + * + * ``` + */ + + /** + * 根据给定的过滤规则, 获取符合条件的子节点的数量 + * @method getChildCount + * @param { Element } node 需要检测的元素 + * @param { Function } fn 过滤器, 要求对符合条件的子节点返回true, 反之则要求返回false + * @return { Number } 符合过滤条件的node元素的子节点数量 + * @example + * ```html + *
+ * + *
+ * + * + * ``` + */ + getChildCount:function (node, fn) { + var count = 0, first = node.firstChild; + fn = fn || function () { + return 1; + }; + while (first) { + if (fn(first)) { + count++; + } + first = first.nextSibling; + } + return count; + }, + + /** + * 判断给定节点是否为空节点 + * @method isEmptyNode + * @param { Node } node 需要检测的节点对象 + * @return { Boolean } 节点是否为空 + * @example + * ```javascript + * UE.dom.domUtils.isEmptyNode( document.body ); + * ``` + */ + isEmptyNode:function (node) { + return !node.firstChild || domUtils.getChildCount(node, function (node) { + return !domUtils.isBr(node) && !domUtils.isBookmarkNode(node) && !domUtils.isWhitespace(node) + }) == 0 + }, + clearSelectedArr:function (nodes) { + var node; + while (node = nodes.pop()) { + domUtils.removeAttributes(node, ['class']); + } + }, + /** + * 将显示区域滚动到指定节点的位置 + * @method scrollToView + * @param {Node} node 节点 + * @param {window} win window对象 + * @param {Number} offsetTop 距离上方的偏移量 + */ + scrollToView:function (node, win, offsetTop) { + var getViewPaneSize = function () { + var doc = win.document, + mode = doc.compatMode == 'CSS1Compat'; + return { + width:( mode ? doc.documentElement.clientWidth : doc.body.clientWidth ) || 0, + height:( mode ? doc.documentElement.clientHeight : doc.body.clientHeight ) || 0 + }; + }, + getScrollPosition = function (win) { + if ('pageXOffset' in win) { + return { + x:win.pageXOffset || 0, + y:win.pageYOffset || 0 + }; + } + else { + var doc = win.document; + return { + x:doc.documentElement.scrollLeft || doc.body.scrollLeft || 0, + y:doc.documentElement.scrollTop || doc.body.scrollTop || 0 + }; + } + }; + var winHeight = getViewPaneSize().height, offset = winHeight * -1 + offsetTop; + offset += (node.offsetHeight || 0); + var elementPosition = domUtils.getXY(node); + offset += elementPosition.y; + var currentScroll = getScrollPosition(win).y; + // offset += 50; + if (offset > currentScroll || offset < currentScroll - winHeight) { + win.scrollTo(0, offset + (offset < 0 ? -20 : 20)); + } + }, + /** + * 判断给定节点是否为br + * @method isBr + * @param { Node } node 需要判断的节点对象 + * @return { Boolean } 给定的节点是否是br节点 + */ + isBr:function (node) { + return node.nodeType == 1 && node.tagName == 'BR'; + }, + /** + * 判断给定的节点是否是一个“填充”节点 + * @private + * @method isFillChar + * @param { Node } node 需要判断的节点 + * @param { Boolean } isInStart 是否从节点内容的开始位置匹配 + * @returns { Boolean } 节点是否是填充节点 + */ + isFillChar:function (node,isInStart) { + if(node.nodeType != 3) + return false; + var text = node.nodeValue; + if(isInStart){ + return new RegExp('^' + domUtils.fillChar).test(text) + } + return !text.replace(new RegExp(domUtils.fillChar,'g'), '').length + }, + isStartInblock:function (range) { + var tmpRange = range.cloneRange(), + flag = 0, + start = tmpRange.startContainer, + tmp; + if(start.nodeType == 1 && start.childNodes[tmpRange.startOffset]){ + start = start.childNodes[tmpRange.startOffset]; + var pre = start.previousSibling; + while(pre && domUtils.isFillChar(pre)){ + start = pre; + pre = pre.previousSibling; + } + } + if(this.isFillChar(start,true) && tmpRange.startOffset == 1){ + tmpRange.setStartBefore(start); + start = tmpRange.startContainer; + } + + while (start && domUtils.isFillChar(start)) { + tmp = start; + start = start.previousSibling + } + if (tmp) { + tmpRange.setStartBefore(tmp); + start = tmpRange.startContainer; + } + if (start.nodeType == 1 && domUtils.isEmptyNode(start) && tmpRange.startOffset == 1) { + tmpRange.setStart(start, 0).collapse(true); + } + while (!tmpRange.startOffset) { + start = tmpRange.startContainer; + if (domUtils.isBlockElm(start) || domUtils.isBody(start)) { + flag = 1; + break; + } + var pre = tmpRange.startContainer.previousSibling, + tmpNode; + if (!pre) { + tmpRange.setStartBefore(tmpRange.startContainer); + } else { + while (pre && domUtils.isFillChar(pre)) { + tmpNode = pre; + pre = pre.previousSibling; + } + if (tmpNode) { + tmpRange.setStartBefore(tmpNode); + } else { + tmpRange.setStartBefore(tmpRange.startContainer); + } + } + } + return flag && !domUtils.isBody(tmpRange.startContainer) ? 1 : 0; + }, + + /** + * 判断给定的元素是否是一个空元素 + * @method isEmptyBlock + * @param { Element } node 需要判断的元素 + * @return { Boolean } 是否是空元素 + * @example + * ```html + *
+ * + * + * ``` + */ + + /** + * 根据指定的判断规则判断给定的元素是否是一个空元素 + * @method isEmptyBlock + * @param { Element } node 需要判断的元素 + * @param { RegExp } reg 对内容执行判断的正则表达式对象 + * @return { Boolean } 是否是空元素 + */ + isEmptyBlock:function (node,reg) { + if(node.nodeType != 1) + return 0; + reg = reg || new RegExp('[ \xa0\t\r\n' + domUtils.fillChar + ']', 'g'); + + if (node[browser.ie ? 'innerText' : 'textContent'].replace(reg, '').length > 0) { + return 0; + } + for (var n in dtd.$isNotEmpty) { + if (node.getElementsByTagName(n).length) { + return 0; + } + } + return 1; + }, + + /** + * 移动元素使得该元素的位置移动指定的偏移量的距离 + * @method setViewportOffset + * @param { Element } element 需要设置偏移量的元素 + * @param { Object } offset 偏移量, 形如{ left: 100, top: 50 }的一个键值对, 表示该元素将在 + * 现有的位置上向水平方向偏移offset.left的距离, 在竖直方向上偏移 + * offset.top的距离 + * @example + * ```html + *
+ * + * + * ``` + */ + setViewportOffset:function (element, offset) { + var left = parseInt(element.style.left) | 0; + var top = parseInt(element.style.top) | 0; + var rect = element.getBoundingClientRect(); + var offsetLeft = offset.left - rect.left; + var offsetTop = offset.top - rect.top; + if (offsetLeft) { + element.style.left = left + offsetLeft + 'px'; + } + if (offsetTop) { + element.style.top = top + offsetTop + 'px'; + } + }, + + /** + * 用“填充字符”填充节点 + * @method fillNode + * @private + * @param { DomDocument } doc 填充的节点所在的docment对象 + * @param { Node } node 需要填充的节点对象 + * @example + * ```html + *
+ * + * + * ``` + */ + fillNode:function (doc, node) { + var tmpNode = browser.ie ? doc.createTextNode(domUtils.fillChar) : doc.createElement('br'); + node.innerHTML = ''; + node.appendChild(tmpNode); + }, + + /** + * 把节点src的所有子节点追加到另一个节点tag上去 + * @method moveChild + * @param { Node } src 源节点, 该节点下的所有子节点将被移除 + * @param { Node } tag 目标节点, 从源节点移除的子节点将被追加到该节点下 + * @example + * ```html + *
+ * + *
+ *
+ *
+ *
+ * + * + * ``` + */ + + /** + * 把节点src的所有子节点移动到另一个节点tag上去, 可以通过dir参数控制附加的行为是“追加”还是“插入顶部” + * @method moveChild + * @param { Node } src 源节点, 该节点下的所有子节点将被移除 + * @param { Node } tag 目标节点, 从源节点移除的子节点将被附加到该节点下 + * @param { Boolean } dir 附加方式, 如果为true, 则附加进去的节点将被放到目标节点的顶部, 反之,则放到末尾 + * @example + * ```html + *
+ * + *
+ *
+ *
+ *
+ * + * + * ``` + */ + moveChild:function (src, tag, dir) { + while (src.firstChild) { + if (dir && tag.firstChild) { + tag.insertBefore(src.lastChild, tag.firstChild); + } else { + tag.appendChild(src.firstChild); + } + } + }, + + /** + * 判断节点的标签上是否不存在任何属性 + * @method hasNoAttributes + * @private + * @param { Node } node 需要检测的节点对象 + * @return { Boolean } 节点是否不包含任何属性 + * @example + * ```html + *
xxxx
+ * + * + * ``` + */ + hasNoAttributes:function (node) { + return browser.ie ? /^<\w+\s*?>/.test(node.outerHTML) : node.attributes.length == 0; + }, + + /** + * 检测节点是否是UEditor所使用的辅助节点 + * @method isCustomeNode + * @private + * @param { Node } node 需要检测的节点 + * @remind 辅助节点是指编辑器要完成工作临时添加的节点, 在输出的时候将会从编辑器内移除, 不会影响最终的结果。 + * @return { Boolean } 给定的节点是否是一个辅助节点 + */ + isCustomeNode:function (node) { + return node.nodeType == 1 && node.getAttribute('_ue_custom_node_'); + }, + + /** + * 检测节点的标签是否是给定的标签 + * @method isTagNode + * @param { Node } node 需要检测的节点对象 + * @param { String } tagName 标签 + * @return { Boolean } 节点的标签是否是给定的标签 + * @example + * ```html + *
+ * + * + * ``` + */ + isTagNode:function (node, tagNames) { + return node.nodeType == 1 && new RegExp('\\b' + node.tagName + '\\b','i').test(tagNames) + }, + + /** + * 给定一个节点数组,在通过指定的过滤器过滤后, 获取其中满足过滤条件的第一个节点 + * @method filterNodeList + * @param { Array } nodeList 需要过滤的节点数组 + * @param { Function } fn 过滤器, 对符合条件的节点, 执行结果返回true, 反之则返回false + * @return { Node | NULL } 如果找到符合过滤条件的节点, 则返回该节点, 否则返回NULL + * @example + * ```javascript + * var divNodes = document.getElementsByTagName("div"); + * divNodes = [].slice.call( divNodes, 0 ); + * + * //output: null + * console.log( UE.dom.domUtils.filterNodeList( divNodes, function ( node ) { + * return node.tagName.toLowerCase() !== 'div'; + * } ) ); + * ``` + */ + + /** + * 给定一个节点数组nodeList和一组标签名tagNames, 获取其中能够匹配标签名的节点集合中的第一个节点 + * @method filterNodeList + * @param { Array } nodeList 需要过滤的节点数组 + * @param { String } tagNames 需要匹配的标签名, 多个标签名之间用空格分割 + * @return { Node | NULL } 如果找到标签名匹配的节点, 则返回该节点, 否则返回NULL + * @example + * ```javascript + * var divNodes = document.getElementsByTagName("div"); + * divNodes = [].slice.call( divNodes, 0 ); + * + * //output: null + * console.log( UE.dom.domUtils.filterNodeList( divNodes, 'a span' ) ); + * ``` + */ + + /** + * 给定一个节点数组,在通过指定的过滤器过滤后, 如果参数forAll为true, 则会返回所有满足过滤 + * 条件的节点集合, 否则, 返回满足条件的节点集合中的第一个节点 + * @method filterNodeList + * @param { Array } nodeList 需要过滤的节点数组 + * @param { Function } fn 过滤器, 对符合条件的节点, 执行结果返回true, 反之则返回false + * @param { Boolean } forAll 是否返回整个节点数组, 如果该参数为false, 则返回节点集合中的第一个节点 + * @return { Array | Node | NULL } 如果找到符合过滤条件的节点, 则根据参数forAll的值决定返回满足 + * 过滤条件的节点数组或第一个节点, 否则返回NULL + * @example + * ```javascript + * var divNodes = document.getElementsByTagName("div"); + * divNodes = [].slice.call( divNodes, 0 ); + * + * //output: 3(假定有3个div) + * console.log( divNodes.length ); + * + * var nodes = UE.dom.domUtils.filterNodeList( divNodes, function ( node ) { + * return node.tagName.toLowerCase() === 'div'; + * }, true ); + * + * //output: 3 + * console.log( nodes.length ); + * + * var node = UE.dom.domUtils.filterNodeList( divNodes, function ( node ) { + * return node.tagName.toLowerCase() === 'div'; + * }, false ); + * + * //output: div + * console.log( node.nodeName ); + * ``` + */ + filterNodeList : function(nodelist,filter,forAll){ + var results = []; + if(!utils .isFunction(filter)){ + var str = filter; + filter = function(n){ + return utils.indexOf(utils.isArray(str) ? str:str.split(' '), n.tagName.toLowerCase()) != -1 + }; + } + utils.each(nodelist,function(n){ + filter(n) && results.push(n) + }); + return results.length == 0 ? null : results.length == 1 || !forAll ? results[0] : results + }, + + /** + * 查询给定的range选区是否在给定的node节点内,且在该节点的最末尾 + * @method isInNodeEndBoundary + * @param { UE.dom.Range } rng 需要判断的range对象, 该对象的startContainer不能为NULL + * @param node 需要检测的节点对象 + * @return { Number } 如果给定的选取range对象是在node内部的最末端, 则返回1, 否则返回0 + */ + isInNodeEndBoundary : function (rng,node){ + var start = rng.startContainer; + if(start.nodeType == 3 && rng.startOffset != start.nodeValue.length){ + return 0; + } + if(start.nodeType == 1 && rng.startOffset != start.childNodes.length){ + return 0; + } + while(start !== node){ + if(start.nextSibling){ + return 0 + }; + start = start.parentNode; + } + return 1; + }, + isBoundaryNode : function (node,dir){ + var tmp; + while(!domUtils.isBody(node)){ + tmp = node; + node = node.parentNode; + if(tmp !== node[dir]){ + return false; + } + } + return true; + }, + fillHtml : browser.ie11below ? ' ' : '
' +}; +var fillCharReg = new RegExp(domUtils.fillChar, 'g'); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/dtd.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/dtd.js new file mode 100644 index 000000000..3b44634ca --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/dtd.js @@ -0,0 +1,179 @@ +///import editor.js +///import core/dom/dom.js +///import core/utils.js +/** + * dtd html语义化的体现类 + * @constructor + * @namespace dtd + */ +var dtd = dom.dtd = (function() { + function _( s ) { + for (var k in s) { + s[k.toUpperCase()] = s[k]; + } + return s; + } + var X = utils.extend2; + var A = _({isindex:1,fieldset:1}), + B = _({input:1,button:1,select:1,textarea:1,label:1}), + C = X( _({a:1}), B ), + D = X( {iframe:1}, C ), + E = _({hr:1,ul:1,menu:1,div:1,blockquote:1,noscript:1,table:1,center:1,address:1,dir:1,pre:1,h5:1,dl:1,h4:1,noframes:1,h6:1,ol:1,h1:1,h3:1,h2:1}), + F = _({ins:1,del:1,script:1,style:1}), + G = X( _({b:1,acronym:1,bdo:1,'var':1,'#':1,abbr:1,code:1,br:1,i:1,cite:1,kbd:1,u:1,strike:1,s:1,tt:1,strong:1,q:1,samp:1,em:1,dfn:1,span:1}), F ), + H = X( _({sub:1,img:1,embed:1,object:1,sup:1,basefont:1,map:1,applet:1,font:1,big:1,small:1}), G ), + I = X( _({p:1}), H ), + J = X( _({iframe:1}), H, B ), + K = _({img:1,embed:1,noscript:1,br:1,kbd:1,center:1,button:1,basefont:1,h5:1,h4:1,samp:1,h6:1,ol:1,h1:1,h3:1,h2:1,form:1,font:1,'#':1,select:1,menu:1,ins:1,abbr:1,label:1,code:1,table:1,script:1,cite:1,input:1,iframe:1,strong:1,textarea:1,noframes:1,big:1,small:1,span:1,hr:1,sub:1,bdo:1,'var':1,div:1,object:1,sup:1,strike:1,dir:1,map:1,dl:1,applet:1,del:1,isindex:1,fieldset:1,ul:1,b:1,acronym:1,a:1,blockquote:1,i:1,u:1,s:1,tt:1,address:1,q:1,pre:1,p:1,em:1,dfn:1}), + + L = X( _({a:0}), J ),//a不能被切开,所以把他 + M = _({tr:1}), + N = _({'#':1}), + O = X( _({param:1}), K ), + P = X( _({form:1}), A, D, E, I ), + Q = _({li:1,ol:1,ul:1}), + R = _({style:1,script:1}), + S = _({base:1,link:1,meta:1,title:1}), + T = X( S, R ), + U = _({head:1,body:1}), + V = _({html:1}); + + var block = _({address:1,blockquote:1,center:1,dir:1,div:1,dl:1,fieldset:1,form:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,hr:1,isindex:1,menu:1,noframes:1,ol:1,p:1,pre:1,table:1,ul:1}), + + empty = _({area:1,base:1,basefont:1,br:1,col:1,command:1,dialog:1,embed:1,hr:1,img:1,input:1,isindex:1,keygen:1,link:1,meta:1,param:1,source:1,track:1,wbr:1}); + + return _({ + + // $ 表示自定的属性 + + // body外的元素列表. + $nonBodyContent: X( V, U, S ), + + //块结构元素列表 + $block : block, + + //内联元素列表 + $inline : L, + + $inlineWithA : X(_({a:1}),L), + + $body : X( _({script:1,style:1}), block ), + + $cdata : _({script:1,style:1}), + + //自闭和元素 + $empty : empty, + + //不是自闭合,但不能让range选中里边 + $nonChild : _({iframe:1,textarea:1}), + //列表元素列表 + $listItem : _({dd:1,dt:1,li:1}), + + //列表根元素列表 + $list: _({ul:1,ol:1,dl:1}), + + //不能认为是空的元素 + $isNotEmpty : _({table:1,ul:1,ol:1,dl:1,iframe:1,area:1,base:1,col:1,hr:1,img:1,embed:1,input:1,link:1,meta:1,param:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1}), + + //如果没有子节点就可以删除的元素列表,像span,a + $removeEmpty : _({a:1,abbr:1,acronym:1,address:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,s:1,samp:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,tt:1,u:1,'var':1}), + + $removeEmptyBlock : _({'p':1,'div':1}), + + //在table元素里的元素列表 + $tableContent : _({caption:1,col:1,colgroup:1,tbody:1,td:1,tfoot:1,th:1,thead:1,tr:1,table:1}), + //不转换的标签 + $notTransContent : _({pre:1,script:1,style:1,textarea:1}), + html: U, + head: T, + style: N, + script: N, + body: P, + base: {}, + link: {}, + meta: {}, + title: N, + col : {}, + tr : _({td:1,th:1}), + img : {}, + embed: {}, + colgroup : _({thead:1,col:1,tbody:1,tr:1,tfoot:1}), + noscript : P, + td : P, + br : {}, + th : P, + center : P, + kbd : L, + button : X( I, E ), + basefont : {}, + h5 : L, + h4 : L, + samp : L, + h6 : L, + ol : Q, + h1 : L, + h3 : L, + option : N, + h2 : L, + form : X( A, D, E, I ), + select : _({optgroup:1,option:1}), + font : L, + ins : L, + menu : Q, + abbr : L, + label : L, + table : _({thead:1,col:1,tbody:1,tr:1,colgroup:1,caption:1,tfoot:1}), + code : L, + tfoot : M, + cite : L, + li : P, + input : {}, + iframe : P, + strong : L, + textarea : N, + noframes : P, + big : L, + small : L, + //trace: + span :_({'#':1,br:1,b:1,strong:1,u:1,i:1,em:1,sub:1,sup:1,strike:1,span:1}), + hr : L, + dt : L, + sub : L, + optgroup : _({option:1}), + param : {}, + bdo : L, + 'var' : L, + div : P, + object : O, + sup : L, + dd : P, + strike : L, + area : {}, + dir : Q, + map : X( _({area:1,form:1,p:1}), A, F, E ), + applet : O, + dl : _({dt:1,dd:1}), + del : L, + isindex : {}, + fieldset : X( _({legend:1}), K ), + thead : M, + ul : Q, + acronym : L, + b : L, + a : X( _({a:1}), J ), + blockquote :X(_({td:1,tr:1,tbody:1,li:1}),P), + caption : L, + i : L, + u : L, + tbody : M, + s : L, + address : X( D, I ), + tt : L, + legend : L, + q : L, + pre : X( G, C ), + p : X(_({'a':1}),L), + em :L, + dfn : L + }); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/filternode.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/filternode.js new file mode 100644 index 000000000..6189f4391 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/filternode.js @@ -0,0 +1,130 @@ +/** + * UE过滤节点的静态方法 + * @file + */ + +/** + * UEditor公用空间,UEditor所有的功能都挂载在该空间下 + * @module UE + */ + + +/** + * 根据传入节点和过滤规则过滤相应节点 + * @module UE + * @since 1.2.6.1 + * @method filterNode + * @param { Object } root 指定root节点 + * @param { Object } rules 过滤规则json对象 + * @example + * ```javascript + * UE.filterNode(root,editor.options.filterRules); + * ``` + */ +var filterNode = UE.filterNode = function () { + function filterNode(node,rules){ + switch (node.type) { + case 'text': + break; + case 'element': + var val; + if(val = rules[node.tagName]){ + if(val === '-'){ + node.parentNode.removeChild(node) + }else if(utils.isFunction(val)){ + var parentNode = node.parentNode, + index = node.getIndex(); + val(node); + if(node.parentNode){ + if(node.children){ + for(var i = 0,ci;ci=node.children[i];){ + filterNode(ci,rules); + if(ci.parentNode){ + i++; + } + } + } + }else{ + for(var i = index,ci;ci=parentNode.children[i];){ + filterNode(ci,rules); + if(ci.parentNode){ + i++; + } + } + } + + + }else{ + var attrs = val['$']; + if(attrs && node.attrs){ + var tmpAttrs = {},tmpVal; + for(var a in attrs){ + tmpVal = node.getAttr(a); + //todo 只先对style单独处理 + if(a == 'style' && utils.isArray(attrs[a])){ + var tmpCssStyle = []; + utils.each(attrs[a],function(v){ + var tmp; + if(tmp = node.getStyle(v)){ + tmpCssStyle.push(v + ':' + tmp); + } + }); + tmpVal = tmpCssStyle.join(';') + } + if(tmpVal){ + tmpAttrs[a] = tmpVal; + } + + } + node.attrs = tmpAttrs; + } + if(node.children){ + for(var i = 0,ci;ci=node.children[i];){ + filterNode(ci,rules); + if(ci.parentNode){ + i++; + } + } + } + } + }else{ + //如果不在名单里扣出子节点并删除该节点,cdata除外 + if(dtd.$cdata[node.tagName]){ + node.parentNode.removeChild(node) + }else{ + var parentNode = node.parentNode, + index = node.getIndex(); + node.parentNode.removeChild(node,true); + for(var i = index,ci;ci=parentNode.children[i];){ + filterNode(ci,rules); + if(ci.parentNode){ + i++; + } + } + } + } + break; + case 'comment': + node.parentNode.removeChild(node) + } + + } + return function(root,rules){ + if(utils.isEmptyObject(rules)){ + return root; + } + var val; + if(val = rules['-']){ + utils.each(val.split(' '),function(k){ + rules[k] = '-' + }) + } + for(var i= 0,ci;ci=root.children[i];){ + filterNode(ci,rules); + if(ci.parentNode){ + i++; + } + } + return root; + } +}(); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/filterword.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/filterword.js new file mode 100644 index 000000000..287e0cc24 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/filterword.js @@ -0,0 +1,189 @@ +/** + * UE过滤word的静态方法 + * @file + */ + +/** + * UEditor公用空间,UEditor所有的功能都挂载在该空间下 + * @module UE + */ + + +/** + * 根据传入html字符串过滤word + * @module UE + * @since 1.2.6.1 + * @method filterWord + * @param { String } html html字符串 + * @return { String } 已过滤后的结果字符串 + * @example + * ```javascript + * UE.filterWord(html); + * ``` + */ +var filterWord = UE.filterWord = function () { + + //是否是word过来的内容 + function isWordDocument( str ) { + return /(class="?Mso|style="[^"]*\bmso\-|w:WordDocument|<(v|o):|lang=)/ig.test( str ); + } + //去掉小数 + function transUnit( v ) { + v = v.replace( /[\d.]+\w+/g, function ( m ) { + return utils.transUnitToPx(m); + } ); + return v; + } + + function filterPasteWord( str ) { + return str.replace(/[\t\r\n]+/g,' ') + .replace( //ig, "" ) + //转换图片 + .replace(/]*>[\s\S]*?.<\/v:shape>/gi,function(str){ + //opera能自己解析出image所这里直接返回空 + if(browser.opera){ + return ''; + } + try{ + //有可能是bitmap占为图,无用,直接过滤掉,主要体现在粘贴excel表格中 + if(/Bitmap/i.test(str)){ + return ''; + } + var width = str.match(/width:([ \d.]*p[tx])/i)[1], + height = str.match(/height:([ \d.]*p[tx])/i)[1], + src = str.match(/src=\s*"([^"]*)"/i)[1]; + return ''; + } catch(e){ + return ''; + } + }) + //针对wps添加的多余标签处理 + .replace(/<\/?div[^>]*>/g,'') + //去掉多余的属性 + .replace( /v:\w+=(["']?)[^'"]+\1/g, '' ) + .replace( /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|xml|meta|link|style|\w+:\w+)(?=[\s\/>]))[^>]*>/gi, "" ) + .replace( /

]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi, "

$1

" ) + //去掉多余的属性 + .replace( /\s+(class|lang|align)\s*=\s*(['"]?)([\w-]+)\2/ig, function(str,name,marks,val){ + //保留list的标示 + return name == 'class' && val == 'MsoListParagraph' ? str : '' + }) + //清除多余的font/span不能匹配 有可能是空格 + .replace( /<(font|span)[^>]*>(\s*)<\/\1>/gi, function(a,b,c){ + return c.replace(/[\t\r\n ]+/g,' ') + }) + //处理style的问题 + .replace( /(<[a-z][^>]*)\sstyle=(["'])([^\2]*?)\2/gi, function( str, tag, tmp, style ) { + var n = [], + s = style.replace( /^\s+|\s+$/, '' ) + .replace(/'/g,'\'') + .replace( /"/gi, "'" ) + .replace(/[\d.]+(cm|pt)/g,function(str){ + return utils.transUnitToPx(str) + }) + .split( /;\s*/g ); + + for ( var i = 0,v; v = s[i];i++ ) { + + var name, value, + parts = v.split( ":" ); + + if ( parts.length == 2 ) { + name = parts[0].toLowerCase(); + value = parts[1].toLowerCase(); + if(/^(background)\w*/.test(name) && value.replace(/(initial|\s)/g,'').length == 0 + || + /^(margin)\w*/.test(name) && /^0\w+$/.test(value) + ){ + continue; + } + + switch ( name ) { + case "mso-padding-alt": + case "mso-padding-top-alt": + case "mso-padding-right-alt": + case "mso-padding-bottom-alt": + case "mso-padding-left-alt": + case "mso-margin-alt": + case "mso-margin-top-alt": + case "mso-margin-right-alt": + case "mso-margin-bottom-alt": + case "mso-margin-left-alt": + //ie下会出现挤到一起的情况 + //case "mso-table-layout-alt": + case "mso-height": + case "mso-width": + case "mso-vertical-align-alt": + //trace:1819 ff下会解析出padding在table上 + if(!/htmlparser

', true); + * ``` + */ + +var htmlparser = UE.htmlparser = function (htmlstr,ignoreBlank) { + //todo 原来的方式 [^"'<>\/] 有\/就不能配对上 ') + } + html.push('') + } + //禁止指定table-width + return '
这样的标签了 + //先去掉了,加上的原因忘了,这里先记录 + var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\s\/<>]+)\s*((?:(?:"[^"]*")|(?:'[^']*')|[^"'<>])*)\/?>))/g, + re_attr = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g; + + //ie下取得的html可能会有\n存在,要去掉,在处理replace(/[\t\r\n]*/g,'');代码高量的\n不能去除 + var allowEmptyTags = { + b:1,code:1,i:1,u:1,strike:1,s:1,tt:1,strong:1,q:1,samp:1,em:1,span:1, + sub:1,img:1,sup:1,font:1,big:1,small:1,iframe:1,a:1,br:1,pre:1 + }; + htmlstr = htmlstr.replace(new RegExp(domUtils.fillChar, 'g'), ''); + if(!ignoreBlank){ + htmlstr = htmlstr.replace(new RegExp('[\\r\\t\\n'+(ignoreBlank?'':' ')+']*<\/?(\\w+)\\s*(?:[^>]*)>[\\r\\t\\n'+(ignoreBlank?'':' ')+']*','g'), function(a,b){ + //br暂时单独处理 + if(b && allowEmptyTags[b.toLowerCase()]){ + return a.replace(/(^[\n\r]+)|([\n\r]+$)/g,''); + } + return a.replace(new RegExp('^[\\r\\n'+(ignoreBlank?'':' ')+']+'),'').replace(new RegExp('[\\r\\n'+(ignoreBlank?'':' ')+']+$'),''); + }); + } + + var notTransAttrs = { + 'href':1, + 'src':1 + }; + + var uNode = UE.uNode, + needParentNode = { + 'td':'tr', + 'tr':['tbody','thead','tfoot'], + 'tbody':'table', + 'th':'tr', + 'thead':'table', + 'tfoot':'table', + 'caption':'table', + 'li':['ul', 'ol'], + 'dt':'dl', + 'dd':'dl', + 'option':'select' + }, + needChild = { + 'ol':'li', + 'ul':'li' + }; + + function text(parent, data) { + + if(needChild[parent.tagName]){ + var tmpNode = uNode.createElement(needChild[parent.tagName]); + parent.appendChild(tmpNode); + tmpNode.appendChild(uNode.createText(data)); + parent = tmpNode; + }else{ + + parent.appendChild(uNode.createText(data)); + } + } + + function element(parent, tagName, htmlattr) { + var needParentTag; + if (needParentTag = needParentNode[tagName]) { + var tmpParent = parent,hasParent; + while(tmpParent.type != 'root'){ + if(utils.isArray(needParentTag) ? utils.indexOf(needParentTag, tmpParent.tagName) != -1 : needParentTag == tmpParent.tagName){ + parent = tmpParent; + hasParent = true; + break; + } + tmpParent = tmpParent.parentNode; + } + if(!hasParent){ + parent = element(parent, utils.isArray(needParentTag) ? needParentTag[0] : needParentTag) + } + } + //按dtd处理嵌套 +// if(parent.type != 'root' && !dtd[parent.tagName][tagName]) +// parent = parent.parentNode; + var elm = new uNode({ + parentNode:parent, + type:'element', + tagName:tagName.toLowerCase(), + //是自闭合的处理一下 + children:dtd.$empty[tagName] ? null : [] + }); + //如果属性存在,处理属性 + if (htmlattr) { + var attrs = {}, match; + while (match = re_attr.exec(htmlattr)) { + attrs[match[1].toLowerCase()] = notTransAttrs[match[1].toLowerCase()] ? (match[2] || match[3] || match[4]) : utils.unhtml(match[2] || match[3] || match[4]) + } + elm.attrs = attrs; + } + //trace:3970 +// //如果parent下不能放elm +// if(dtd.$inline[parent.tagName] && dtd.$block[elm.tagName] && !dtd[parent.tagName][elm.tagName]){ +// parent = parent.parentNode; +// elm.parentNode = parent; +// } + parent.children.push(elm); + //如果是自闭合节点返回父亲节点 + return dtd.$empty[tagName] ? parent : elm + } + + function comment(parent, data) { + parent.children.push(new uNode({ + type:'comment', + data:data, + parentNode:parent + })); + } + + var match, currentIndex = 0, nextIndex = 0; + //设置根节点 + var root = new uNode({ + type:'root', + children:[] + }); + var currentParent = root; + + while (match = re_tag.exec(htmlstr)) { + currentIndex = match.index; + try{ + if (currentIndex > nextIndex) { + //text node + text(currentParent, htmlstr.slice(nextIndex, currentIndex)); + } + if (match[3]) { + + if(dtd.$cdata[currentParent.tagName]){ + text(currentParent, match[0]); + }else{ + //start tag + currentParent = element(currentParent, match[3].toLowerCase(), match[4]); + } + + + } else if (match[1]) { + if(currentParent.type != 'root'){ + if(dtd.$cdata[currentParent.tagName] && !dtd.$cdata[match[1]]){ + text(currentParent, match[0]); + }else{ + var tmpParent = currentParent; + while(currentParent.type == 'element' && currentParent.tagName != match[1].toLowerCase()){ + currentParent = currentParent.parentNode; + if(currentParent.type == 'root'){ + currentParent = tmpParent; + throw 'break' + } + } + //end tag + currentParent = currentParent.parentNode; + } + + } + + } else if (match[2]) { + //comment + comment(currentParent, match[2]) + } + }catch(e){} + + nextIndex = re_tag.lastIndex; + + } + //如果结束是文本,就有可能丢掉,所以这里手动判断一下 + //例如
  • sdfsdfsdf
  • sdfsdfsdfsdf + if (nextIndex < htmlstr.length) { + text(currentParent, htmlstr.slice(nextIndex)); + } + return root; +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/keymap.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/keymap.js new file mode 100644 index 000000000..a6a8b9e4f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/keymap.js @@ -0,0 +1,48 @@ +var keymap = UE.keymap = { + 'Backspace' : 8, + 'Tab' : 9, + 'Enter' : 13, + + 'Shift':16, + 'Control':17, + 'Alt':18, + 'CapsLock':20, + + 'Esc':27, + + 'Spacebar':32, + + 'PageUp':33, + 'PageDown':34, + 'End':35, + 'Home':36, + + 'Left':37, + 'Up':38, + 'Right':39, + 'Down':40, + + 'Insert':45, + + 'Del':46, + + 'NumLock':144, + + 'Cmd':91, + + '=':187, + '-':189, + + "b":66, + 'i':73, + //回退 + 'z':90, + 'y':89, + //粘贴 + 'v' : 86, + 'x' : 88, + + 's' : 83, + + 'n' : 78 +}; \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/loadconfig.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/loadconfig.js new file mode 100644 index 000000000..530097173 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/loadconfig.js @@ -0,0 +1,66 @@ +(function(){ + + UE.Editor.prototype.loadServerConfig = function(){ + var me = this; + setTimeout(function(){ + try{ + me.options.imageUrl && me.setOpt('serverUrl', me.options.imageUrl.replace(/^(.*[\/]).+([\.].+)$/, '$1controller$2')); + + var configUrl = me.getActionUrl('config'), + isJsonp = utils.isCrossDomainUrl(configUrl); + + /* 发出ajax请求 */ + me._serverConfigLoaded = false; + + configUrl && UE.ajax.request(configUrl,{ + 'method': 'GET', + 'dataType': isJsonp ? 'jsonp':'', + 'onsuccess':function(r){ + try { + var config = isJsonp ? r:eval("("+r.responseText+")"); + utils.extend(me.options, config); + me.fireEvent('serverConfigLoaded'); + me._serverConfigLoaded = true; + } catch (e) { + showErrorMsg(me.getLang('loadconfigFormatError')); + } + }, + 'onerror':function(){ + showErrorMsg(me.getLang('loadconfigHttpError')); + } + }); + } catch(e){ + showErrorMsg(me.getLang('loadconfigError')); + } + }); + + function showErrorMsg(msg) { + console && console.error(msg); + //me.fireEvent('showMessage', { + // 'title': msg, + // 'type': 'error' + //}); + } + }; + + UE.Editor.prototype.isServerConfigLoaded = function(){ + var me = this; + return me._serverConfigLoaded || false; + }; + + UE.Editor.prototype.afterConfigReady = function(handler){ + if (!handler || !utils.isFunction(handler)) return; + var me = this; + var readyHandler = function(){ + handler.apply(me, arguments); + me.removeListener('serverConfigLoaded', readyHandler); + }; + + if (me.isServerConfigLoaded()) { + handler.call(me, 'serverConfigLoaded'); + } else { + me.addListener('serverConfigLoaded', readyHandler); + } + }; + +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/localstorage.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/localstorage.js new file mode 100644 index 000000000..4e0db3cd4 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/localstorage.js @@ -0,0 +1,140 @@ +//存储媒介封装 +var LocalStorage = UE.LocalStorage = (function () { + + var storage = window.localStorage || getUserData() || null, + LOCAL_FILE = 'localStorage'; + + return { + + saveLocalData: function (key, data) { + + if (storage && data) { + storage.setItem(key, data); + return true; + } + + return false; + + }, + + getLocalData: function (key) { + + if (storage) { + return storage.getItem(key); + } + + return null; + + }, + + removeItem: function (key) { + + storage && storage.removeItem(key); + + } + + }; + + function getUserData() { + + var container = document.createElement("div"); + container.style.display = "none"; + + if (!container.addBehavior) { + return null; + } + + container.addBehavior("#default#userdata"); + + return { + + getItem: function (key) { + + var result = null; + + try { + document.body.appendChild(container); + container.load(LOCAL_FILE); + result = container.getAttribute(key); + document.body.removeChild(container); + } catch (e) { + } + + return result; + + }, + + setItem: function (key, value) { + + document.body.appendChild(container); + container.setAttribute(key, value); + container.save(LOCAL_FILE); + document.body.removeChild(container); + + }, + + //// 暂时没有用到 + //clear: function () { + // + // var expiresTime = new Date(); + // expiresTime.setFullYear(expiresTime.getFullYear() - 1); + // document.body.appendChild(container); + // container.expires = expiresTime.toUTCString(); + // container.save(LOCAL_FILE); + // document.body.removeChild(container); + // + //}, + + removeItem: function (key) { + + document.body.appendChild(container); + container.removeAttribute(key); + container.save(LOCAL_FILE); + document.body.removeChild(container); + + } + + }; + + } + +})(); + +(function () { + + var ROOTKEY = 'ueditor_preference'; + + UE.Editor.prototype.setPreferences = function(key,value){ + var obj = {}; + if (utils.isString(key)) { + obj[ key ] = value; + } else { + obj = key; + } + var data = LocalStorage.getLocalData(ROOTKEY); + if (data && (data = utils.str2json(data))) { + utils.extend(data, obj); + } else { + data = obj; + } + data && LocalStorage.saveLocalData(ROOTKEY, utils.json2str(data)); + }; + + UE.Editor.prototype.getPreferences = function(key){ + var data = LocalStorage.getLocalData(ROOTKEY); + if (data && (data = utils.str2json(data))) { + return key ? data[key] : data + } + return null; + }; + + UE.Editor.prototype.removePreferences = function (key) { + var data = LocalStorage.getLocalData(ROOTKEY); + if (data && (data = utils.str2json(data))) { + data[key] = undefined; + delete data[key] + } + data && LocalStorage.saveLocalData(ROOTKEY, utils.json2str(data)); + }; + +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/node.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/node.js new file mode 100644 index 000000000..8177aba54 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/node.js @@ -0,0 +1,754 @@ +/** + * 编辑器模拟的节点类 + * @file + * @module UE + * @class uNode + * @since 1.2.6.1 + */ + +/** + * UEditor公用空间,UEditor所有的功能都挂载在该空间下 + * @unfile + * @module UE + */ + +(function () { + + /** + * 编辑器模拟的节点类 + * @unfile + * @module UE + * @class uNode + */ + + /** + * 通过一个键值对,创建一个uNode对象 + * @constructor + * @param { Object } attr 传入要创建的uNode的初始属性 + * @example + * ```javascript + * var node = new uNode({ + * type:'element', + * tagName:'span', + * attrs:{style:'font-size:14px;'} + * } + * ``` + */ + var uNode = UE.uNode = function (obj) { + this.type = obj.type; + this.data = obj.data; + this.tagName = obj.tagName; + this.parentNode = obj.parentNode; + this.attrs = obj.attrs || {}; + this.children = obj.children; + }; + + var notTransAttrs = { + 'href':1, + 'src':1, + '_src':1, + '_href':1, + 'cdata_data':1 + }; + + var notTransTagName = { + style:1, + script:1 + }; + + var indentChar = ' ', + breakChar = '\n'; + + function insertLine(arr, current, begin) { + arr.push(breakChar); + return current + (begin ? 1 : -1); + } + + function insertIndent(arr, current) { + //插入缩进 + for (var i = 0; i < current; i++) { + arr.push(indentChar); + } + } + + //创建uNode的静态方法 + //支持标签和html + uNode.createElement = function (html) { + if (/[<>]/.test(html)) { + return UE.htmlparser(html).children[0] + } else { + return new uNode({ + type:'element', + children:[], + tagName:html + }) + } + }; + uNode.createText = function (data,noTrans) { + return new UE.uNode({ + type:'text', + 'data':noTrans ? data : utils.unhtml(data || '') + }) + }; + function nodeToHtml(node, arr, formatter, current) { + switch (node.type) { + case 'root': + for (var i = 0, ci; ci = node.children[i++];) { + //插入新行 + if (formatter && ci.type == 'element' && !dtd.$inlineWithA[ci.tagName] && i > 1) { + insertLine(arr, current, true); + insertIndent(arr, current) + } + nodeToHtml(ci, arr, formatter, current) + } + break; + case 'text': + isText(node, arr); + break; + case 'element': + isElement(node, arr, formatter, current); + break; + case 'comment': + isComment(node, arr, formatter); + } + return arr; + } + + function isText(node, arr) { + if(node.parentNode.tagName == 'pre'){ + //源码模式下输入html标签,不能做转换处理,直接输出 + arr.push(node.data) + }else{ + arr.push(notTransTagName[node.parentNode.tagName] ? utils.html(node.data) : node.data.replace(/[ ]{2}/g,'  ')) + } + + } + + function isElement(node, arr, formatter, current) { + var attrhtml = ''; + if (node.attrs) { + attrhtml = []; + var attrs = node.attrs; + for (var a in attrs) { + //这里就针对 + //

    '

    + //这里边的\"做转换,要不用innerHTML直接被截断了,属性src + //有可能做的不够 + attrhtml.push(a + (attrs[a] !== undefined ? '="' + (notTransAttrs[a] ? utils.html(attrs[a]).replace(/["]/g, function (a) { + return '"' + }) : utils.unhtml(attrs[a])) + '"' : '')) + } + attrhtml = attrhtml.join(' '); + } + arr.push('<' + node.tagName + + (attrhtml ? ' ' + attrhtml : '') + + (dtd.$empty[node.tagName] ? '\/' : '' ) + '>' + ); + //插入新行 + if (formatter && !dtd.$inlineWithA[node.tagName] && node.tagName != 'pre') { + if(node.children && node.children.length){ + current = insertLine(arr, current, true); + insertIndent(arr, current) + } + + } + if (node.children && node.children.length) { + for (var i = 0, ci; ci = node.children[i++];) { + if (formatter && ci.type == 'element' && !dtd.$inlineWithA[ci.tagName] && i > 1) { + insertLine(arr, current); + insertIndent(arr, current) + } + nodeToHtml(ci, arr, formatter, current) + } + } + if (!dtd.$empty[node.tagName]) { + if (formatter && !dtd.$inlineWithA[node.tagName] && node.tagName != 'pre') { + + if(node.children && node.children.length){ + current = insertLine(arr, current); + insertIndent(arr, current) + } + } + arr.push('<\/' + node.tagName + '>'); + } + + } + + function isComment(node, arr) { + arr.push(''); + } + + function getNodeById(root, id) { + var node; + if (root.type == 'element' && root.getAttr('id') == id) { + return root; + } + if (root.children && root.children.length) { + for (var i = 0, ci; ci = root.children[i++];) { + if (node = getNodeById(ci, id)) { + return node; + } + } + } + } + + function getNodesByTagName(node, tagName, arr) { + if (node.type == 'element' && node.tagName == tagName) { + arr.push(node); + } + if (node.children && node.children.length) { + for (var i = 0, ci; ci = node.children[i++];) { + getNodesByTagName(ci, tagName, arr) + } + } + } + function nodeTraversal(root,fn){ + if(root.children && root.children.length){ + for(var i= 0,ci;ci=root.children[i];){ + nodeTraversal(ci,fn); + //ci被替换的情况,这里就不再走 fn了 + if(ci.parentNode ){ + if(ci.children && ci.children.length){ + fn(ci) + } + if(ci.parentNode) i++ + } + } + }else{ + fn(root) + } + + } + uNode.prototype = { + + /** + * 当前节点对象,转换成html文本 + * @method toHtml + * @return { String } 返回转换后的html字符串 + * @example + * ```javascript + * node.toHtml(); + * ``` + */ + + /** + * 当前节点对象,转换成html文本 + * @method toHtml + * @param { Boolean } formatter 是否格式化返回值 + * @return { String } 返回转换后的html字符串 + * @example + * ```javascript + * node.toHtml( true ); + * ``` + */ + toHtml:function (formatter) { + var arr = []; + nodeToHtml(this, arr, formatter, 0); + return arr.join('') + }, + + /** + * 获取节点的html内容 + * @method innerHTML + * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点 + * @return { String } 返回节点的html内容 + * @example + * ```javascript + * var htmlstr = node.innerHTML(); + * ``` + */ + + /** + * 设置节点的html内容 + * @method innerHTML + * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点 + * @param { String } htmlstr 传入要设置的html内容 + * @return { UE.uNode } 返回节点本身 + * @example + * ```javascript + * node.innerHTML('text'); + * ``` + */ + innerHTML:function (htmlstr) { + if (this.type != 'element' || dtd.$empty[this.tagName]) { + return this; + } + if (utils.isString(htmlstr)) { + if(this.children){ + for (var i = 0, ci; ci = this.children[i++];) { + ci.parentNode = null; + } + } + this.children = []; + var tmpRoot = UE.htmlparser(htmlstr); + for (var i = 0, ci; ci = tmpRoot.children[i++];) { + this.children.push(ci); + ci.parentNode = this; + } + return this; + } else { + var tmpRoot = new UE.uNode({ + type:'root', + children:this.children + }); + return tmpRoot.toHtml(); + } + }, + + /** + * 获取节点的纯文本内容 + * @method innerText + * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点 + * @return { String } 返回节点的存文本内容 + * @example + * ```javascript + * var textStr = node.innerText(); + * ``` + */ + + /** + * 设置节点的纯文本内容 + * @method innerText + * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点 + * @param { String } textStr 传入要设置的文本内容 + * @return { UE.uNode } 返回节点本身 + * @example + * ```javascript + * node.innerText('text'); + * ``` + */ + innerText:function (textStr,noTrans) { + if (this.type != 'element' || dtd.$empty[this.tagName]) { + return this; + } + if (textStr) { + if(this.children){ + for (var i = 0, ci; ci = this.children[i++];) { + ci.parentNode = null; + } + } + this.children = []; + this.appendChild(uNode.createText(textStr,noTrans)); + return this; + } else { + return this.toHtml().replace(/<[^>]+>/g, ''); + } + }, + + /** + * 获取当前对象的data属性 + * @method getData + * @return { Object } 若节点的type值是elemenet,返回空字符串,否则返回节点的data属性 + * @example + * ```javascript + * node.getData(); + * ``` + */ + getData:function () { + if (this.type == 'element') + return ''; + return this.data + }, + + /** + * 获取当前节点下的第一个子节点 + * @method firstChild + * @return { UE.uNode } 返回第一个子节点 + * @example + * ```javascript + * node.firstChild(); //返回第一个子节点 + * ``` + */ + firstChild:function () { +// if (this.type != 'element' || dtd.$empty[this.tagName]) { +// return this; +// } + return this.children ? this.children[0] : null; + }, + + /** + * 获取当前节点下的最后一个子节点 + * @method lastChild + * @return { UE.uNode } 返回最后一个子节点 + * @example + * ```javascript + * node.lastChild(); //返回最后一个子节点 + * ``` + */ + lastChild:function () { +// if (this.type != 'element' || dtd.$empty[this.tagName] ) { +// return this; +// } + return this.children ? this.children[this.children.length - 1] : null; + }, + + /** + * 获取和当前节点有相同父亲节点的前一个节点 + * @method previousSibling + * @return { UE.uNode } 返回前一个节点 + * @example + * ```javascript + * node.children[2].previousSibling(); //返回子节点node.children[1] + * ``` + */ + previousSibling : function(){ + var parent = this.parentNode; + for (var i = 0, ci; ci = parent.children[i]; i++) { + if (ci === this) { + return i == 0 ? null : parent.children[i-1]; + } + } + + }, + + /** + * 获取和当前节点有相同父亲节点的后一个节点 + * @method nextSibling + * @return { UE.uNode } 返回后一个节点,找不到返回null + * @example + * ```javascript + * node.children[2].nextSibling(); //如果有,返回子节点node.children[3] + * ``` + */ + nextSibling : function(){ + var parent = this.parentNode; + for (var i = 0, ci; ci = parent.children[i++];) { + if (ci === this) { + return parent.children[i]; + } + } + }, + + /** + * 用新的节点替换当前节点 + * @method replaceChild + * @param { UE.uNode } target 要替换成该节点参数 + * @param { UE.uNode } source 要被替换掉的节点 + * @return { UE.uNode } 返回替换之后的节点对象 + * @example + * ```javascript + * node.replaceChild(newNode, childNode); //用newNode替换childNode,childNode是node的子节点 + * ``` + */ + replaceChild:function (target, source) { + if (this.children) { + if(target.parentNode){ + target.parentNode.removeChild(target); + } + for (var i = 0, ci; ci = this.children[i]; i++) { + if (ci === source) { + this.children.splice(i, 1, target); + source.parentNode = null; + target.parentNode = this; + return target; + } + } + } + }, + + /** + * 在节点的子节点列表最后位置插入一个节点 + * @method appendChild + * @param { UE.uNode } node 要插入的节点 + * @return { UE.uNode } 返回刚插入的子节点 + * @example + * ```javascript + * node.appendChild( newNode ); //在node内插入子节点newNode + * ``` + */ + appendChild:function (node) { + if (this.type == 'root' || (this.type == 'element' && !dtd.$empty[this.tagName])) { + if (!this.children) { + this.children = [] + } + if(node.parentNode){ + node.parentNode.removeChild(node); + } + for (var i = 0, ci; ci = this.children[i]; i++) { + if (ci === node) { + this.children.splice(i, 1); + break; + } + } + this.children.push(node); + node.parentNode = this; + return node; + } + + + }, + + /** + * 在传入节点的前面插入一个节点 + * @method insertBefore + * @param { UE.uNode } target 要插入的节点 + * @param { UE.uNode } source 在该参数节点前面插入 + * @return { UE.uNode } 返回刚插入的子节点 + * @example + * ```javascript + * node.parentNode.insertBefore(newNode, node); //在node节点后面插入newNode + * ``` + */ + insertBefore:function (target, source) { + if (this.children) { + if(target.parentNode){ + target.parentNode.removeChild(target); + } + for (var i = 0, ci; ci = this.children[i]; i++) { + if (ci === source) { + this.children.splice(i, 0, target); + target.parentNode = this; + return target; + } + } + + } + }, + + /** + * 在传入节点的后面插入一个节点 + * @method insertAfter + * @param { UE.uNode } target 要插入的节点 + * @param { UE.uNode } source 在该参数节点后面插入 + * @return { UE.uNode } 返回刚插入的子节点 + * @example + * ```javascript + * node.parentNode.insertAfter(newNode, node); //在node节点后面插入newNode + * ``` + */ + insertAfter:function (target, source) { + if (this.children) { + if(target.parentNode){ + target.parentNode.removeChild(target); + } + for (var i = 0, ci; ci = this.children[i]; i++) { + if (ci === source) { + this.children.splice(i + 1, 0, target); + target.parentNode = this; + return target; + } + + } + } + }, + + /** + * 从当前节点的子节点列表中,移除节点 + * @method removeChild + * @param { UE.uNode } node 要移除的节点引用 + * @param { Boolean } keepChildren 是否保留移除节点的子节点,若传入true,自动把移除节点的子节点插入到移除的位置 + * @return { * } 返回刚移除的子节点 + * @example + * ```javascript + * node.removeChild(childNode,true); //在node的子节点列表中移除child节点,并且吧child的子节点插入到移除的位置 + * ``` + */ + removeChild:function (node,keepChildren) { + if (this.children) { + for (var i = 0, ci; ci = this.children[i]; i++) { + if (ci === node) { + this.children.splice(i, 1); + ci.parentNode = null; + if(keepChildren && ci.children && ci.children.length){ + for(var j= 0,cj;cj=ci.children[j];j++){ + this.children.splice(i+j,0,cj); + cj.parentNode = this; + + } + } + return ci; + } + } + } + }, + + /** + * 获取当前节点所代表的元素属性,即获取attrs对象下的属性值 + * @method getAttr + * @param { String } attrName 要获取的属性名称 + * @return { * } 返回attrs对象下的属性值 + * @example + * ```javascript + * node.getAttr('title'); + * ``` + */ + getAttr:function (attrName) { + return this.attrs && this.attrs[attrName.toLowerCase()] + }, + + /** + * 设置当前节点所代表的元素属性,即设置attrs对象下的属性值 + * @method setAttr + * @param { String } attrName 要设置的属性名称 + * @param { * } attrVal 要设置的属性值,类型视设置的属性而定 + * @return { * } 返回attrs对象下的属性值 + * @example + * ```javascript + * node.setAttr('title','标题'); + * ``` + */ + setAttr:function (attrName, attrVal) { + if (!attrName) { + delete this.attrs; + return; + } + if(!this.attrs){ + this.attrs = {}; + } + if (utils.isObject(attrName)) { + for (var a in attrName) { + if (!attrName[a]) { + delete this.attrs[a] + } else { + this.attrs[a.toLowerCase()] = attrName[a]; + } + } + } else { + if (!attrVal) { + delete this.attrs[attrName] + } else { + this.attrs[attrName.toLowerCase()] = attrVal; + } + + } + }, + + /** + * 获取当前节点在父节点下的位置索引 + * @method getIndex + * @return { Number } 返回索引数值,如果没有父节点,返回-1 + * @example + * ```javascript + * node.getIndex(); + * ``` + */ + getIndex:function(){ + var parent = this.parentNode; + for(var i= 0,ci;ci=parent.children[i];i++){ + if(ci === this){ + return i; + } + } + return -1; + }, + + /** + * 在当前节点下,根据id查找节点 + * @method getNodeById + * @param { String } id 要查找的id + * @return { UE.uNode } 返回找到的节点 + * @example + * ```javascript + * node.getNodeById('textId'); + * ``` + */ + getNodeById:function (id) { + var node; + if (this.children && this.children.length) { + for (var i = 0, ci; ci = this.children[i++];) { + if (node = getNodeById(ci, id)) { + return node; + } + } + } + }, + + /** + * 在当前节点下,根据元素名称查找节点列表 + * @method getNodesByTagName + * @param { String } tagNames 要查找的元素名称 + * @return { Array } 返回找到的节点列表 + * @example + * ```javascript + * node.getNodesByTagName('span'); + * ``` + */ + getNodesByTagName:function (tagNames) { + tagNames = utils.trim(tagNames).replace(/[ ]{2,}/g, ' ').split(' '); + var arr = [], me = this; + utils.each(tagNames, function (tagName) { + if (me.children && me.children.length) { + for (var i = 0, ci; ci = me.children[i++];) { + getNodesByTagName(ci, tagName, arr) + } + } + }); + return arr; + }, + + /** + * 根据样式名称,获取节点的样式值 + * @method getStyle + * @param { String } name 要获取的样式名称 + * @return { String } 返回样式值 + * @example + * ```javascript + * node.getStyle('font-size'); + * ``` + */ + getStyle:function (name) { + var cssStyle = this.getAttr('style'); + if (!cssStyle) { + return '' + } + var reg = new RegExp('(^|;)\\s*' + name + ':([^;]+)','i'); + var match = cssStyle.match(reg); + if (match && match[0]) { + return match[2] + } + return ''; + }, + + /** + * 给节点设置样式 + * @method setStyle + * @param { String } name 要设置的的样式名称 + * @param { String } val 要设置的的样值 + * @example + * ```javascript + * node.setStyle('font-size', '12px'); + * ``` + */ + setStyle:function (name, val) { + function exec(name, val) { + var reg = new RegExp('(^|;)\\s*' + name + ':([^;]+;?)', 'gi'); + cssStyle = cssStyle.replace(reg, '$1'); + if (val) { + cssStyle = name + ':' + utils.unhtml(val) + ';' + cssStyle + } + + } + + var cssStyle = this.getAttr('style'); + if (!cssStyle) { + cssStyle = ''; + } + if (utils.isObject(name)) { + for (var a in name) { + exec(a, name[a]) + } + } else { + exec(name, val) + } + this.setAttr('style', utils.trim(cssStyle)) + }, + + /** + * 传入一个函数,递归遍历当前节点下的所有节点 + * @method traversal + * @param { Function } fn 遍历到节点的时,传入节点作为参数,运行此函数 + * @example + * ```javascript + * traversal(node, function(){ + * console.log(node.type); + * }); + * ``` + */ + traversal:function(fn){ + if(this.children && this.children.length){ + nodeTraversal(this,fn); + } + return this; + } + } +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/plugin.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/plugin.js new file mode 100644 index 000000000..ec6b5e570 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/plugin.js @@ -0,0 +1,81 @@ +/** + * Created with JetBrains PhpStorm. + * User: campaign + * Date: 10/8/13 + * Time: 6:15 PM + * To change this template use File | Settings | File Templates. + */ +UE.plugin = function(){ + var _plugins = {}; + return { + register : function(pluginName,fn,oldOptionName,afterDisabled){ + if(oldOptionName && utils.isFunction(oldOptionName)){ + afterDisabled = oldOptionName; + oldOptionName = null + } + _plugins[pluginName] = { + optionName : oldOptionName || pluginName, + execFn : fn, + //当插件被禁用时执行 + afterDisabled : afterDisabled + } + }, + load : function(editor){ + utils.each(_plugins,function(plugin){ + var _export = plugin.execFn.call(editor); + if(editor.options[plugin.optionName] !== false){ + if(_export){ + //后边需要再做扩展 + utils.each(_export,function(v,k){ + switch(k.toLowerCase()){ + case 'shortcutkey': + editor.addshortcutkey(v); + break; + case 'bindevents': + utils.each(v,function(fn,eventName){ + editor.addListener(eventName,fn); + }); + break; + case 'bindmultievents': + utils.each(utils.isArray(v) ? v:[v],function(event){ + var types = utils.trim(event.type).split(/\s+/); + utils.each(types,function(eventName){ + editor.addListener(eventName, event.handler); + }); + }); + break; + case 'commands': + utils.each(v,function(execFn,execName){ + editor.commands[execName] = execFn + }); + break; + case 'outputrule': + editor.addOutputRule(v); + break; + case 'inputrule': + editor.addInputRule(v); + break; + case 'defaultoptions': + editor.setOpt(v) + } + }) + } + + }else if(plugin.afterDisabled){ + plugin.afterDisabled.call(editor) + } + + }); + //向下兼容 + utils.each(UE.plugins,function(plugin){ + plugin.call(editor); + }); + }, + run : function(pluginName,editor){ + var plugin = _plugins[pluginName]; + if(plugin){ + plugin.exeFn.call(editor) + } + } + } +}(); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/core/utils.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/utils.js new file mode 100644 index 000000000..1117d0c4e --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/core/utils.js @@ -0,0 +1,1210 @@ +/** + * 工具函数包 + * @file + * @module UE.utils + * @since 1.2.6.1 + */ + +/** + * UEditor封装使用的静态工具函数 + * @module UE.utils + * @unfile + */ + +var utils = UE.utils = { + + /** + * 用给定的迭代器遍历对象 + * @method each + * @param { Object } obj 需要遍历的对象 + * @param { Function } iterator 迭代器, 该方法接受两个参数, 第一个参数是当前所处理的value, 第二个参数是当前遍历对象的key + * @example + * ```javascript + * var demoObj = { + * key1: 1, + * key2: 2 + * }; + * + * //output: key1: 1, key2: 2 + * UE.utils.each( demoObj, funciton ( value, key ) { + * + * console.log( key + ":" + value ); + * + * } ); + * ``` + */ + + /** + * 用给定的迭代器遍历数组或类数组对象 + * @method each + * @param { Array } array 需要遍历的数组或者类数组 + * @param { Function } iterator 迭代器, 该方法接受两个参数, 第一个参数是当前所处理的value, 第二个参数是当前遍历对象的key + * @example + * ```javascript + * var divs = document.getElmentByTagNames( "div" ); + * + * //output: 0: DIV, 1: DIV ... + * UE.utils.each( divs, funciton ( value, key ) { + * + * console.log( key + ":" + value.tagName ); + * + * } ); + * ``` + */ + each : function(obj, iterator, context) { + if (obj == null) return; + if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if(iterator.call(context, obj[i], i, obj) === false) + return false; + } + } else { + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + if(iterator.call(context, obj[key], key, obj) === false) + return false; + } + } + } + }, + + /** + * 以给定对象作为原型创建一个新对象 + * @method makeInstance + * @param { Object } protoObject 该对象将作为新创建对象的原型 + * @return { Object } 新的对象, 该对象的原型是给定的protoObject对象 + * @example + * ```javascript + * + * var protoObject = { sayHello: function () { console.log('Hello UEditor!'); } }; + * + * var newObject = UE.utils.makeInstance( protoObject ); + * //output: Hello UEditor! + * newObject.sayHello(); + * ``` + */ + makeInstance:function (obj) { + var noop = new Function(); + noop.prototype = obj; + obj = new noop; + noop.prototype = null; + return obj; + }, + + /** + * 将source对象中的属性扩展到target对象上 + * @method extend + * @remind 该方法将强制把source对象上的属性复制到target对象上 + * @see UE.utils.extend(Object,Object,Boolean) + * @param { Object } target 目标对象, 新的属性将附加到该对象上 + * @param { Object } source 源对象, 该对象的属性会被附加到target对象上 + * @return { Object } 返回target对象 + * @example + * ```javascript + * + * var target = { name: 'target', sex: 1 }, + * source = { name: 'source', age: 17 }; + * + * UE.utils.extend( target, source ); + * + * //output: { name: 'source', sex: 1, age: 17 } + * console.log( target ); + * + * ``` + */ + + /** + * 将source对象中的属性扩展到target对象上, 根据指定的isKeepTarget值决定是否保留目标对象中与 + * 源对象属性名相同的属性值。 + * @method extend + * @param { Object } target 目标对象, 新的属性将附加到该对象上 + * @param { Object } source 源对象, 该对象的属性会被附加到target对象上 + * @param { Boolean } isKeepTarget 是否保留目标对象中与源对象中属性名相同的属性 + * @return { Object } 返回target对象 + * @example + * ```javascript + * + * var target = { name: 'target', sex: 1 }, + * source = { name: 'source', age: 17 }; + * + * UE.utils.extend( target, source, true ); + * + * //output: { name: 'target', sex: 1, age: 17 } + * console.log( target ); + * + * ``` + */ + extend:function (t, s, b) { + if (s) { + for (var k in s) { + if (!b || !t.hasOwnProperty(k)) { + t[k] = s[k]; + } + } + } + return t; + }, + + /** + * 将给定的多个对象的属性复制到目标对象target上 + * @method extend2 + * @remind 该方法将强制把源对象上的属性复制到target对象上 + * @remind 该方法支持两个及以上的参数, 从第二个参数开始, 其属性都会被复制到第一个参数上。 如果遇到同名的属性, + * 将会覆盖掉之前的值。 + * @param { Object } target 目标对象, 新的属性将附加到该对象上 + * @param { Object... } source 源对象, 支持多个对象, 该对象的属性会被附加到target对象上 + * @return { Object } 返回target对象 + * @example + * ```javascript + * + * var target = {}, + * source1 = { name: 'source', age: 17 }, + * source2 = { title: 'dev' }; + * + * UE.utils.extend2( target, source1, source2 ); + * + * //output: { name: 'source', age: 17, title: 'dev' } + * console.log( target ); + * + * ``` + */ + extend2:function (t) { + var a = arguments; + for (var i = 1; i < a.length; i++) { + var x = a[i]; + for (var k in x) { + if (!t.hasOwnProperty(k)) { + t[k] = x[k]; + } + } + } + return t; + }, + + /** + * 模拟继承机制, 使得subClass继承自superClass + * @method inherits + * @param { Object } subClass 子类对象 + * @param { Object } superClass 超类对象 + * @warning 该方法只能让subClass继承超类的原型, subClass对象自身的属性和方法不会被继承 + * @return { Object } 继承superClass后的子类对象 + * @example + * ```javascript + * function SuperClass(){ + * this.name = "小李"; + * } + * + * SuperClass.prototype = { + * hello:function(str){ + * console.log(this.name + str); + * } + * } + * + * function SubClass(){ + * this.name = "小张"; + * } + * + * UE.utils.inherits(SubClass,SuperClass); + * + * var sub = new SubClass(); + * //output: '小张早上好! + * sub.hello("早上好!"); + * ``` + */ + inherits:function (subClass, superClass) { + var oldP = subClass.prototype, + newP = utils.makeInstance(superClass.prototype); + utils.extend(newP, oldP, true); + subClass.prototype = newP; + return (newP.constructor = subClass); + }, + + /** + * 用指定的context对象作为函数fn的上下文 + * @method bind + * @param { Function } fn 需要绑定上下文的函数对象 + * @param { Object } content 函数fn新的上下文对象 + * @return { Function } 一个新的函数, 该函数作为原始函数fn的代理, 将完成fn的上下文调换工作。 + * @example + * ```javascript + * + * var name = 'window', + * newTest = null; + * + * function test () { + * console.log( this.name ); + * } + * + * newTest = UE.utils.bind( test, { name: 'object' } ); + * + * //output: object + * newTest(); + * + * //output: window + * test(); + * + * ``` + */ + bind:function (fn, context) { + return function () { + return fn.apply(context, arguments); + }; + }, + + /** + * 创建延迟指定时间后执行的函数fn + * @method defer + * @param { Function } fn 需要延迟执行的函数对象 + * @param { int } delay 延迟的时间, 单位是毫秒 + * @warning 该方法的时间控制是不精确的,仅仅只能保证函数的执行是在给定的时间之后, + * 而不能保证刚好到达延迟时间时执行。 + * @return { Function } 目标函数fn的代理函数, 只有执行该函数才能起到延时效果 + * @example + * ```javascript + * var start = 0; + * + * function test(){ + * console.log( new Date() - start ); + * } + * + * var testDefer = UE.utils.defer( test, 1000 ); + * // + * start = new Date(); + * //output: (大约在1000毫秒之后输出) 1000 + * testDefer(); + * ``` + */ + + /** + * 创建延迟指定时间后执行的函数fn, 如果在延迟时间内再次执行该方法, 将会根据指定的exclusion的值, + * 决定是否取消前一次函数的执行, 如果exclusion的值为true, 则取消执行,反之,将继续执行前一个方法。 + * @method defer + * @param { Function } fn 需要延迟执行的函数对象 + * @param { int } delay 延迟的时间, 单位是毫秒 + * @param { Boolean } exclusion 如果在延迟时间内再次执行该函数,该值将决定是否取消执行前一次函数的执行, + * 值为true表示取消执行, 反之则将在执行前一次函数之后才执行本次函数调用。 + * @warning 该方法的时间控制是不精确的,仅仅只能保证函数的执行是在给定的时间之后, + * 而不能保证刚好到达延迟时间时执行。 + * @return { Function } 目标函数fn的代理函数, 只有执行该函数才能起到延时效果 + * @example + * ```javascript + * + * function test(){ + * console.log(1); + * } + * + * var testDefer = UE.utils.defer( test, 1000, true ); + * + * //output: (两次调用仅有一次输出) 1 + * testDefer(); + * testDefer(); + * ``` + */ + defer:function (fn, delay, exclusion) { + var timerID; + return function () { + if (exclusion) { + clearTimeout(timerID); + } + timerID = setTimeout(fn, delay); + }; + }, + + /** + * 获取元素item在数组array中首次出现的位置, 如果未找到item, 则返回-1 + * @method indexOf + * @remind 该方法的匹配过程使用的是恒等“===” + * @param { Array } array 需要查找的数组对象 + * @param { * } item 需要在目标数组中查找的值 + * @return { int } 返回item在目标数组array中首次出现的位置, 如果在数组中未找到item, 则返回-1 + * @example + * ```javascript + * var item = 1, + * arr = [ 3, 4, 6, 8, 1, 1, 2 ]; + * + * //output: 4 + * console.log( UE.utils.indexOf( arr, item ) ); + * ``` + */ + + /** + * 获取元素item数组array中首次出现的位置, 如果未找到item, 则返回-1。通过start的值可以指定搜索的起始位置。 + * @method indexOf + * @remind 该方法的匹配过程使用的是恒等“===” + * @param { Array } array 需要查找的数组对象 + * @param { * } item 需要在目标数组中查找的值 + * @param { int } start 搜索的起始位置 + * @return { int } 返回item在目标数组array中的start位置之后首次出现的位置, 如果在数组中未找到item, 则返回-1 + * @example + * ```javascript + * var item = 1, + * arr = [ 3, 4, 6, 8, 1, 2, 8, 3, 2, 1, 1, 4 ]; + * + * //output: 9 + * console.log( UE.utils.indexOf( arr, item, 5 ) ); + * ``` + */ + indexOf:function (array, item, start) { + var index = -1; + start = this.isNumber(start) ? start : 0; + this.each(array, function (v, i) { + if (i >= start && v === item) { + index = i; + return false; + } + }); + return index; + }, + + /** + * 移除数组array中所有的元素item + * @method removeItem + * @param { Array } array 要移除元素的目标数组 + * @param { * } item 将要被移除的元素 + * @remind 该方法的匹配过程使用的是恒等“===” + * @example + * ```javascript + * var arr = [ 4, 5, 7, 1, 3, 4, 6 ]; + * + * UE.utils.removeItem( arr, 4 ); + * //output: [ 5, 7, 1, 3, 6 ] + * console.log( arr ); + * + * ``` + */ + removeItem:function (array, item) { + for (var i = 0, l = array.length; i < l; i++) { + if (array[i] === item) { + array.splice(i, 1); + i--; + } + } + }, + + /** + * 删除字符串str的首尾空格 + * @method trim + * @param { String } str 需要删除首尾空格的字符串 + * @return { String } 删除了首尾的空格后的字符串 + * @example + * ```javascript + * + * var str = " UEdtior "; + * + * //output: 9 + * console.log( str.length ); + * + * //output: 7 + * console.log( UE.utils.trim( " UEdtior " ).length ); + * + * //output: 9 + * console.log( str.length ); + * + * ``` + */ + trim:function (str) { + return str.replace(/(^[ \t\n\r]+)|([ \t\n\r]+$)/g, ''); + }, + + /** + * 将字符串str以','分隔成数组后,将该数组转换成哈希对象, 其生成的hash对象的key为数组中的元素, value为1 + * @method listToMap + * @warning 该方法在生成的hash对象中,会为每一个key同时生成一个另一个全大写的key。 + * @param { String } str 该字符串将被以','分割为数组, 然后进行转化 + * @return { Object } 转化之后的hash对象 + * @example + * ```javascript + * + * //output: Object {UEdtior: 1, UEDTIOR: 1, Hello: 1, HELLO: 1} + * console.log( UE.utils.listToMap( 'UEdtior,Hello' ) ); + * + * ``` + */ + + /** + * 将字符串数组转换成哈希对象, 其生成的hash对象的key为数组中的元素, value为1 + * @method listToMap + * @warning 该方法在生成的hash对象中,会为每一个key同时生成一个另一个全大写的key。 + * @param { Array } arr 字符串数组 + * @return { Object } 转化之后的hash对象 + * @example + * ```javascript + * + * //output: Object {UEdtior: 1, UEDTIOR: 1, Hello: 1, HELLO: 1} + * console.log( UE.utils.listToMap( [ 'UEdtior', 'Hello' ] ) ); + * + * ``` + */ + listToMap:function (list) { + if (!list)return {}; + list = utils.isArray(list) ? list : list.split(','); + for (var i = 0, ci, obj = {}; ci = list[i++];) { + obj[ci.toUpperCase()] = obj[ci] = 1; + } + return obj; + }, + + /** + * 将str中的html符号转义,将转义“',&,<,",>”五个字符 + * @method unhtml + * @param { String } str 需要转义的字符串 + * @return { String } 转义后的字符串 + * @example + * ```javascript + * var html = '&'; + * + * //output: <body>&</body> + * console.log( UE.utils.unhtml( html ) ); + * + * ``` + */ + unhtml:function (str, reg) { + return str ? str.replace(reg || /[&<">'](?:(amp|lt|quot|gt|#39|nbsp|#\d+);)?/g, function (a, b) { + if (b) { + return a; + } else { + return { + '<':'<', + '&':'&', + '"':'"', + '>':'>', + "'":''' + }[a] + } + + }) : ''; + }, + /** + * 将url中的html字符转义, 仅转义 ', ", <, > 四个字符 + * @param { String } str 需要转义的字符串 + * @param { RegExp } reg 自定义的正则 + * @return { String } 转义后的字符串 + */ + unhtmlForUrl:function (str, reg) { + return str ? str.replace(reg || /[<">']/g, function (a) { + return { + '<':'<', + '&':'&', + '"':'"', + '>':'>', + "'":''' + }[a] + + }) : ''; + }, + + /** + * 将str中的转义字符还原成html字符 + * @see UE.utils.unhtml(String); + * @method html + * @param { String } str 需要逆转义的字符串 + * @return { String } 逆转义后的字符串 + * @example + * ```javascript + * + * var str = '<body>&</body>'; + * + * //output: & + * console.log( UE.utils.html( str ) ); + * + * ``` + */ + html:function (str) { + return str ? str.replace(/&((g|l|quo)t|amp|#39|nbsp);/g, function (m) { + return { + '<':'<', + '&':'&', + '"':'"', + '>':'>', + ''':"'", + ' ':' ' + }[m] + }) : ''; + }, + + /** + * 将css样式转换为驼峰的形式 + * @method cssStyleToDomStyle + * @param { String } cssName 需要转换的css样式名 + * @return { String } 转换成驼峰形式后的css样式名 + * @example + * ```javascript + * + * var str = 'border-top'; + * + * //output: borderTop + * console.log( UE.utils.cssStyleToDomStyle( str ) ); + * + * ``` + */ + cssStyleToDomStyle:function () { + var test = document.createElement('div').style, + cache = { + 'float':test.cssFloat != undefined ? 'cssFloat' : test.styleFloat != undefined ? 'styleFloat' : 'float' + }; + + return function (cssName) { + return cache[cssName] || (cache[cssName] = cssName.toLowerCase().replace(/-./g, function (match) { + return match.charAt(1).toUpperCase(); + })); + }; + }(), + + /** + * 动态加载文件到doc中 + * @method loadFile + * @param { DomDocument } document 需要加载资源文件的文档对象 + * @param { Object } options 加载资源文件的属性集合, 取值请参考代码示例 + * @example + * ```javascript + * + * UE.utils.loadFile( document, { + * src:"test.js", + * tag:"script", + * type:"text/javascript", + * defer:"defer" + * } ); + * + * ``` + */ + + /** + * 动态加载文件到doc中,加载成功后执行的回调函数fn + * @method loadFile + * @param { DomDocument } document 需要加载资源文件的文档对象 + * @param { Object } options 加载资源文件的属性集合, 该集合支持的值是script标签和style标签支持的所有属性。 + * @param { Function } fn 资源文件加载成功之后执行的回调 + * @warning 对于在同一个文档中多次加载同一URL的文件, 该方法会在第一次加载之后缓存该请求, + * 在此之后的所有同一URL的请求, 将会直接触发回调。 + * @example + * ```javascript + * + * UE.utils.loadFile( document, { + * src:"test.js", + * tag:"script", + * type:"text/javascript", + * defer:"defer" + * }, function () { + * console.log('加载成功'); + * } ); + * + * ``` + */ + loadFile:function () { + var tmpList = []; + + function getItem(doc, obj) { + try { + for (var i = 0, ci; ci = tmpList[i++];) { + if (ci.doc === doc && ci.url == (obj.src || obj.href)) { + return ci; + } + } + } catch (e) { + return null; + } + + } + + return function (doc, obj, fn) { + var item = getItem(doc, obj); + if (item) { + if (item.ready) { + fn && fn(); + } else { + item.funs.push(fn) + } + return; + } + tmpList.push({ + doc:doc, + url:obj.src || obj.href, + funs:[fn] + }); + if (!doc.body) { + var html = []; + for (var p in obj) { + if (p == 'tag')continue; + html.push(p + '="' + obj[p] + '"') + } + doc.write('<' + obj.tag + ' ' + html.join(' ') + ' >'); + return; + } + if (obj.id && doc.getElementById(obj.id)) { + return; + } + var element = doc.createElement(obj.tag); + delete obj.tag; + for (var p in obj) { + element.setAttribute(p, obj[p]); + } + element.onload = element.onreadystatechange = function () { + if (!this.readyState || /loaded|complete/.test(this.readyState)) { + item = getItem(doc, obj); + if (item.funs.length > 0) { + item.ready = 1; + for (var fi; fi = item.funs.pop();) { + fi(); + } + } + element.onload = element.onreadystatechange = null; + } + }; + element.onerror = function () { + throw Error('The load ' + (obj.href || obj.src) + ' fails,check the url settings of file ueditor.config.js ') + }; + doc.getElementsByTagName("head")[0].appendChild(element); + } + }(), + + /** + * 判断obj对象是否为空 + * @method isEmptyObject + * @param { * } obj 需要判断的对象 + * @remind 如果判断的对象是NULL, 将直接返回true, 如果是数组且为空, 返回true, 如果是字符串, 且字符串为空, + * 返回true, 如果是普通对象, 且该对象没有任何实例属性, 返回true + * @return { Boolean } 对象是否为空 + * @example + * ```javascript + * + * //output: true + * console.log( UE.utils.isEmptyObject( {} ) ); + * + * //output: true + * console.log( UE.utils.isEmptyObject( [] ) ); + * + * //output: true + * console.log( UE.utils.isEmptyObject( "" ) ); + * + * //output: false + * console.log( UE.utils.isEmptyObject( { key: 1 } ) ); + * + * //output: false + * console.log( UE.utils.isEmptyObject( [1] ) ); + * + * //output: false + * console.log( UE.utils.isEmptyObject( "1" ) ); + * + * ``` + */ + isEmptyObject:function (obj) { + if (obj == null) return true; + if (this.isArray(obj) || this.isString(obj)) return obj.length === 0; + for (var key in obj) if (obj.hasOwnProperty(key)) return false; + return true; + }, + + /** + * 把rgb格式的颜色值转换成16进制格式 + * @method fixColor + * @param { String } rgb格式的颜色值 + * @param { String } + * @example + * rgb(255,255,255) => "#ffffff" + */ + fixColor:function (name, value) { + if (/color/i.test(name) && /rgba?/.test(value)) { + var array = value.split(","); + if (array.length > 3) + return ""; + value = "#"; + for (var i = 0, color; color = array[i++];) { + color = parseInt(color.replace(/[^\d]/gi, ''), 10).toString(16); + value += color.length == 1 ? "0" + color : color; + } + value = value.toUpperCase(); + } + return value; + }, + /** + * 只针对border,padding,margin做了处理,因为性能问题 + * @public + * @function + * @param {String} val style字符串 + */ + optCss:function (val) { + var padding, margin, border; + val = val.replace(/(padding|margin|border)\-([^:]+):([^;]+);?/gi, function (str, key, name, val) { + if (val.split(' ').length == 1) { + switch (key) { + case 'padding': + !padding && (padding = {}); + padding[name] = val; + return ''; + case 'margin': + !margin && (margin = {}); + margin[name] = val; + return ''; + case 'border': + return val == 'initial' ? '' : str; + } + } + return str; + }); + + function opt(obj, name) { + if (!obj) { + return ''; + } + var t = obj.top , b = obj.bottom, l = obj.left, r = obj.right, val = ''; + if (!t || !l || !b || !r) { + for (var p in obj) { + val += ';' + name + '-' + p + ':' + obj[p] + ';'; + } + } else { + val += ';' + name + ':' + + (t == b && b == l && l == r ? t : + t == b && l == r ? (t + ' ' + l) : + l == r ? (t + ' ' + l + ' ' + b) : (t + ' ' + r + ' ' + b + ' ' + l)) + ';' + } + return val; + } + + val += opt(padding, 'padding') + opt(margin, 'margin'); + return val.replace(/^[ \n\r\t;]*|[ \n\r\t]*$/, '').replace(/;([ \n\r\t]+)|\1;/g, ';') + .replace(/(&((l|g)t|quot|#39))?;{2,}/g, function (a, b) { + return b ? b + ";;" : ';' + }); + }, + + /** + * 克隆对象 + * @method clone + * @param { Object } source 源对象 + * @return { Object } source的一个副本 + */ + + /** + * 深度克隆对象,将source的属性克隆到target对象, 会覆盖target重名的属性。 + * @method clone + * @param { Object } source 源对象 + * @param { Object } target 目标对象 + * @return { Object } 附加了source对象所有属性的target对象 + */ + clone:function (source, target) { + var tmp; + target = target || {}; + for (var i in source) { + if (source.hasOwnProperty(i)) { + tmp = source[i]; + if (typeof tmp == 'object') { + target[i] = utils.isArray(tmp) ? [] : {}; + utils.clone(source[i], target[i]) + } else { + target[i] = tmp; + } + } + } + return target; + }, + + /** + * 把cm/pt为单位的值转换为px为单位的值 + * @method transUnitToPx + * @param { String } 待转换的带单位的字符串 + * @return { String } 转换为px为计量单位的值的字符串 + * @example + * ```javascript + * + * //output: 500px + * console.log( UE.utils.transUnitToPx( '20cm' ) ); + * + * //output: 27px + * console.log( UE.utils.transUnitToPx( '20pt' ) ); + * + * ``` + */ + transUnitToPx:function (val) { + if (!/(pt|cm)/.test(val)) { + return val + } + var unit; + val.replace(/([\d.]+)(\w+)/, function (str, v, u) { + val = v; + unit = u; + }); + switch (unit) { + case 'cm': + val = parseFloat(val) * 25; + break; + case 'pt': + val = Math.round(parseFloat(val) * 96 / 72); + } + return val + (val ? 'px' : ''); + }, + + /** + * 在dom树ready之后执行给定的回调函数 + * @method domReady + * @remind 如果在执行该方法的时候, dom树已经ready, 那么回调函数将立刻执行 + * @param { Function } fn dom树ready之后的回调函数 + * @example + * ```javascript + * + * UE.utils.domReady( function () { + * + * console.log('123'); + * + * } ); + * + * ``` + */ + domReady:function () { + + var fnArr = []; + + function doReady(doc) { + //确保onready只执行一次 + doc.isReady = true; + for (var ci; ci = fnArr.pop(); ci()) { + } + } + + return function (onready, win) { + win = win || window; + var doc = win.document; + onready && fnArr.push(onready); + if (doc.readyState === "complete") { + doReady(doc); + } else { + doc.isReady && doReady(doc); + if (browser.ie && browser.version != 11) { + (function () { + if (doc.isReady) return; + try { + doc.documentElement.doScroll("left"); + } catch (error) { + setTimeout(arguments.callee, 0); + return; + } + doReady(doc); + })(); + win.attachEvent('onload', function () { + doReady(doc) + }); + } else { + doc.addEventListener("DOMContentLoaded", function () { + doc.removeEventListener("DOMContentLoaded", arguments.callee, false); + doReady(doc); + }, false); + win.addEventListener('load', function () { + doReady(doc) + }, false); + } + } + + } + }(), + + /** + * 动态添加css样式 + * @method cssRule + * @param { String } 节点名称 + * @grammar UE.utils.cssRule('添加的样式的节点名称',['样式','放到哪个document上']) + * @grammar UE.utils.cssRule('body','body{background:#ccc}') => null //给body添加背景颜色 + * @grammar UE.utils.cssRule('body') =>样式的字符串 //取得key值为body的样式的内容,如果没有找到key值先关的样式将返回空,例如刚才那个背景颜色,将返回 body{background:#ccc} + * @grammar UE.utils.cssRule('body',document) => 返回指定key的样式,并且指定是哪个document + * @grammar UE.utils.cssRule('body','') =>null //清空给定的key值的背景颜色 + */ + cssRule:browser.ie && browser.version != 11 ? function (key, style, doc) { + var indexList, index; + if(style === undefined || style && style.nodeType && style.nodeType == 9){ + //获取样式 + doc = style && style.nodeType && style.nodeType == 9 ? style : (doc || document); + indexList = doc.indexList || (doc.indexList = {}); + index = indexList[key]; + if(index !== undefined){ + return doc.styleSheets[index].cssText + } + return undefined; + } + doc = doc || document; + indexList = doc.indexList || (doc.indexList = {}); + index = indexList[key]; + //清除样式 + if(style === ''){ + if(index!== undefined){ + doc.styleSheets[index].cssText = ''; + delete indexList[key]; + return true + } + return false; + } + + //添加样式 + if(index!== undefined){ + sheetStyle = doc.styleSheets[index]; + }else{ + sheetStyle = doc.createStyleSheet('', index = doc.styleSheets.length); + indexList[key] = index; + } + sheetStyle.cssText = style; + }: function (key, style, doc) { + var head, node; + if(style === undefined || style && style.nodeType && style.nodeType == 9){ + //获取样式 + doc = style && style.nodeType && style.nodeType == 9 ? style : (doc || document); + node = doc.getElementById(key); + return node ? node.innerHTML : undefined; + } + doc = doc || document; + node = doc.getElementById(key); + + //清除样式 + if(style === ''){ + if(node){ + node.parentNode.removeChild(node); + return true + } + return false; + } + + //添加样式 + if(node){ + node.innerHTML = style; + }else{ + node = doc.createElement('style'); + node.id = key; + node.innerHTML = style; + doc.getElementsByTagName('head')[0].appendChild(node); + } + }, + sort:function(array,compareFn){ + compareFn = compareFn || function(item1, item2){ return item1.localeCompare(item2);}; + for(var i= 0,len = array.length; i 0){ + var t = array[i]; + array[i] = array[j]; + array[j] = t; + } + } + } + return array; + }, + serializeParam:function (json) { + var strArr = []; + for (var i in json) { + //忽略默认的几个参数 + if(i=="method" || i=="timeout" || i=="async") continue; + //传递过来的对象和函数不在提交之列 + if (!((typeof json[i]).toLowerCase() == "function" || (typeof json[i]).toLowerCase() == "object")) { + strArr.push( encodeURIComponent(i) + "="+encodeURIComponent(json[i]) ); + } else if (utils.isArray(json[i])) { + //支持传数组内容 + for(var j = 0; j < json[i].length; j++) { + strArr.push( encodeURIComponent(i) + "[]="+encodeURIComponent(json[i][j]) ); + } + } + } + return strArr.join("&"); + }, + formatUrl:function (url) { + var u = url.replace(/&&/g, '&'); + u = u.replace(/\?&/g, '?'); + u = u.replace(/&$/g, ''); + u = u.replace(/&#/g, '#'); + u = u.replace(/&+/g, '&'); + return u; + }, + isCrossDomainUrl:function (url) { + var a = document.createElement('a'); + a.href = url; + if (browser.ie) { + a.href = a.href; + } + return !(a.protocol == location.protocol && a.hostname == location.hostname && + (a.port == location.port || (a.port == '80' && location.port == '') || (a.port == '' && location.port == '80'))); + }, + clearEmptyAttrs : function(obj){ + for(var p in obj){ + if(obj[p] === ''){ + delete obj[p] + } + } + return obj; + }, + str2json : function(s){ + + if (!utils.isString(s)) return null; + if (window.JSON) { + return JSON.parse(s); + } else { + return (new Function("return " + utils.trim(s || '')))(); + } + + }, + json2str : (function(){ + + if (window.JSON) { + + return JSON.stringify; + + } else { + + var escapeMap = { + "\b": '\\b', + "\t": '\\t', + "\n": '\\n', + "\f": '\\f', + "\r": '\\r', + '"' : '\\"', + "\\": '\\\\' + }; + + function encodeString(source) { + if (/["\\\x00-\x1f]/.test(source)) { + source = source.replace( + /["\\\x00-\x1f]/g, + function (match) { + var c = escapeMap[match]; + if (c) { + return c; + } + c = match.charCodeAt(); + return "\\u00" + + Math.floor(c / 16).toString(16) + + (c % 16).toString(16); + }); + } + return '"' + source + '"'; + } + + function encodeArray(source) { + var result = ["["], + l = source.length, + preComma, i, item; + + for (i = 0; i < l; i++) { + item = source[i]; + + switch (typeof item) { + case "undefined": + case "function": + case "unknown": + break; + default: + if(preComma) { + result.push(','); + } + result.push(utils.json2str(item)); + preComma = 1; + } + } + result.push("]"); + return result.join(""); + } + + function pad(source) { + return source < 10 ? '0' + source : source; + } + + function encodeDate(source){ + return '"' + source.getFullYear() + "-" + + pad(source.getMonth() + 1) + "-" + + pad(source.getDate()) + "T" + + pad(source.getHours()) + ":" + + pad(source.getMinutes()) + ":" + + pad(source.getSeconds()) + '"'; + } + + return function (value) { + switch (typeof value) { + case 'undefined': + return 'undefined'; + + case 'number': + return isFinite(value) ? String(value) : "null"; + + case 'string': + return encodeString(value); + + case 'boolean': + return String(value); + + default: + if (value === null) { + return 'null'; + } else if (utils.isArray(value)) { + return encodeArray(value); + } else if (utils.isDate(value)) { + return encodeDate(value); + } else { + var result = ['{'], + encode = utils.json2str, + preComma, + item; + + for (var key in value) { + if (Object.prototype.hasOwnProperty.call(value, key)) { + item = value[key]; + switch (typeof item) { + case 'undefined': + case 'unknown': + case 'function': + break; + default: + if (preComma) { + result.push(','); + } + preComma = 1; + result.push(encode(key) + ':' + encode(item)); + } + } + } + result.push('}'); + return result.join(''); + } + } + }; + } + + })() + +}; +/** + * 判断给定的对象是否是字符串 + * @method isString + * @param { * } object 需要判断的对象 + * @return { Boolean } 给定的对象是否是字符串 + */ + +/** + * 判断给定的对象是否是数组 + * @method isArray + * @param { * } object 需要判断的对象 + * @return { Boolean } 给定的对象是否是数组 + */ + +/** + * 判断给定的对象是否是一个Function + * @method isFunction + * @param { * } object 需要判断的对象 + * @return { Boolean } 给定的对象是否是Function + */ + +/** + * 判断给定的对象是否是Number + * @method isNumber + * @param { * } object 需要判断的对象 + * @return { Boolean } 给定的对象是否是Number + */ + +/** + * 判断给定的对象是否是一个正则表达式 + * @method isRegExp + * @param { * } object 需要判断的对象 + * @return { Boolean } 给定的对象是否是正则表达式 + */ + +/** + * 判断给定的对象是否是一个普通对象 + * @method isObject + * @param { * } object 需要判断的对象 + * @return { Boolean } 给定的对象是否是普通对象 + */ +utils.each(['String', 'Function', 'Array', 'Number', 'RegExp', 'Object', 'Date'], function (v) { + UE.utils['is' + v] = function (obj) { + return Object.prototype.toString.apply(obj) == '[object ' + v + ']'; + } +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/editor.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/editor.js new file mode 100644 index 000000000..153de0bf7 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/editor.js @@ -0,0 +1,21 @@ +UEDITOR_CONFIG = window.UEDITOR_CONFIG || {}; + +var baidu = window.baidu || {}; + +window.baidu = baidu; + +window.UE = baidu.editor = window.UE || {}; + +UE.plugins = {}; + +UE.commands = {}; + +UE.instants = {}; + +UE.I18N = {}; + +UE._customizeUI = {}; + +UE.version = "1.4.3"; + +var dom = UE.dom = {}; \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/anchor.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/anchor.js new file mode 100644 index 000000000..5fcaabf62 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/anchor.js @@ -0,0 +1,85 @@ +/** + * 锚点插件,为UEditor提供插入锚点支持 + * @file + * @since 1.2.6.1 + */ +UE.plugin.register('anchor', function (){ + + return { + bindEvents:{ + 'ready':function(){ + utils.cssRule('anchor', + '.anchorclass{background: url(\'' + + this.options.themePath + + this.options.theme +'/images/anchor.gif\') no-repeat scroll left center transparent;cursor: auto;display: inline-block;height: 16px;width: 15px;}', + this.document); + } + }, + outputRule: function(root){ + utils.each(root.getNodesByTagName('img'),function(a){ + var val; + if(val = a.getAttr('anchorname')){ + a.tagName = 'a'; + a.setAttr({ + anchorname : '', + name : val, + 'class' : '' + }) + } + }) + }, + inputRule:function(root){ + utils.each(root.getNodesByTagName('a'),function(a){ + var val; + if((val = a.getAttr('name')) && !a.getAttr('href')){ + a.tagName = 'img'; + a.setAttr({ + anchorname :a.getAttr('name'), + 'class' : 'anchorclass' + }); + a.setAttr('name') + + } + }) + + }, + commands:{ + /** + * 插入锚点 + * @command anchor + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } name 锚点名称字符串 + * @example + * ```javascript + * //editor 是编辑器实例 + * editor.execCommand('anchor', 'anchor1'); + * ``` + */ + 'anchor':{ + execCommand:function (cmd, name) { + var range = this.selection.getRange(),img = range.getClosedNode(); + if (img && img.getAttribute('anchorname')) { + if (name) { + img.setAttribute('anchorname', name); + } else { + range.setStartBefore(img).setCursor(); + domUtils.remove(img); + } + } else { + if (name) { + //只在选区的开始插入 + var anchor = this.document.createElement('img'); + range.collapse(true); + domUtils.setAttributes(anchor,{ + 'anchorname':name, + 'class':'anchorclass' + }); + range.insertNode(anchor).setStartAfter(anchor).setCursor(false,true); + } + } + } + } + } + } +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autofloat.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autofloat.js new file mode 100644 index 000000000..f23ace24d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autofloat.js @@ -0,0 +1,135 @@ +///import core +///commands 悬浮工具栏 +///commandsName AutoFloat,autoFloatEnabled +///commandsTitle 悬浮工具栏 +/** + * modified by chengchao01 + * 注意: 引入此功能后,在IE6下会将body的背景图片覆盖掉! + */ +UE.plugins['autofloat'] = function() { + var me = this, + lang = me.getLang(); + me.setOpt({ + topOffset:0 + }); + var optsAutoFloatEnabled = me.options.autoFloatEnabled !== false, + topOffset = me.options.topOffset; + + + //如果不固定toolbar的位置,则直接退出 + if(!optsAutoFloatEnabled){ + return; + } + var uiUtils = UE.ui.uiUtils, + LteIE6 = browser.ie && browser.version <= 6, + quirks = browser.quirks; + + function checkHasUI(){ + if(!UE.ui){ + alert(lang.autofloatMsg); + return 0; + } + return 1; + } + function fixIE6FixedPos(){ + var docStyle = document.body.style; + docStyle.backgroundImage = 'url("about:blank")'; + docStyle.backgroundAttachment = 'fixed'; + } + var bakCssText, + placeHolder = document.createElement('div'), + toolbarBox,orgTop, + getPosition, + flag =true; //ie7模式下需要偏移 + function setFloating(){ + var toobarBoxPos = domUtils.getXY(toolbarBox), + origalFloat = domUtils.getComputedStyle(toolbarBox,'position'), + origalLeft = domUtils.getComputedStyle(toolbarBox,'left'); + toolbarBox.style.width = toolbarBox.offsetWidth + 'px'; + toolbarBox.style.zIndex = me.options.zIndex * 1 + 1; + toolbarBox.parentNode.insertBefore(placeHolder, toolbarBox); + if (LteIE6 || (quirks && browser.ie)) { + if(toolbarBox.style.position != 'absolute'){ + toolbarBox.style.position = 'absolute'; + } + toolbarBox.style.top = (document.body.scrollTop||document.documentElement.scrollTop) - orgTop + topOffset + 'px'; + } else { + if (browser.ie7Compat && flag) { + flag = false; + toolbarBox.style.left = domUtils.getXY(toolbarBox).x - document.documentElement.getBoundingClientRect().left+2 + 'px'; + } + if(toolbarBox.style.position != 'fixed'){ + toolbarBox.style.position = 'fixed'; + toolbarBox.style.top = topOffset +"px"; + ((origalFloat == 'absolute' || origalFloat == 'relative') && parseFloat(origalLeft)) && (toolbarBox.style.left = toobarBoxPos.x + 'px'); + } + } + } + function unsetFloating(){ + flag = true; + if(placeHolder.parentNode){ + placeHolder.parentNode.removeChild(placeHolder); + } + + toolbarBox.style.cssText = bakCssText; + } + + function updateFloating(){ + var rect3 = getPosition(me.container); + var offset=me.options.toolbarTopOffset||0; + if (rect3.top < 0 && rect3.bottom - toolbarBox.offsetHeight > offset) { + setFloating(); + }else{ + unsetFloating(); + } + } + var defer_updateFloating = utils.defer(function(){ + updateFloating(); + },browser.ie ? 200 : 100,true); + + me.addListener('destroy',function(){ + domUtils.un(window, ['scroll','resize'], updateFloating); + me.removeListener('keydown', defer_updateFloating); + }); + + me.addListener('ready', function(){ + if(checkHasUI(me)){ + //加载了ui组件,但在new时,没有加载ui,导致编辑器实例上没有ui类,所以这里做判断 + if(!me.ui){ + return; + } + getPosition = uiUtils.getClientRect; + toolbarBox = me.ui.getDom('toolbarbox'); + orgTop = getPosition(toolbarBox).top; + bakCssText = toolbarBox.style.cssText; + placeHolder.style.height = toolbarBox.offsetHeight + 'px'; + if(LteIE6){ + fixIE6FixedPos(); + } + domUtils.on(window, ['scroll','resize'], updateFloating); + me.addListener('keydown', defer_updateFloating); + + me.addListener('beforefullscreenchange', function (t, enabled){ + if (enabled) { + unsetFloating(); + } + }); + me.addListener('fullscreenchanged', function (t, enabled){ + if (!enabled) { + updateFloating(); + } + }); + me.addListener('sourcemodechanged', function (t, enabled){ + setTimeout(function (){ + updateFloating(); + },0); + }); + me.addListener("clearDoc",function(){ + setTimeout(function(){ + updateFloating(); + },0); + + }) + } + }); +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autoheight.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autoheight.js new file mode 100644 index 000000000..f684c2c4b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autoheight.js @@ -0,0 +1,115 @@ +///import core +///commands 当输入内容超过编辑器高度时,编辑器自动增高 +///commandsName AutoHeight,autoHeightEnabled +///commandsTitle 自动增高 +/** + * @description 自动伸展 + * @author zhanyi + */ +UE.plugins['autoheight'] = function () { + var me = this; + //提供开关,就算加载也可以关闭 + me.autoHeightEnabled = me.options.autoHeightEnabled !== false; + if (!me.autoHeightEnabled) { + return; + } + + var bakOverflow, + lastHeight = 0, + options = me.options, + currentHeight, + timer; + + function adjustHeight() { + var me = this; + clearTimeout(timer); + if(isFullscreen)return; + if (!me.queryCommandState || me.queryCommandState && me.queryCommandState('source') != 1) { + timer = setTimeout(function(){ + + var node = me.body.lastChild; + while(node && node.nodeType != 1){ + node = node.previousSibling; + } + if(node && node.nodeType == 1){ + node.style.clear = 'both'; + currentHeight = Math.max(domUtils.getXY(node).y + node.offsetHeight + 25 ,Math.max(options.minFrameHeight, options.initialFrameHeight)) ; + if (currentHeight != lastHeight) { + if (currentHeight !== parseInt(me.iframe.parentNode.style.height)) { + me.iframe.parentNode.style.height = currentHeight + 'px'; + } + me.body.style.height = currentHeight + 'px'; + lastHeight = currentHeight; + } + domUtils.removeStyle(node,'clear'); + } + + + },50) + } + } + var isFullscreen; + me.addListener('fullscreenchanged',function(cmd,f){ + isFullscreen = f + }); + me.addListener('destroy', function () { + me.removeListener('contentchange afterinserthtml keyup mouseup',adjustHeight) + }); + me.enableAutoHeight = function () { + var me = this; + if (!me.autoHeightEnabled) { + return; + } + var doc = me.document; + me.autoHeightEnabled = true; + bakOverflow = doc.body.style.overflowY; + doc.body.style.overflowY = 'hidden'; + me.addListener('contentchange afterinserthtml keyup mouseup',adjustHeight); + //ff不给事件算得不对 + + setTimeout(function () { + adjustHeight.call(me); + }, browser.gecko ? 100 : 0); + me.fireEvent('autoheightchanged', me.autoHeightEnabled); + }; + me.disableAutoHeight = function () { + + me.body.style.overflowY = bakOverflow || ''; + + me.removeListener('contentchange', adjustHeight); + me.removeListener('keyup', adjustHeight); + me.removeListener('mouseup', adjustHeight); + me.autoHeightEnabled = false; + me.fireEvent('autoheightchanged', me.autoHeightEnabled); + }; + + me.on('setHeight',function(){ + me.disableAutoHeight() + }); + me.addListener('ready', function () { + me.enableAutoHeight(); + //trace:1764 + var timer; + domUtils.on(browser.ie ? me.body : me.document, browser.webkit ? 'dragover' : 'drop', function () { + clearTimeout(timer); + timer = setTimeout(function () { + //trace:3681 + adjustHeight.call(me); + }, 100); + + }); + //修复内容过多时,回到顶部,顶部内容被工具栏遮挡问题 + var lastScrollY; + window.onscroll = function(){ + if(lastScrollY === null){ + lastScrollY = this.scrollY + }else if(this.scrollY == 0 && lastScrollY != 0){ + me.window.scrollTo(0,0); + lastScrollY = null; + } + } + }); + + +}; + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autolink.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autolink.js new file mode 100644 index 000000000..7197aae6a --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autolink.js @@ -0,0 +1,177 @@ +///import core +///commands 为非ie浏览器自动添加a标签 +///commandsName AutoLink +///commandsTitle 自动增加链接 +/** + * @description 为非ie浏览器自动添加a标签 + * @author zhanyi + */ + +UE.plugin.register('autolink',function(){ + var cont = 0; + + return !browser.ie ? { + + bindEvents:{ + 'reset' : function(){ + cont = 0; + }, + 'keydown':function(type, evt) { + var me = this; + var keyCode = evt.keyCode || evt.which; + + if (keyCode == 32 || keyCode == 13) { + + var sel = me.selection.getNative(), + range = sel.getRangeAt(0).cloneRange(), + offset, + charCode; + + var start = range.startContainer; + while (start.nodeType == 1 && range.startOffset > 0) { + start = range.startContainer.childNodes[range.startOffset - 1]; + if (!start){ + break; + } + range.setStart(start, start.nodeType == 1 ? start.childNodes.length : start.nodeValue.length); + range.collapse(true); + start = range.startContainer; + } + + do{ + if (range.startOffset == 0) { + start = range.startContainer.previousSibling; + + while (start && start.nodeType == 1) { + start = start.lastChild; + } + if (!start || domUtils.isFillChar(start)){ + break; + } + offset = start.nodeValue.length; + } else { + start = range.startContainer; + offset = range.startOffset; + } + range.setStart(start, offset - 1); + charCode = range.toString().charCodeAt(0); + } while (charCode != 160 && charCode != 32); + + if (range.toString().replace(new RegExp(domUtils.fillChar, 'g'), '').match(/(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i)) { + while(range.toString().length){ + if(/^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i.test(range.toString())){ + break; + } + try{ + range.setStart(range.startContainer,range.startOffset+1); + }catch(e){ + //trace:2121 + var start = range.startContainer; + while(!(next = start.nextSibling)){ + if(domUtils.isBody(start)){ + return; + } + start = start.parentNode; + + } + range.setStart(next,0); + + } + + } + //range的开始边界已经在a标签里的不再处理 + if(domUtils.findParentByTagName(range.startContainer,'a',true)){ + return; + } + var a = me.document.createElement('a'),text = me.document.createTextNode(' '),href; + + me.undoManger && me.undoManger.save(); + a.appendChild(range.extractContents()); + a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g,''); + href = a.getAttribute("href").replace(new RegExp(domUtils.fillChar,'g'),''); + href = /^(?:https?:\/\/)/ig.test(href) ? href : "http://"+ href; + a.setAttribute('_src',utils.html(href)); + a.href = utils.html(href); + + range.insertNode(a); + a.parentNode.insertBefore(text, a.nextSibling); + range.setStart(text, 0); + range.collapse(true); + sel.removeAllRanges(); + sel.addRange(range); + me.undoManger && me.undoManger.save(); + } + } + } + } + }:{} + },function(){ + var keyCodes = { + 37:1, 38:1, 39:1, 40:1, + 13:1,32:1 + }; + function checkIsCludeLink(node){ + if(node.nodeType == 3){ + return null + } + if(node.nodeName == 'A'){ + return node; + } + var lastChild = node.lastChild; + + while(lastChild){ + if(lastChild.nodeName == 'A'){ + return lastChild; + } + if(lastChild.nodeType == 3){ + if(domUtils.isWhitespace(lastChild)){ + lastChild = lastChild.previousSibling; + continue; + } + return null + } + lastChild = lastChild.lastChild; + } + } + browser.ie && this.addListener('keyup',function(cmd,evt){ + var me = this,keyCode = evt.keyCode; + if(keyCodes[keyCode]){ + var rng = me.selection.getRange(); + var start = rng.startContainer; + + if(keyCode == 13){ + while(start && !domUtils.isBody(start) && !domUtils.isBlockElm(start)){ + start = start.parentNode; + } + if(start && !domUtils.isBody(start) && start.nodeName == 'P'){ + var pre = start.previousSibling; + if(pre && pre.nodeType == 1){ + var pre = checkIsCludeLink(pre); + if(pre && !pre.getAttribute('_href')){ + domUtils.remove(pre,true); + } + } + } + }else if(keyCode == 32 ){ + if(start.nodeType == 3 && /^\s$/.test(start.nodeValue)){ + start = start.previousSibling; + if(start && start.nodeName == 'A' && !start.getAttribute('_href')){ + domUtils.remove(start,true); + } + } + }else { + start = domUtils.findParentByTagName(start,'a',true); + if(start && !start.getAttribute('_href')){ + var bk = rng.createBookmark(); + + domUtils.remove(start,true); + rng.moveToBookmark(bk).select(true) + } + } + + } + + + }); + } +); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autosave.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autosave.js new file mode 100644 index 000000000..cea38ee79 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autosave.js @@ -0,0 +1,129 @@ +UE.plugin.register('autosave', function (){ + + var me = this, + //无限循环保护 + lastSaveTime = new Date(), + //最小保存间隔时间 + MIN_TIME = 20, + //auto save key + saveKey = null; + + function save ( editor ) { + + var saveData; + + if ( new Date() - lastSaveTime < MIN_TIME ) { + return; + } + + if ( !editor.hasContents() ) { + //这里不能调用命令来删除, 会造成事件死循环 + saveKey && me.removePreferences( saveKey ); + return; + } + + lastSaveTime = new Date(); + + editor._saveFlag = null; + + saveData = me.body.innerHTML; + + if ( editor.fireEvent( "beforeautosave", { + content: saveData + } ) === false ) { + return; + } + + me.setPreferences( saveKey, saveData ); + + editor.fireEvent( "afterautosave", { + content: saveData + } ); + + } + + return { + defaultOptions: { + //默认间隔时间 + saveInterval: 500 + }, + bindEvents:{ + 'ready':function(){ + + var _suffix = "-drafts-data", + key = null; + + if ( me.key ) { + key = me.key + _suffix; + } else { + key = ( me.container.parentNode.id || 'ue-common' ) + _suffix; + } + + //页面地址+编辑器ID 保持唯一 + saveKey = ( location.protocol + location.host + location.pathname ).replace( /[.:\/]/g, '_' ) + key; + + }, + + 'contentchange': function () { + + if ( !saveKey ) { + return; + } + + if ( me._saveFlag ) { + window.clearTimeout( me._saveFlag ); + } + + if ( me.options.saveInterval > 0 ) { + + me._saveFlag = window.setTimeout( function () { + + save( me ); + + }, me.options.saveInterval ); + + } else { + + save(me); + + } + + + } + }, + commands:{ + 'clearlocaldata':{ + execCommand:function (cmd, name) { + if ( saveKey && me.getPreferences( saveKey ) ) { + me.removePreferences( saveKey ) + } + }, + notNeedUndo: true, + ignoreContentChange:true + }, + + 'getlocaldata':{ + execCommand:function (cmd, name) { + return saveKey ? me.getPreferences( saveKey ) || '' : ''; + }, + notNeedUndo: true, + ignoreContentChange:true + }, + + 'drafts':{ + execCommand:function (cmd, name) { + if ( saveKey ) { + me.body.innerHTML = me.getPreferences( saveKey ) || '

    '+domUtils.fillHtml+'

    '; + me.focus(true); + } + }, + queryCommandState: function () { + return saveKey ? ( me.getPreferences( saveKey ) === null ? -1 : 0 ) : -1; + }, + notNeedUndo: true, + ignoreContentChange:true + } + } + } + +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autosubmit.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autosubmit.js new file mode 100644 index 000000000..a6b7a0faf --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autosubmit.js @@ -0,0 +1,39 @@ +/** + * 快捷键提交 + * @file + * @since 1.2.6.1 + */ + +/** + * 提交表单 + * @command autosubmit + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'autosubmit' ); + * ``` + */ + +UE.plugin.register('autosubmit',function(){ + return { + shortcutkey:{ + "autosubmit":"ctrl+13" //手动提交 + }, + commands:{ + 'autosubmit':{ + execCommand:function () { + var me=this, + form = domUtils.findParentByTagName(me.iframe,"form", false); + if (form){ + if(me.fireEvent("beforesubmit")===false){ + return; + } + me.sync(); + form.submit(); + } + } + } + } + } +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autotypeset.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autotypeset.js new file mode 100644 index 000000000..76b0b72c3 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autotypeset.js @@ -0,0 +1,321 @@ +/** + * 自动排版 + * @file + * @since 1.2.6.1 + */ + +/** + * 对当前编辑器的内容执行自动排版, 排版的行为根据config配置文件里的“autotypeset”选项进行控制。 + * @command autotypeset + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'autotypeset' ); + * ``` + */ + +UE.plugins['autotypeset'] = function(){ + + this.setOpt({'autotypeset': { + mergeEmptyline: true, //合并空行 + removeClass: true, //去掉冗余的class + removeEmptyline: false, //去掉空行 + textAlign:"left", //段落的排版方式,可以是 left,right,center,justify 去掉这个属性表示不执行排版 + imageBlockLine: 'center', //图片的浮动方式,独占一行剧中,左右浮动,默认: center,left,right,none 去掉这个属性表示不执行排版 + pasteFilter: false, //根据规则过滤没事粘贴进来的内容 + clearFontSize: false, //去掉所有的内嵌字号,使用编辑器默认的字号 + clearFontFamily: false, //去掉所有的内嵌字体,使用编辑器默认的字体 + removeEmptyNode: false, // 去掉空节点 + //可以去掉的标签 + removeTagNames: utils.extend({div:1},dtd.$removeEmpty), + indent: false, // 行首缩进 + indentValue : '2em', //行首缩进的大小 + bdc2sb: false, + tobdc: false + }}); + + var me = this, + opt = me.options.autotypeset, + remainClass = { + 'selectTdClass':1, + 'pagebreak':1, + 'anchorclass':1 + }, + remainTag = { + 'li':1 + }, + tags = { + div:1, + p:1, + //trace:2183 这些也认为是行 + blockquote:1,center:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1, + span:1 + }, + highlightCont; + //升级了版本,但配置项目里没有autotypeset + if(!opt){ + return; + } + + readLocalOpts(); + + function isLine(node,notEmpty){ + if(!node || node.nodeType == 3) + return 0; + if(domUtils.isBr(node)) + return 1; + if(node && node.parentNode && tags[node.tagName.toLowerCase()]){ + if(highlightCont && highlightCont.contains(node) + || + node.getAttribute('pagebreak') + ){ + return 0; + } + + return notEmpty ? !domUtils.isEmptyBlock(node) : domUtils.isEmptyBlock(node,new RegExp('[\\s'+domUtils.fillChar + +']','g')); + } + } + + function removeNotAttributeSpan(node){ + if(!node.style.cssText){ + domUtils.removeAttributes(node,['style']); + if(node.tagName.toLowerCase() == 'span' && domUtils.hasNoAttributes(node)){ + domUtils.remove(node,true); + } + } + } + function autotype(type,html){ + + var me = this,cont; + if(html){ + if(!opt.pasteFilter){ + return; + } + cont = me.document.createElement('div'); + cont.innerHTML = html.html; + }else{ + cont = me.document.body; + } + var nodes = domUtils.getElementsByTagName(cont,'*'); + + // 行首缩进,段落方向,段间距,段内间距 + for(var i=0,ci;ci=nodes[i++];){ + + if(me.fireEvent('excludeNodeinautotype',ci) === true){ + continue; + } + //font-size + if(opt.clearFontSize && ci.style.fontSize){ + domUtils.removeStyle(ci,'font-size'); + + removeNotAttributeSpan(ci); + + } + //font-family + if(opt.clearFontFamily && ci.style.fontFamily){ + domUtils.removeStyle(ci,'font-family'); + removeNotAttributeSpan(ci); + } + + if(isLine(ci)){ + //合并空行 + if(opt.mergeEmptyline ){ + var next = ci.nextSibling,tmpNode,isBr = domUtils.isBr(ci); + while(isLine(next)){ + tmpNode = next; + next = tmpNode.nextSibling; + if(isBr && (!next || next && !domUtils.isBr(next))){ + break; + } + domUtils.remove(tmpNode); + } + + } + //去掉空行,保留占位的空行 + if(opt.removeEmptyline && domUtils.inDoc(ci,cont) && !remainTag[ci.parentNode.tagName.toLowerCase()] ){ + if(domUtils.isBr(ci)){ + next = ci.nextSibling; + if(next && !domUtils.isBr(next)){ + continue; + } + } + domUtils.remove(ci); + continue; + + } + + } + if(isLine(ci,true) && ci.tagName != 'SPAN'){ + if(opt.indent){ + ci.style.textIndent = opt.indentValue; + } + if(opt.textAlign){ + ci.style.textAlign = opt.textAlign; + } + // if(opt.lineHeight) + // ci.style.lineHeight = opt.lineHeight + 'cm'; + + } + + //去掉class,保留的class不去掉 + if(opt.removeClass && ci.className && !remainClass[ci.className.toLowerCase()]){ + + if(highlightCont && highlightCont.contains(ci)){ + continue; + } + domUtils.removeAttributes(ci,['class']); + } + + //表情不处理 + if(opt.imageBlockLine && ci.tagName.toLowerCase() == 'img' && !ci.getAttribute('emotion')){ + if(html){ + var img = ci; + switch (opt.imageBlockLine){ + case 'left': + case 'right': + case 'none': + var pN = img.parentNode,tmpNode,pre,next; + while(dtd.$inline[pN.tagName] || pN.tagName == 'A'){ + pN = pN.parentNode; + } + tmpNode = pN; + if(tmpNode.tagName == 'P' && domUtils.getStyle(tmpNode,'text-align') == 'center'){ + if(!domUtils.isBody(tmpNode) && domUtils.getChildCount(tmpNode,function(node){return !domUtils.isBr(node) && !domUtils.isWhitespace(node)}) == 1){ + pre = tmpNode.previousSibling; + next = tmpNode.nextSibling; + if(pre && next && pre.nodeType == 1 && next.nodeType == 1 && pre.tagName == next.tagName && domUtils.isBlockElm(pre)){ + pre.appendChild(tmpNode.firstChild); + while(next.firstChild){ + pre.appendChild(next.firstChild); + } + domUtils.remove(tmpNode); + domUtils.remove(next); + }else{ + domUtils.setStyle(tmpNode,'text-align',''); + } + + + } + + + } + domUtils.setStyle(img,'float', opt.imageBlockLine); + break; + case 'center': + if(me.queryCommandValue('imagefloat') != 'center'){ + pN = img.parentNode; + domUtils.setStyle(img,'float','none'); + tmpNode = img; + while(pN && domUtils.getChildCount(pN,function(node){return !domUtils.isBr(node) && !domUtils.isWhitespace(node)}) == 1 + && (dtd.$inline[pN.tagName] || pN.tagName == 'A')){ + tmpNode = pN; + pN = pN.parentNode; + } + var pNode = me.document.createElement('p'); + domUtils.setAttributes(pNode,{ + + style:'text-align:center' + }); + tmpNode.parentNode.insertBefore(pNode,tmpNode); + pNode.appendChild(tmpNode); + domUtils.setStyle(tmpNode,'float',''); + + } + + + } + } else { + var range = me.selection.getRange(); + range.selectNode(ci).select(); + me.execCommand('imagefloat', opt.imageBlockLine); + } + + } + + //去掉冗余的标签 + if(opt.removeEmptyNode){ + if(opt.removeTagNames[ci.tagName.toLowerCase()] && domUtils.hasNoAttributes(ci) && domUtils.isEmptyBlock(ci)){ + domUtils.remove(ci); + } + } + } + if(opt.tobdc){ + var root = UE.htmlparser(cont.innerHTML); + root.traversal(function(node){ + if(node.type == 'text'){ + node.data = ToDBC(node.data) + } + }); + cont.innerHTML = root.toHtml() + } + if(opt.bdc2sb){ + var root = UE.htmlparser(cont.innerHTML); + root.traversal(function(node){ + if(node.type == 'text'){ + node.data = DBC2SB(node.data) + } + }); + cont.innerHTML = root.toHtml() + } + if(html){ + html.html = cont.innerHTML; + } + } + if(opt.pasteFilter){ + me.addListener('beforepaste',autotype); + } + + function DBC2SB(str) { + var result = ''; + for (var i = 0; i < str.length; i++) { + var code = str.charCodeAt(i); //获取当前字符的unicode编码 + if (code >= 65281 && code <= 65373)//在这个unicode编码范围中的是所有的英文字母已经各种字符 + { + result += String.fromCharCode(str.charCodeAt(i) - 65248); //把全角字符的unicode编码转换为对应半角字符的unicode码 + } else if (code == 12288)//空格 + { + result += String.fromCharCode(str.charCodeAt(i) - 12288 + 32); + } else { + result += str.charAt(i); + } + } + return result; + } + function ToDBC(txtstring) { + txtstring = utils.html(txtstring); + var tmp = ""; + var mark = "";/*用于判断,如果是html尖括里的标记,则不进行全角的转换*/ + for (var i = 0; i < txtstring.length; i++) { + if (txtstring.charCodeAt(i) == 32) { + tmp = tmp + String.fromCharCode(12288); + } + else if (txtstring.charCodeAt(i) < 127) { + tmp = tmp + String.fromCharCode(txtstring.charCodeAt(i) + 65248); + } + else { + tmp += txtstring.charAt(i); + } + } + return tmp; + } + + function readLocalOpts() { + var cookieOpt = me.getPreferences('autotypeset'); + utils.extend(me.options.autotypeset, cookieOpt); + } + + me.commands['autotypeset'] = { + execCommand:function () { + me.removeListener('beforepaste',autotype); + if(opt.pasteFilter){ + me.addListener('beforepaste',autotype); + } + autotype.call(me) + } + + }; + +}; + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autoupload.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autoupload.js new file mode 100644 index 000000000..75d5169b5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/autoupload.js @@ -0,0 +1,179 @@ +/** + * @description + * 1.拖放文件到编辑区域,自动上传并插入到选区 + * 2.插入粘贴板的图片,自动上传并插入到选区 + * @author Jinqn + * @date 2013-10-14 + */ +UE.plugin.register('autoupload', function (){ + + function sendAndInsertFile(file, editor) { + var me = editor; + //模拟数据 + var fieldName, urlPrefix, maxSize, allowFiles, actionUrl, + loadingHtml, errorHandler, successHandler, + filetype = /image\/\w+/i.test(file.type) ? 'image':'file', + loadingId = 'loading_' + (+new Date()).toString(36); + + fieldName = me.getOpt(filetype + 'FieldName'); + urlPrefix = me.getOpt(filetype + 'UrlPrefix'); + maxSize = me.getOpt(filetype + 'MaxSize'); + allowFiles = me.getOpt(filetype + 'AllowFiles'); + actionUrl = me.getActionUrl(me.getOpt(filetype + 'ActionName')); + errorHandler = function(title) { + var loader = me.document.getElementById(loadingId); + loader && domUtils.remove(loader); + me.fireEvent('showmessage', { + 'id': loadingId, + 'content': title, + 'type': 'error', + 'timeout': 4000 + }); + }; + + if (filetype == 'image') { + loadingHtml = ''; + successHandler = function(data) { + var link = urlPrefix + data.url, + loader = me.document.getElementById(loadingId); + if (loader) { + loader.setAttribute('src', link); + loader.setAttribute('_src', link); + loader.setAttribute('title', data.title || ''); + loader.setAttribute('alt', data.original || ''); + loader.removeAttribute('id'); + domUtils.removeClasses(loader, 'loadingclass'); + } + }; + } else { + loadingHtml = '

    ' + + '' + + '

    '; + successHandler = function(data) { + var link = urlPrefix + data.url, + loader = me.document.getElementById(loadingId); + + var rng = me.selection.getRange(), + bk = rng.createBookmark(); + rng.selectNode(loader).select(); + me.execCommand('insertfile', {'url': link}); + rng.moveToBookmark(bk).select(); + }; + } + + /* 插入loading的占位符 */ + me.execCommand('inserthtml', loadingHtml); + + /* 判断后端配置是否没有加载成功 */ + if (!me.getOpt(filetype + 'ActionName')) { + errorHandler(me.getLang('autoupload.errorLoadConfig')); + return; + } + /* 判断文件大小是否超出限制 */ + if(file.size > maxSize) { + errorHandler(me.getLang('autoupload.exceedSizeError')); + return; + } + /* 判断文件格式是否超出允许 */ + var fileext = file.name ? file.name.substr(file.name.lastIndexOf('.')):''; + if ((fileext && filetype != 'image') || (allowFiles && (allowFiles.join('') + '.').indexOf(fileext.toLowerCase() + '.') == -1)) { + errorHandler(me.getLang('autoupload.exceedTypeError')); + return; + } + + /* 创建Ajax并提交 */ + var xhr = new XMLHttpRequest(), + fd = new FormData(), + params = utils.serializeParam(me.queryCommandValue('serverparam')) || '', + url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?':'&') + params); + + fd.append(fieldName, file, file.name || ('blob.' + file.type.substr('image/'.length))); + fd.append('type', 'ajax'); + xhr.open("post", url, true); + xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); + xhr.addEventListener('load', function (e) { + try{ + var json = (new Function("return " + utils.trim(e.target.response)))(); + if (json.state == 'SUCCESS' && json.url) { + successHandler(json); + } else { + errorHandler(json.state); + } + }catch(er){ + errorHandler(me.getLang('autoupload.loadError')); + } + }); + xhr.send(fd); + } + + function getPasteImage(e){ + return e.clipboardData && e.clipboardData.items && e.clipboardData.items.length == 1 && /^image\//.test(e.clipboardData.items[0].type) ? e.clipboardData.items:null; + } + function getDropImage(e){ + return e.dataTransfer && e.dataTransfer.files ? e.dataTransfer.files:null; + } + + return { + outputRule: function(root){ + utils.each(root.getNodesByTagName('img'),function(n){ + if (/\b(loaderrorclass)|(bloaderrorclass)\b/.test(n.getAttr('class'))) { + n.parentNode.removeChild(n); + } + }); + utils.each(root.getNodesByTagName('p'),function(n){ + if (/\bloadpara\b/.test(n.getAttr('class'))) { + n.parentNode.removeChild(n); + } + }); + }, + bindEvents:{ + //插入粘贴板的图片,拖放插入图片 + 'ready':function(e){ + var me = this; + if(window.FormData && window.FileReader) { + domUtils.on(me.body, 'paste drop', function(e){ + var hasImg = false, + items; + //获取粘贴板文件列表或者拖放文件列表 + items = e.type == 'paste' ? getPasteImage(e):getDropImage(e); + if(items){ + var len = items.length, + file; + while (len--){ + file = items[len]; + if(file.getAsFile) file = file.getAsFile(); + if(file && file.size > 0) { + sendAndInsertFile(file, me); + hasImg = true; + } + } + hasImg && e.preventDefault(); + } + + }); + //取消拖放图片时出现的文字光标位置提示 + domUtils.on(me.body, 'dragover', function (e) { + if(e.dataTransfer.types[0] == 'Files') { + e.preventDefault(); + } + }); + + //设置loading的样式 + utils.cssRule('loading', + '.loadingclass{display:inline-block;cursor:default;background: url(\'' + + this.options.themePath + + this.options.theme +'/images/loading.gif\') no-repeat center center transparent;border:1px solid #cccccc;margin-left:1px;height: 22px;width: 22px;}\n' + + '.loaderrorclass{display:inline-block;cursor:default;background: url(\'' + + this.options.themePath + + this.options.theme +'/images/loaderror.png\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;' + + '}', + this.document); + } + } + } + } +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/background.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/background.js new file mode 100644 index 000000000..92b41801c --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/background.js @@ -0,0 +1,107 @@ +/** + * 背景插件,为UEditor提供设置背景功能 + * @file + * @since 1.2.6.1 + */ +UE.plugin.register('background', function () { + var me = this, + cssRuleId = 'editor_background', + isSetColored, + reg = new RegExp('body[\\s]*\\{(.+)\\}', 'i'); + + function stringToObj(str) { + var obj = {}, styles = str.split(';'); + utils.each(styles, function (v) { + var index = v.indexOf(':'), + key = utils.trim(v.substr(0, index)).toLowerCase(); + key && (obj[key] = utils.trim(v.substr(index + 1) || '')); + }); + return obj; + } + + function setBackground(obj) { + if (obj) { + var styles = []; + for (var name in obj) { + if (obj.hasOwnProperty(name)) { + styles.push(name + ":" + obj[name] + '; '); + } + } + utils.cssRule(cssRuleId, styles.length ? ('body{' + styles.join("") + '}') : '', me.document); + } else { + utils.cssRule(cssRuleId, '', me.document) + } + } + //重写editor.hasContent方法 + + var orgFn = me.hasContents; + me.hasContents = function(){ + if(me.queryCommandValue('background')){ + return true + } + return orgFn.apply(me,arguments); + }; + return { + bindEvents: { + 'getAllHtml': function (type, headHtml) { + var body = this.body, + su = domUtils.getComputedStyle(body, "background-image"), + url = ""; + if (su.indexOf(me.options.imagePath) > 0) { + url = su.substring(su.indexOf(me.options.imagePath), su.length - 1).replace(/"|\(|\)/ig, ""); + } else { + url = su != "none" ? su.replace(/url\("?|"?\)/ig, "") : ""; + } + var html = ' '; + headHtml.push(html); + }, + 'aftersetcontent': function () { + if(isSetColored == false) setBackground(); + } + }, + inputRule: function (root) { + isSetColored = false; + utils.each(root.getNodesByTagName('p'), function (p) { + var styles = p.getAttr('data-background'); + if (styles) { + isSetColored = true; + setBackground(stringToObj(styles)); + p.parentNode.removeChild(p); + } + }) + }, + outputRule: function (root) { + var me = this, + styles = (utils.cssRule(cssRuleId, me.document) || '').replace(/[\n\r]+/g, '').match(reg); + if (styles) { + root.appendChild(UE.uNode.createElement('


    ')); + } + }, + commands: { + 'background': { + execCommand: function (cmd, obj) { + setBackground(obj); + }, + queryCommandValue: function () { + var me = this, + styles = (utils.cssRule(cssRuleId, me.document) || '').replace(/[\n\r]+/g, '').match(reg); + return styles ? stringToObj(styles[1]) : null; + }, + notNeedUndo: true + } + } + } +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/basestyle.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/basestyle.js new file mode 100644 index 000000000..78499dc76 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/basestyle.js @@ -0,0 +1,148 @@ +/** + * B、I、sub、super命令支持 + * @file + * @since 1.2.6.1 + */ + +UE.plugins['basestyle'] = function(){ + + /** + * 字体加粗 + * @command bold + * @param { String } cmd 命令字符串 + * @remind 对已加粗的文本内容执行该命令, 将取消加粗 + * @method execCommand + * @example + * ```javascript + * //editor是编辑器实例 + * //对当前选中的文本内容执行加粗操作 + * //第一次执行, 文本内容加粗 + * editor.execCommand( 'bold' ); + * + * //第二次执行, 文本内容取消加粗 + * editor.execCommand( 'bold' ); + * ``` + */ + + + /** + * 字体倾斜 + * @command italic + * @method execCommand + * @param { String } cmd 命令字符串 + * @remind 对已倾斜的文本内容执行该命令, 将取消倾斜 + * @example + * ```javascript + * //editor是编辑器实例 + * //对当前选中的文本内容执行斜体操作 + * //第一次操作, 文本内容将变成斜体 + * editor.execCommand( 'italic' ); + * + * //再次对同一文本内容执行, 则文本内容将恢复正常 + * editor.execCommand( 'italic' ); + * ``` + */ + + /** + * 下标文本,与“superscript”命令互斥 + * @command subscript + * @method execCommand + * @remind 把选中的文本内容切换成下标文本, 如果当前选中的文本已经是下标, 则该操作会把文本内容还原成正常文本 + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * //editor是编辑器实例 + * //对当前选中的文本内容执行下标操作 + * //第一次操作, 文本内容将变成下标文本 + * editor.execCommand( 'subscript' ); + * + * //再次对同一文本内容执行, 则文本内容将恢复正常 + * editor.execCommand( 'subscript' ); + * ``` + */ + + /** + * 上标文本,与“subscript”命令互斥 + * @command superscript + * @method execCommand + * @remind 把选中的文本内容切换成上标文本, 如果当前选中的文本已经是上标, 则该操作会把文本内容还原成正常文本 + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * //editor是编辑器实例 + * //对当前选中的文本内容执行上标操作 + * //第一次操作, 文本内容将变成上标文本 + * editor.execCommand( 'superscript' ); + * + * //再次对同一文本内容执行, 则文本内容将恢复正常 + * editor.execCommand( 'superscript' ); + * ``` + */ + var basestyles = { + 'bold':['strong','b'], + 'italic':['em','i'], + 'subscript':['sub'], + 'superscript':['sup'] + }, + getObj = function(editor,tagNames){ + return domUtils.filterNodeList(editor.selection.getStartElementPath(),tagNames); + }, + me = this; + //添加快捷键 + me.addshortcutkey({ + "Bold" : "ctrl+66",//^B + "Italic" : "ctrl+73", //^I + "Underline" : "ctrl+85"//^U + }); + me.addInputRule(function(root){ + utils.each(root.getNodesByTagName('b i'),function(node){ + switch (node.tagName){ + case 'b': + node.tagName = 'strong'; + break; + case 'i': + node.tagName = 'em'; + } + }); + }); + for ( var style in basestyles ) { + (function( cmd, tagNames ) { + me.commands[cmd] = { + execCommand : function( cmdName ) { + var range = me.selection.getRange(),obj = getObj(this,tagNames); + if ( range.collapsed ) { + if ( obj ) { + var tmpText = me.document.createTextNode(''); + range.insertNode( tmpText ).removeInlineStyle( tagNames ); + range.setStartBefore(tmpText); + domUtils.remove(tmpText); + } else { + var tmpNode = range.document.createElement( tagNames[0] ); + if(cmdName == 'superscript' || cmdName == 'subscript'){ + tmpText = me.document.createTextNode(''); + range.insertNode(tmpText) + .removeInlineStyle(['sub','sup']) + .setStartBefore(tmpText) + .collapse(true); + } + range.insertNode( tmpNode ).setStart( tmpNode, 0 ); + } + range.collapse( true ); + } else { + if(cmdName == 'superscript' || cmdName == 'subscript'){ + if(!obj || obj.tagName.toLowerCase() != cmdName){ + range.removeInlineStyle(['sub','sup']); + } + } + obj ? range.removeInlineStyle( tagNames ) : range.applyInlineStyle( tagNames[0] ); + } + range.select(); + }, + queryCommandState : function() { + return getObj(this,tagNames) ? 1 : 0; + } + }; + })( style, basestyles[style] ); + } +}; + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/blockquote.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/blockquote.js new file mode 100644 index 000000000..9f71f9e17 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/blockquote.js @@ -0,0 +1,172 @@ +/** + * 添加引用 + * @file + * @since 1.2.6.1 + */ + +/** + * 添加引用 + * @command blockquote + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'blockquote' ); + * ``` + */ + +/** + * 添加引用 + * @command blockquote + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { Object } attrs 节点属性 + * @example + * ```javascript + * editor.execCommand( 'blockquote',{ + * style: "color: red;" + * } ); + * ``` + */ + + +UE.plugins['blockquote'] = function(){ + var me = this; + function getObj(editor){ + return domUtils.filterNodeList(editor.selection.getStartElementPath(),'blockquote'); + } + me.commands['blockquote'] = { + execCommand : function( cmdName, attrs ) { + var range = this.selection.getRange(), + obj = getObj(this), + blockquote = dtd.blockquote, + bookmark = range.createBookmark(); + + if ( obj ) { + + var start = range.startContainer, + startBlock = domUtils.isBlockElm(start) ? start : domUtils.findParent(start,function(node){return domUtils.isBlockElm(node)}), + + end = range.endContainer, + endBlock = domUtils.isBlockElm(end) ? end : domUtils.findParent(end,function(node){return domUtils.isBlockElm(node)}); + + //处理一下li + startBlock = domUtils.findParentByTagName(startBlock,'li',true) || startBlock; + endBlock = domUtils.findParentByTagName(endBlock,'li',true) || endBlock; + + + if(startBlock.tagName == 'LI' || startBlock.tagName == 'TD' || startBlock === obj || domUtils.isBody(startBlock)){ + domUtils.remove(obj,true); + }else{ + domUtils.breakParent(startBlock,obj); + } + + if(startBlock !== endBlock){ + obj = domUtils.findParentByTagName(endBlock,'blockquote'); + if(obj){ + if(endBlock.tagName == 'LI' || endBlock.tagName == 'TD'|| domUtils.isBody(endBlock)){ + obj.parentNode && domUtils.remove(obj,true); + }else{ + domUtils.breakParent(endBlock,obj); + } + + } + } + + var blockquotes = domUtils.getElementsByTagName(this.document,'blockquote'); + for(var i=0,bi;bi=blockquotes[i++];){ + if(!bi.childNodes.length){ + domUtils.remove(bi); + }else if(domUtils.getPosition(bi,startBlock)&domUtils.POSITION_FOLLOWING && domUtils.getPosition(bi,endBlock)&domUtils.POSITION_PRECEDING){ + domUtils.remove(bi,true); + } + } + + + + + } else { + + var tmpRange = range.cloneRange(), + node = tmpRange.startContainer.nodeType == 1 ? tmpRange.startContainer : tmpRange.startContainer.parentNode, + preNode = node, + doEnd = 1; + + //调整开始 + while ( 1 ) { + if ( domUtils.isBody(node) ) { + if ( preNode !== node ) { + if ( range.collapsed ) { + tmpRange.selectNode( preNode ); + doEnd = 0; + } else { + tmpRange.setStartBefore( preNode ); + } + }else{ + tmpRange.setStart(node,0); + } + + break; + } + if ( !blockquote[node.tagName] ) { + if ( range.collapsed ) { + tmpRange.selectNode( preNode ); + } else{ + tmpRange.setStartBefore( preNode); + } + break; + } + + preNode = node; + node = node.parentNode; + } + + //调整结束 + if ( doEnd ) { + preNode = node = node = tmpRange.endContainer.nodeType == 1 ? tmpRange.endContainer : tmpRange.endContainer.parentNode; + while ( 1 ) { + + if ( domUtils.isBody( node ) ) { + if ( preNode !== node ) { + + tmpRange.setEndAfter( preNode ); + + } else { + tmpRange.setEnd( node, node.childNodes.length ); + } + + break; + } + if ( !blockquote[node.tagName] ) { + tmpRange.setEndAfter( preNode ); + break; + } + + preNode = node; + node = node.parentNode; + } + + } + + + node = range.document.createElement( 'blockquote' ); + domUtils.setAttributes( node, attrs ); + node.appendChild( tmpRange.extractContents() ); + tmpRange.insertNode( node ); + //去除重复的 + var childs = domUtils.getElementsByTagName(node,'blockquote'); + for(var i=0,ci;ci=childs[i++];){ + if(ci.parentNode){ + domUtils.remove(ci,true); + } + } + + } + range.moveToBookmark( bookmark ).select(); + }, + queryCommandState : function() { + return getObj(this) ? 1 : 0; + } + }; +}; + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/catchremoteimage.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/catchremoteimage.js new file mode 100644 index 000000000..5b32930dd --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/catchremoteimage.js @@ -0,0 +1,106 @@ +///import core +///commands 远程图片抓取 +///commandsName catchRemoteImage,catchremoteimageenable +///commandsTitle 远程图片抓取 +/** + * 远程图片抓取,当开启本插件时所有不符合本地域名的图片都将被抓取成为本地服务器上的图片 + */ +UE.plugins['catchremoteimage'] = function () { + var me = this, + ajax = UE.ajax; + + /* 设置默认值 */ + if (me.options.catchRemoteImageEnable === false) return; + me.setOpt({ + catchRemoteImageEnable: false + }); + + me.addListener("afterpaste", function () { + me.fireEvent("catchRemoteImage"); + }); + + me.addListener("catchRemoteImage", function () { + + var catcherLocalDomain = me.getOpt('catcherLocalDomain'), + catcherActionUrl = me.getActionUrl(me.getOpt('catcherActionName')), + catcherUrlPrefix = me.getOpt('catcherUrlPrefix'), + catcherFieldName = me.getOpt('catcherFieldName'); + + var remoteImages = [], + imgs = domUtils.getElementsByTagName(me.document, "img"), + test = function (src, urls) { + if (src.indexOf(location.host) != -1 || /(^\.)|(^\/)/.test(src)) { + return true; + } + if (urls) { + for (var j = 0, url; url = urls[j++];) { + if (src.indexOf(url) !== -1) { + return true; + } + } + } + return false; + }; + + for (var i = 0, ci; ci = imgs[i++];) { + if (ci.getAttribute("word_img")) { + continue; + } + var src = ci.getAttribute("_src") || ci.src || ""; + if (/^(https?|ftp):/i.test(src) && !test(src, catcherLocalDomain)) { + remoteImages.push(src); + } + } + + if (remoteImages.length) { + catchremoteimage(remoteImages, { + //成功抓取 + success: function (r) { + try { + var info = r.state !== undefined ? r:eval("(" + r.responseText + ")"); + } catch (e) { + return; + } + + /* 获取源路径和新路径 */ + var i, j, ci, cj, oldSrc, newSrc, list = info.list; + + for (i = 0; ci = imgs[i++];) { + oldSrc = ci.getAttribute("_src") || ci.src || ""; + for (j = 0; cj = list[j++];) { + if (oldSrc == cj.source && cj.state == "SUCCESS") { //抓取失败时不做替换处理 + newSrc = catcherUrlPrefix + cj.url; + domUtils.setAttributes(ci, { + "src": newSrc, + "_src": newSrc + }); + break; + } + } + } + me.fireEvent('catchremotesuccess') + }, + //回调失败,本次请求超时 + error: function () { + me.fireEvent("catchremoteerror"); + } + }); + } + + function catchremoteimage(imgs, callbacks) { + var params = utils.serializeParam(me.queryCommandValue('serverparam')) || '', + url = utils.formatUrl(catcherActionUrl + (catcherActionUrl.indexOf('?') == -1 ? '?':'&') + params), + isJsonp = utils.isCrossDomainUrl(url), + opt = { + 'method': 'POST', + 'dataType': isJsonp ? 'jsonp':'', + 'timeout': 60000, //单位:毫秒,回调请求超时设置。目标用户如果网速不是很快的话此处建议设置一个较大的数值 + 'onsuccess': callbacks["success"], + 'onerror': callbacks["error"] + }; + opt[catcherFieldName] = imgs; + ajax.request(url, opt); + } + + }); +}; \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/charts.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/charts.js new file mode 100644 index 000000000..562ee436d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/charts.js @@ -0,0 +1,142 @@ +UE.plugin.register('charts', function (){ + + var me = this; + + return { + bindEvents: { + 'chartserror': function () { + } + }, + commands:{ + 'charts': { + execCommand: function ( cmd, data ) { + + var tableNode = domUtils.findParentByTagName(this.selection.getRange().startContainer, 'table', true), + flagText = [], + config = {}; + + if ( !tableNode ) { + return false; + } + + if ( !validData( tableNode ) ) { + me.fireEvent( "chartserror" ); + return false; + } + + config.title = data.title || ''; + config.subTitle = data.subTitle || ''; + config.xTitle = data.xTitle || ''; + config.yTitle = data.yTitle || ''; + config.suffix = data.suffix || ''; + config.tip = data.tip || ''; + //数据对齐方式 + config.dataFormat = data.tableDataFormat || ''; + //图表类型 + config.chartType = data.chartType || 0; + + for ( var key in config ) { + + if ( !config.hasOwnProperty( key ) ) { + continue; + } + + flagText.push( key+":"+config[ key ] ); + + } + + tableNode.setAttribute( "data-chart", flagText.join( ";" ) ); + domUtils.addClass( tableNode, "edui-charts-table" ); + + + + }, + queryCommandState: function ( cmd, name ) { + + var tableNode = domUtils.findParentByTagName(this.selection.getRange().startContainer, 'table', true); + return tableNode && validData( tableNode ) ? 0 : -1; + + } + } + }, + inputRule:function(root){ + utils.each(root.getNodesByTagName('table'),function( tableNode ){ + + if ( tableNode.getAttr("data-chart") !== undefined ) { + tableNode.setAttr("style"); + } + + }) + + }, + outputRule:function(root){ + utils.each(root.getNodesByTagName('table'),function( tableNode ){ + + if ( tableNode.getAttr("data-chart") !== undefined ) { + tableNode.setAttr("style", "display: none;"); + } + + }) + + } + } + + function validData ( table ) { + + var firstRows = null, + cellCount = 0; + + //行数不够 + if ( table.rows.length < 2 ) { + return false; + } + + //列数不够 + if ( table.rows[0].cells.length < 2 ) { + return false; + } + + //第一行所有cell必须是th + firstRows = table.rows[ 0 ].cells; + cellCount = firstRows.length; + + for ( var i = 0, cell; cell = firstRows[ i ]; i++ ) { + + if ( cell.tagName.toLowerCase() !== 'th' ) { + return false; + } + + } + + for ( var i = 1, row; row = table.rows[ i ]; i++ ) { + + //每行单元格数不匹配, 返回false + if ( row.cells.length != cellCount ) { + return false; + } + + //第一列不是th也返回false + if ( row.cells[0].tagName.toLowerCase() !== 'th' ) { + return false; + } + + for ( var j = 1, cell; cell = row.cells[ j ]; j++ ) { + + var value = utils.trim( ( cell.innerText || cell.textContent || '' ) ); + + value = value.replace( new RegExp( UE.dom.domUtils.fillChar, 'g' ), '' ).replace( /^\s+|\s+$/g, '' ); + + //必须是数字 + if ( !/^\d*\.?\d+$/.test( value ) ) { + return false; + } + + } + + } + + return true; + + } + +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/cleardoc.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/cleardoc.js new file mode 100644 index 000000000..8daebe8ca --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/cleardoc.js @@ -0,0 +1,37 @@ +/** + * 清空文档插件 + * @file + * @since 1.2.6.1 + */ + +/** + * 清空文档 + * @command cleardoc + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * //editor 是编辑器实例 + * editor.execCommand('cleardoc'); + * ``` + */ + +UE.commands['cleardoc'] = { + execCommand : function( cmdName) { + var me = this, + enterTag = me.options.enterTag, + range = me.selection.getRange(); + if(enterTag == "br"){ + me.body.innerHTML = "
    "; + range.setStart(me.body,0).setCursor(); + }else{ + me.body.innerHTML = "

    "+(ie ? "" : "
    ")+"

    "; + range.setStart(me.body.firstChild,0).setCursor(false,true); + } + setTimeout(function(){ + me.fireEvent("clearDoc"); + },0); + + } +}; + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/contextmenu.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/contextmenu.js new file mode 100644 index 000000000..0ddd9c7ad --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/contextmenu.js @@ -0,0 +1,496 @@ +///import core +///commands 右键菜单 +///commandsName ContextMenu +///commandsTitle 右键菜单 +/** + * 右键菜单 + * @function + * @name baidu.editor.plugins.contextmenu + * @author zhanyi + */ + +UE.plugins['contextmenu'] = function () { + var me = this; + me.setOpt('enableContextMenu',true); + if(me.getOpt('enableContextMenu') === false){ + return; + } + var lang = me.getLang( "contextMenu" ), + menu, + items = me.options.contextMenu || [ + {label:lang['selectall'], cmdName:'selectall'}, + { + label:lang.cleardoc, + cmdName:'cleardoc', + exec:function () { + if ( confirm( lang.confirmclear ) ) { + this.execCommand( 'cleardoc' ); + } + } + }, + '-', + { + label:lang.unlink, + cmdName:'unlink' + }, + '-', + { + group:lang.paragraph, + icon:'justifyjustify', + subMenu:[ + { + label:lang.justifyleft, + cmdName:'justify', + value:'left' + }, + { + label:lang.justifyright, + cmdName:'justify', + value:'right' + }, + { + label:lang.justifycenter, + cmdName:'justify', + value:'center' + }, + { + label:lang.justifyjustify, + cmdName:'justify', + value:'justify' + } + ] + }, + '-', + { + group:lang.table, + icon:'table', + subMenu:[ + { + label:lang.inserttable, + cmdName:'inserttable' + }, + { + label:lang.deletetable, + cmdName:'deletetable' + }, + '-', + { + label:lang.deleterow, + cmdName:'deleterow' + }, + { + label:lang.deletecol, + cmdName:'deletecol' + }, + { + label:lang.insertcol, + cmdName:'insertcol' + }, + { + label:lang.insertcolnext, + cmdName:'insertcolnext' + }, + { + label:lang.insertrow, + cmdName:'insertrow' + }, + { + label:lang.insertrownext, + cmdName:'insertrownext' + }, + '-', + { + label:lang.insertcaption, + cmdName:'insertcaption' + }, + { + label:lang.deletecaption, + cmdName:'deletecaption' + }, + { + label:lang.inserttitle, + cmdName:'inserttitle' + }, + { + label:lang.deletetitle, + cmdName:'deletetitle' + }, + { + label:lang.inserttitlecol, + cmdName:'inserttitlecol' + }, + { + label:lang.deletetitlecol, + cmdName:'deletetitlecol' + }, + '-', + { + label:lang.mergecells, + cmdName:'mergecells' + }, + { + label:lang.mergeright, + cmdName:'mergeright' + }, + { + label:lang.mergedown, + cmdName:'mergedown' + }, + '-', + { + label:lang.splittorows, + cmdName:'splittorows' + }, + { + label:lang.splittocols, + cmdName:'splittocols' + }, + { + label:lang.splittocells, + cmdName:'splittocells' + }, + '-', + { + label:lang.averageDiseRow, + cmdName:'averagedistributerow' + }, + { + label:lang.averageDisCol, + cmdName:'averagedistributecol' + }, + '-', + { + label:lang.edittd, + cmdName:'edittd', + exec:function () { + if ( UE.ui['edittd'] ) { + new UE.ui['edittd']( this ); + } + this.getDialog('edittd').open(); + } + }, + { + label:lang.edittable, + cmdName:'edittable', + exec:function () { + if ( UE.ui['edittable'] ) { + new UE.ui['edittable']( this ); + } + this.getDialog('edittable').open(); + } + }, + { + label:lang.setbordervisible, + cmdName:'setbordervisible' + } + ] + }, + { + group:lang.tablesort, + icon:'tablesort', + subMenu:[ + { + label:lang.enablesort, + cmdName:'enablesort' + }, + { + label:lang.disablesort, + cmdName:'disablesort' + }, + '-', + { + label:lang.reversecurrent, + cmdName:'sorttable', + value:'reversecurrent' + }, + { + label:lang.orderbyasc, + cmdName:'sorttable', + value:'orderbyasc' + }, + { + label:lang.reversebyasc, + cmdName:'sorttable', + value:'reversebyasc' + }, + { + label:lang.orderbynum, + cmdName:'sorttable', + value:'orderbynum' + }, + { + label:lang.reversebynum, + cmdName:'sorttable', + value:'reversebynum' + } + ] + }, + { + group:lang.borderbk, + icon:'borderBack', + subMenu:[ + { + label:lang.setcolor, + cmdName:"interlacetable", + exec:function(){ + this.execCommand("interlacetable"); + } + }, + { + label:lang.unsetcolor, + cmdName:"uninterlacetable", + exec:function(){ + this.execCommand("uninterlacetable"); + } + }, + { + label:lang.setbackground, + cmdName:"settablebackground", + exec:function(){ + this.execCommand("settablebackground",{repeat:true,colorList:["#bbb","#ccc"]}); + } + }, + { + label:lang.unsetbackground, + cmdName:"cleartablebackground", + exec:function(){ + this.execCommand("cleartablebackground"); + } + }, + { + label:lang.redandblue, + cmdName:"settablebackground", + exec:function(){ + this.execCommand("settablebackground",{repeat:true,colorList:["red","blue"]}); + } + }, + { + label:lang.threecolorgradient, + cmdName:"settablebackground", + exec:function(){ + this.execCommand("settablebackground",{repeat:true,colorList:["#aaa","#bbb","#ccc"]}); + } + } + ] + }, + { + group:lang.aligntd, + icon:'aligntd', + subMenu:[ + { + cmdName:'cellalignment', + value:{align:'left',vAlign:'top'} + }, + { + cmdName:'cellalignment', + value:{align:'center',vAlign:'top'} + }, + { + cmdName:'cellalignment', + value:{align:'right',vAlign:'top'} + }, + { + cmdName:'cellalignment', + value:{align:'left',vAlign:'middle'} + }, + { + cmdName:'cellalignment', + value:{align:'center',vAlign:'middle'} + }, + { + cmdName:'cellalignment', + value:{align:'right',vAlign:'middle'} + }, + { + cmdName:'cellalignment', + value:{align:'left',vAlign:'bottom'} + }, + { + cmdName:'cellalignment', + value:{align:'center',vAlign:'bottom'} + }, + { + cmdName:'cellalignment', + value:{align:'right',vAlign:'bottom'} + } + ] + }, + { + group:lang.aligntable, + icon:'aligntable', + subMenu:[ + { + cmdName:'tablealignment', + className: 'left', + label:lang.tableleft, + value:"left" + }, + { + cmdName:'tablealignment', + className: 'center', + label:lang.tablecenter, + value:"center" + }, + { + cmdName:'tablealignment', + className: 'right', + label:lang.tableright, + value:"right" + } + ] + }, + '-', + { + label:lang.insertparagraphbefore, + cmdName:'insertparagraph', + value:true + }, + { + label:lang.insertparagraphafter, + cmdName:'insertparagraph' + }, + { + label:lang['copy'], + cmdName:'copy' + }, + { + label:lang['paste'], + cmdName:'paste' + } + ]; + if ( !items.length ) { + return; + } + var uiUtils = UE.ui.uiUtils; + + me.addListener( 'contextmenu', function ( type, evt ) { + + var offset = uiUtils.getViewportOffsetByEvent( evt ); + me.fireEvent( 'beforeselectionchange' ); + if ( menu ) { + menu.destroy(); + } + for ( var i = 0, ti, contextItems = []; ti = items[i]; i++ ) { + var last; + (function ( item ) { + if ( item == '-' ) { + if ( (last = contextItems[contextItems.length - 1 ] ) && last !== '-' ) { + contextItems.push( '-' ); + } + } else if ( item.hasOwnProperty( "group" ) ) { + for ( var j = 0, cj, subMenu = []; cj = item.subMenu[j]; j++ ) { + (function ( subItem ) { + if ( subItem == '-' ) { + if ( (last = subMenu[subMenu.length - 1 ] ) && last !== '-' ) { + subMenu.push( '-' ); + }else{ + subMenu.splice(subMenu.length-1); + } + } else { + if ( (me.commands[subItem.cmdName] || UE.commands[subItem.cmdName] || subItem.query) && + (subItem.query ? subItem.query() : me.queryCommandState( subItem.cmdName )) > -1 ) { + subMenu.push( { + 'label':subItem.label || me.getLang( "contextMenu." + subItem.cmdName + (subItem.value || '') )||"", + 'className':'edui-for-' +subItem.cmdName + ( subItem.className ? ( ' edui-for-' + subItem.cmdName + '-' + subItem.className ) : '' ), + onclick:subItem.exec ? function () { + subItem.exec.call( me ); + } : function () { + me.execCommand( subItem.cmdName, subItem.value ); + } + } ); + } + } + })( cj ); + } + if ( subMenu.length ) { + function getLabel(){ + switch (item.icon){ + case "table": + return me.getLang( "contextMenu.table" ); + case "justifyjustify": + return me.getLang( "contextMenu.paragraph" ); + case "aligntd": + return me.getLang("contextMenu.aligntd"); + case "aligntable": + return me.getLang("contextMenu.aligntable"); + case "tablesort": + return lang.tablesort; + case "borderBack": + return lang.borderbk; + default : + return ''; + } + } + contextItems.push( { + //todo 修正成自动获取方式 + 'label':getLabel(), + className:'edui-for-' + item.icon, + 'subMenu':{ + items:subMenu, + editor:me + } + } ); + } + + } else { + //有可能commmand没有加载右键不能出来,或者没有command也想能展示出来添加query方法 + if ( (me.commands[item.cmdName] || UE.commands[item.cmdName] || item.query) && + (item.query ? item.query.call(me) : me.queryCommandState( item.cmdName )) > -1 ) { + + contextItems.push( { + 'label':item.label || me.getLang( "contextMenu." + item.cmdName ), + className:'edui-for-' + (item.icon ? item.icon : item.cmdName + (item.value || '')), + onclick:item.exec ? function () { + item.exec.call( me ); + } : function () { + me.execCommand( item.cmdName, item.value ); + } + } ); + } + + } + + })( ti ); + } + if ( contextItems[contextItems.length - 1] == '-' ) { + contextItems.pop(); + } + + menu = new UE.ui.Menu( { + items:contextItems, + className:"edui-contextmenu", + editor:me + } ); + menu.render(); + menu.showAt( offset ); + + me.fireEvent("aftershowcontextmenu",menu); + + domUtils.preventDefault( evt ); + if ( browser.ie ) { + var ieRange; + try { + ieRange = me.selection.getNative().createRange(); + } catch ( e ) { + return; + } + if ( ieRange.item ) { + var range = new dom.Range( me.document ); + range.selectNode( ieRange.item( 0 ) ).select( true, true ); + } + } + }); + + // 添加复制的flash按钮 + me.addListener('aftershowcontextmenu', function(type, menu) { + if (me.zeroclipboard) { + var items = menu.items; + for (var key in items) { + if (items[key].className == 'edui-for-copy') { + me.zeroclipboard.clip(items[key].getDom()); + } + } + } + }); + +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/convertcase.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/convertcase.js new file mode 100644 index 000000000..4ae6a1dcc --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/convertcase.js @@ -0,0 +1,56 @@ +/** + * 大小写转换 + * @file + * @since 1.2.6.1 + */ + +/** + * 把选区内文本变大写,与“tolowercase”命令互斥 + * @command touppercase + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'touppercase' ); + * ``` + */ + +/** + * 把选区内文本变小写,与“touppercase”命令互斥 + * @command tolowercase + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'tolowercase' ); + * ``` + */ +UE.commands['touppercase'] = +UE.commands['tolowercase'] = { + execCommand:function (cmd) { + var me = this; + var rng = me.selection.getRange(); + if(rng.collapsed){ + return rng; + } + var bk = rng.createBookmark(), + bkEnd = bk.end, + filterFn = function( node ) { + return !domUtils.isBr(node) && !domUtils.isWhitespace( node ); + }, + curNode = domUtils.getNextDomNode( bk.start, false, filterFn ); + while ( curNode && (domUtils.getPosition( curNode, bkEnd ) & domUtils.POSITION_PRECEDING) ) { + + if ( curNode.nodeType == 3 ) { + curNode.nodeValue = curNode.nodeValue[cmd == 'touppercase' ? 'toUpperCase' : 'toLowerCase'](); + } + curNode = domUtils.getNextDomNode( curNode, true, filterFn ); + if(curNode === bkEnd){ + break; + } + + } + rng.moveToBookmark(bk).select(); + } +}; + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/copy.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/copy.js new file mode 100644 index 000000000..6e267a435 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/copy.js @@ -0,0 +1,69 @@ +UE.plugin.register('copy', function () { + + var me = this; + + function initZeroClipboard() { + + ZeroClipboard.config({ + debug: false, + swfPath: me.options.UEDITOR_HOME_URL + 'third-party/zeroclipboard/ZeroClipboard.swf' + }); + + var client = me.zeroclipboard = new ZeroClipboard(); + + // 复制内容 + client.on('copy', function (e) { + var client = e.client, + rng = me.selection.getRange(), + div = document.createElement('div'); + + div.appendChild(rng.cloneContents()); + client.setText(div.innerText || div.textContent); + client.setHtml(div.innerHTML); + rng.select(); + }); + // hover事件传递到target + client.on('mouseover mouseout', function (e) { + var target = e.target; + if (e.type == 'mouseover') { + domUtils.addClass(target, 'edui-state-hover'); + } else if (e.type == 'mouseout') { + domUtils.removeClasses(target, 'edui-state-hover'); + } + }); + // flash加载不成功 + client.on('wrongflash noflash', function () { + ZeroClipboard.destroy(); + }); + } + + return { + bindEvents: { + 'ready': function () { + if (!browser.ie) { + if (window.ZeroClipboard) { + initZeroClipboard(); + } else { + utils.loadFile(document, { + src: me.options.UEDITOR_HOME_URL + "third-party/zeroclipboard/ZeroClipboard.js", + tag: "script", + type: "text/javascript", + defer: "defer" + }, function () { + initZeroClipboard(); + }); + } + } + } + }, + commands: { + 'copy': { + execCommand: function (cmd) { + if (!me.document.execCommand('copy')) { + alert(me.getLang('copymsg')); + } + } + } + } + } +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/customstyle.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/customstyle.js new file mode 100644 index 000000000..57cb2abb9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/customstyle.js @@ -0,0 +1,146 @@ +/** + * 自定义样式 + * @file + * @since 1.2.6.1 + */ + +/** + * 根据config配置文件里“customstyle”选项的值对匹配的标签执行样式替换。 + * @command customstyle + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'customstyle' ); + * ``` + */ +UE.plugins['customstyle'] = function() { + var me = this; + me.setOpt({ 'customstyle':[ + {tag:'h1',name:'tc', style:'font-size:32px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;margin:0 0 20px 0;'}, + {tag:'h1',name:'tl', style:'font-size:32px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:left;margin:0 0 10px 0;'}, + {tag:'span',name:'im', style:'font-size:16px;font-style:italic;font-weight:bold;line-height:18px;'}, + {tag:'span',name:'hi', style:'font-size:16px;font-style:italic;font-weight:bold;color:rgb(51, 153, 204);line-height:18px;'} + ]}); + me.commands['customstyle'] = { + execCommand : function(cmdName, obj) { + var me = this, + tagName = obj.tag, + node = domUtils.findParent(me.selection.getStart(), function(node) { + return node.getAttribute('label'); + }, true), + range,bk,tmpObj = {}; + for (var p in obj) { + if(obj[p]!==undefined) + tmpObj[p] = obj[p]; + } + delete tmpObj.tag; + if (node && node.getAttribute('label') == obj.label) { + range = this.selection.getRange(); + bk = range.createBookmark(); + if (range.collapsed) { + //trace:1732 删掉自定义标签,要有p来回填站位 + if(dtd.$block[node.tagName]){ + var fillNode = me.document.createElement('p'); + domUtils.moveChild(node, fillNode); + node.parentNode.insertBefore(fillNode, node); + domUtils.remove(node); + }else{ + domUtils.remove(node,true); + } + + } else { + + var common = domUtils.getCommonAncestor(bk.start, bk.end), + nodes = domUtils.getElementsByTagName(common, tagName); + if(new RegExp(tagName,'i').test(common.tagName)){ + nodes.push(common); + } + for (var i = 0,ni; ni = nodes[i++];) { + if (ni.getAttribute('label') == obj.label) { + var ps = domUtils.getPosition(ni, bk.start),pe = domUtils.getPosition(ni, bk.end); + if ((ps & domUtils.POSITION_FOLLOWING || ps & domUtils.POSITION_CONTAINS) + && + (pe & domUtils.POSITION_PRECEDING || pe & domUtils.POSITION_CONTAINS) + ) + if (dtd.$block[tagName]) { + var fillNode = me.document.createElement('p'); + domUtils.moveChild(ni, fillNode); + ni.parentNode.insertBefore(fillNode, ni); + } + domUtils.remove(ni, true); + } + } + node = domUtils.findParent(common, function(node) { + return node.getAttribute('label') == obj.label; + }, true); + if (node) { + + domUtils.remove(node, true); + + } + + } + range.moveToBookmark(bk).select(); + } else { + if (dtd.$block[tagName]) { + this.execCommand('paragraph', tagName, tmpObj,'customstyle'); + range = me.selection.getRange(); + if (!range.collapsed) { + range.collapse(); + node = domUtils.findParent(me.selection.getStart(), function(node) { + return node.getAttribute('label') == obj.label; + }, true); + var pNode = me.document.createElement('p'); + domUtils.insertAfter(node, pNode); + domUtils.fillNode(me.document, pNode); + range.setStart(pNode, 0).setCursor(); + } + } else { + + range = me.selection.getRange(); + if (range.collapsed) { + node = me.document.createElement(tagName); + domUtils.setAttributes(node, tmpObj); + range.insertNode(node).setStart(node, 0).setCursor(); + + return; + } + + bk = range.createBookmark(); + range.applyInlineStyle(tagName, tmpObj).moveToBookmark(bk).select(); + } + } + + }, + queryCommandValue : function() { + var parent = domUtils.filterNodeList( + this.selection.getStartElementPath(), + function(node){return node.getAttribute('label')} + ); + return parent ? parent.getAttribute('label') : ''; + } + }; + //当去掉customstyle是,如果是块元素,用p代替 + me.addListener('keyup', function(type, evt) { + var keyCode = evt.keyCode || evt.which; + + if (keyCode == 32 || keyCode == 13) { + var range = me.selection.getRange(); + if (range.collapsed) { + var node = domUtils.findParent(me.selection.getStart(), function(node) { + return node.getAttribute('label'); + }, true); + if (node && dtd.$block[node.tagName] && domUtils.isEmptyNode(node)) { + var p = me.document.createElement('p'); + domUtils.insertAfter(node, p); + domUtils.fillNode(me.document, p); + domUtils.remove(node); + range.setStart(p, 0).setCursor(); + + + } + } + } + }); +}; \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/defaultfilter.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/defaultfilter.js new file mode 100644 index 000000000..65eb91110 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/defaultfilter.js @@ -0,0 +1,228 @@ +///import core +///plugin 编辑器默认的过滤转换机制 + +UE.plugins['defaultfilter'] = function () { + var me = this; + me.setOpt({ + 'allowDivTransToP':true, + 'disabledTableInTable':true + }); + //默认的过滤处理 + //进入编辑器的内容处理 + me.addInputRule(function (root) { + var allowDivTransToP = this.options.allowDivTransToP; + var val; + function tdParent(node){ + while(node && node.type == 'element'){ + if(node.tagName == 'td'){ + return true; + } + node = node.parentNode; + } + return false; + } + //进行默认的处理 + root.traversal(function (node) { + if (node.type == 'element') { + if (!dtd.$cdata[node.tagName] && me.options.autoClearEmptyNode && dtd.$inline[node.tagName] && !dtd.$empty[node.tagName] && (!node.attrs || utils.isEmptyObject(node.attrs))) { + if (!node.firstChild()) node.parentNode.removeChild(node); + else if (node.tagName == 'span' && (!node.attrs || utils.isEmptyObject(node.attrs))) { + node.parentNode.removeChild(node, true) + } + return; + } + switch (node.tagName) { + case 'style': + case 'script': + node.setAttr({ + cdata_tag: node.tagName, + cdata_data: (node.innerHTML() || ''), + '_ue_custom_node_':'true' + }); + node.tagName = 'div'; + node.innerHTML(''); + break; + case 'a': + if (val = node.getAttr('href')) { + node.setAttr('_href', val) + } + break; + case 'img': + //todo base64暂时去掉,后边做远程图片上传后,干掉这个 + if (val = node.getAttr('src')) { + if (/^data:/.test(val)) { + node.parentNode.removeChild(node); + break; + } + } + node.setAttr('_src', node.getAttr('src')); + break; + case 'span': + if (browser.webkit && (val = node.getStyle('white-space'))) { + if (/nowrap|normal/.test(val)) { + node.setStyle('white-space', ''); + if (me.options.autoClearEmptyNode && utils.isEmptyObject(node.attrs)) { + node.parentNode.removeChild(node, true) + } + } + } + val = node.getAttr('id'); + if(val && /^_baidu_bookmark_/i.test(val)){ + node.parentNode.removeChild(node) + } + break; + case 'p': + if (val = node.getAttr('align')) { + node.setAttr('align'); + node.setStyle('text-align', val) + } + //trace:3431 +// var cssStyle = node.getAttr('style'); +// if (cssStyle) { +// cssStyle = cssStyle.replace(/(margin|padding)[^;]+/g, ''); +// node.setAttr('style', cssStyle) +// +// } + //p标签不允许嵌套 + utils.each(node.children,function(n){ + if(n.type == 'element' && n.tagName == 'p'){ + var next = n.nextSibling(); + node.parentNode.insertAfter(n,node); + var last = n; + while(next){ + var tmp = next.nextSibling(); + node.parentNode.insertAfter(next,last); + last = next; + next = tmp; + } + return false; + } + }); + if (!node.firstChild()) { + node.innerHTML(browser.ie ? ' ' : '
    ') + } + break; + case 'div': + if(node.getAttr('cdata_tag')){ + break; + } + //针对代码这里不处理插入代码的div + val = node.getAttr('class'); + if(val && /^line number\d+/.test(val)){ + break; + } + if(!allowDivTransToP){ + break; + } + var tmpNode, p = UE.uNode.createElement('p'); + while (tmpNode = node.firstChild()) { + if (tmpNode.type == 'text' || !UE.dom.dtd.$block[tmpNode.tagName]) { + p.appendChild(tmpNode); + } else { + if (p.firstChild()) { + node.parentNode.insertBefore(p, node); + p = UE.uNode.createElement('p'); + } else { + node.parentNode.insertBefore(tmpNode, node); + } + } + } + if (p.firstChild()) { + node.parentNode.insertBefore(p, node); + } + node.parentNode.removeChild(node); + break; + case 'dl': + node.tagName = 'ul'; + break; + case 'dt': + case 'dd': + node.tagName = 'li'; + break; + case 'li': + var className = node.getAttr('class'); + if (!className || !/list\-/.test(className)) { + node.setAttr() + } + var tmpNodes = node.getNodesByTagName('ol ul'); + UE.utils.each(tmpNodes, function (n) { + node.parentNode.insertAfter(n, node); + }); + break; + case 'td': + case 'th': + case 'caption': + if(!node.children || !node.children.length){ + node.appendChild(browser.ie11below ? UE.uNode.createText(' ') : UE.uNode.createElement('br')) + } + break; + case 'table': + if(me.options.disabledTableInTable && tdParent(node)){ + node.parentNode.insertBefore(UE.uNode.createText(node.innerText()),node); + node.parentNode.removeChild(node) + } + } + + } +// if(node.type == 'comment'){ +// node.parentNode.removeChild(node); +// } + }) + + }); + + //从编辑器出去的内容处理 + me.addOutputRule(function (root) { + + var val; + root.traversal(function (node) { + if (node.type == 'element') { + + if (me.options.autoClearEmptyNode && dtd.$inline[node.tagName] && !dtd.$empty[node.tagName] && (!node.attrs || utils.isEmptyObject(node.attrs))) { + + if (!node.firstChild()) node.parentNode.removeChild(node); + else if (node.tagName == 'span' && (!node.attrs || utils.isEmptyObject(node.attrs))) { + node.parentNode.removeChild(node, true) + } + return; + } + switch (node.tagName) { + case 'div': + if (val = node.getAttr('cdata_tag')) { + node.tagName = val; + node.appendChild(UE.uNode.createText(node.getAttr('cdata_data'))); + node.setAttr({cdata_tag: '', cdata_data: '','_ue_custom_node_':''}); + } + break; + case 'a': + if (val = node.getAttr('_href')) { + node.setAttr({ + 'href': utils.html(val), + '_href': '' + }) + } + break; + break; + case 'span': + val = node.getAttr('id'); + if(val && /^_baidu_bookmark_/i.test(val)){ + node.parentNode.removeChild(node) + } + break; + case 'img': + if (val = node.getAttr('_src')) { + node.setAttr({ + 'src': node.getAttr('_src'), + '_src': '' + }) + } + + + } + } + + }) + + + }); +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/directionality.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/directionality.js new file mode 100644 index 000000000..c7fd8ba80 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/directionality.js @@ -0,0 +1,121 @@ +/** + * 设置文字输入的方向的插件 + * @file + * @since 1.2.6.1 + */ +(function() { + var block = domUtils.isBlockElm , + getObj = function(editor){ +// var startNode = editor.selection.getStart(), +// parents; +// if ( startNode ) { +// //查找所有的是block的父亲节点 +// parents = domUtils.findParents( startNode, true, block, true ); +// for ( var i = 0,ci; ci = parents[i++]; ) { +// if ( ci.getAttribute( 'dir' ) ) { +// return ci; +// } +// } +// } + return domUtils.filterNodeList(editor.selection.getStartElementPath(),function(n){return n && n.nodeType == 1 && n.getAttribute('dir')}); + + }, + doDirectionality = function(range,editor,forward){ + + var bookmark, + filterFn = function( node ) { + return node.nodeType == 1 ? !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace(node); + }, + + obj = getObj( editor ); + + if ( obj && range.collapsed ) { + obj.setAttribute( 'dir', forward ); + return range; + } + bookmark = range.createBookmark(); + range.enlarge( true ); + var bookmark2 = range.createBookmark(), + current = domUtils.getNextDomNode( bookmark2.start, false, filterFn ), + tmpRange = range.cloneRange(), + tmpNode; + while ( current && !(domUtils.getPosition( current, bookmark2.end ) & domUtils.POSITION_FOLLOWING) ) { + if ( current.nodeType == 3 || !block( current ) ) { + tmpRange.setStartBefore( current ); + while ( current && current !== bookmark2.end && !block( current ) ) { + tmpNode = current; + current = domUtils.getNextDomNode( current, false, null, function( node ) { + return !block( node ); + } ); + } + tmpRange.setEndAfter( tmpNode ); + var common = tmpRange.getCommonAncestor(); + if ( !domUtils.isBody( common ) && block( common ) ) { + //遍历到了block节点 + common.setAttribute( 'dir', forward ); + current = common; + } else { + //没有遍历到,添加一个block节点 + var p = range.document.createElement( 'p' ); + p.setAttribute( 'dir', forward ); + var frag = tmpRange.extractContents(); + p.appendChild( frag ); + tmpRange.insertNode( p ); + current = p; + } + + current = domUtils.getNextDomNode( current, false, filterFn ); + } else { + current = domUtils.getNextDomNode( current, true, filterFn ); + } + } + return range.moveToBookmark( bookmark2 ).moveToBookmark( bookmark ); + }; + + /** + * 文字输入方向 + * @command directionality + * @method execCommand + * @param { String } cmdName 命令字符串 + * @param { String } forward 传入'ltr'表示从左向右输入,传入'rtl'表示从右向左输入 + * @example + * ```javascript + * editor.execCommand( 'directionality', 'ltr'); + * ``` + */ + + /** + * 查询当前选区的文字输入方向 + * @command directionality + * @method queryCommandValue + * @param { String } cmdName 命令字符串 + * @return { String } 返回'ltr'表示从左向右输入,返回'rtl'表示从右向左输入 + * @example + * ```javascript + * editor.queryCommandValue( 'directionality'); + * ``` + */ + UE.commands['directionality'] = { + execCommand : function( cmdName,forward ) { + var range = this.selection.getRange(); + //闭合时单独处理 + if(range.collapsed){ + var txt = this.document.createTextNode('d'); + range.insertNode(txt); + } + doDirectionality(range,this,forward); + if(txt){ + range.setStartBefore(txt).collapse(true); + domUtils.remove(txt); + } + + range.select(); + return true; + }, + queryCommandValue : function() { + var node = getObj(this); + return node ? node.getAttribute('dir') : 'ltr'; + } + }; +})(); + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/dragdrop.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/dragdrop.js new file mode 100644 index 000000000..2e3424203 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/dragdrop.js @@ -0,0 +1,56 @@ +UE.plugins['dragdrop'] = function (){ + + var me = this; + me.ready(function(){ + domUtils.on(this.body,'dragend',function(){ + var rng = me.selection.getRange(); + var node = rng.getClosedNode()||me.selection.getStart(); + + if(node && node.tagName == 'IMG'){ + + var pre = node.previousSibling,next; + while(next = node.nextSibling){ + if(next.nodeType == 1 && next.tagName == 'SPAN' && !next.firstChild){ + domUtils.remove(next) + }else{ + break; + } + } + + + if((pre && pre.nodeType == 1 && !domUtils.isEmptyBlock(pre) || !pre) && (!next || next && !domUtils.isEmptyBlock(next))){ + if(pre && pre.tagName == 'P' && !domUtils.isEmptyBlock(pre)){ + pre.appendChild(node); + domUtils.moveChild(next,pre); + domUtils.remove(next); + }else if(next && next.tagName == 'P' && !domUtils.isEmptyBlock(next)){ + next.insertBefore(node,next.firstChild); + } + + if(pre && pre.tagName == 'P' && domUtils.isEmptyBlock(pre)){ + domUtils.remove(pre) + } + if(next && next.tagName == 'P' && domUtils.isEmptyBlock(next)){ + domUtils.remove(next) + } + rng.selectNode(node).select(); + me.fireEvent('saveScene'); + + } + + } + + }) + }); + me.addListener('keyup', function(type, evt) { + var keyCode = evt.keyCode || evt.which; + if (keyCode == 13) { + var rng = me.selection.getRange(),node; + if(node = domUtils.findParentByTagName(rng.startContainer,'p',true)){ + if(domUtils.getComputedStyle(node,'text-align') == 'center'){ + domUtils.removeStyle(node,'text-align') + } + } + } + }) +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/elementpath.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/elementpath.js new file mode 100644 index 000000000..c67c35171 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/elementpath.js @@ -0,0 +1,43 @@ +/** + * 选取路径命令 + * @file + */ +UE.plugins['elementpath'] = function(){ + var currentLevel, + tagNames, + me = this; + me.setOpt('elementPathEnabled',true); + if(!me.options.elementPathEnabled){ + return; + } + me.commands['elementpath'] = { + execCommand : function( cmdName, level ) { + var start = tagNames[level], + range = me.selection.getRange(); + currentLevel = level*1; + range.selectNode(start).select(); + }, + queryCommandValue : function() { + //产生一个副本,不能修改原来的startElementPath; + var parents = [].concat(this.selection.getStartElementPath()).reverse(), + names = []; + tagNames = parents; + for(var i=0,ci;ci=parents[i];i++){ + if(ci.nodeType == 3) { + continue; + } + var name = ci.tagName.toLowerCase(); + if(name == 'img' && ci.getAttribute('anchorname')){ + name = 'anchor'; + } + names[i] = name; + if(currentLevel == i){ + currentLevel = -1; + break; + } + } + return names; + } + }; +}; + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/enterkey.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/enterkey.js new file mode 100644 index 000000000..53d2be736 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/enterkey.js @@ -0,0 +1,175 @@ +///import core +///import plugins/undo.js +///commands 设置回车标签p或br +///commandsName EnterKey +///commandsTitle 设置回车标签p或br +/** + * @description 处理回车 + * @author zhanyi + */ +UE.plugins['enterkey'] = function() { + var hTag, + me = this, + tag = me.options.enterTag; + me.addListener('keyup', function(type, evt) { + + var keyCode = evt.keyCode || evt.which; + if (keyCode == 13) { + var range = me.selection.getRange(), + start = range.startContainer, + doSave; + + //修正在h1-h6里边回车后不能嵌套p的问题 + if (!browser.ie) { + + if (/h\d/i.test(hTag)) { + if (browser.gecko) { + var h = domUtils.findParentByTagName(start, [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6','blockquote','caption','table'], true); + if (!h) { + me.document.execCommand('formatBlock', false, '

    '); + doSave = 1; + } + } else { + //chrome remove div + if (start.nodeType == 1) { + var tmp = me.document.createTextNode(''),div; + range.insertNode(tmp); + div = domUtils.findParentByTagName(tmp, 'div', true); + if (div) { + var p = me.document.createElement('p'); + while (div.firstChild) { + p.appendChild(div.firstChild); + } + div.parentNode.insertBefore(p, div); + domUtils.remove(div); + range.setStartBefore(tmp).setCursor(); + doSave = 1; + } + domUtils.remove(tmp); + + } + } + + if (me.undoManger && doSave) { + me.undoManger.save(); + } + } + //没有站位符,会出现多行的问题 + browser.opera && range.select(); + }else{ + me.fireEvent('saveScene',true,true) + } + } + }); + + me.addListener('keydown', function(type, evt) { + var keyCode = evt.keyCode || evt.which; + if (keyCode == 13) {//回车 + if(me.fireEvent('beforeenterkeydown')){ + domUtils.preventDefault(evt); + return; + } + me.fireEvent('saveScene',true,true); + hTag = ''; + + + var range = me.selection.getRange(); + + if (!range.collapsed) { + //跨td不能删 + var start = range.startContainer, + end = range.endContainer, + startTd = domUtils.findParentByTagName(start, 'td', true), + endTd = domUtils.findParentByTagName(end, 'td', true); + if (startTd && endTd && startTd !== endTd || !startTd && endTd || startTd && !endTd) { + evt.preventDefault ? evt.preventDefault() : ( evt.returnValue = false); + return; + } + } + if (tag == 'p') { + + + if (!browser.ie) { + + start = domUtils.findParentByTagName(range.startContainer, ['ol','ul','p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6','blockquote','caption'], true); + + //opera下执行formatblock会在table的场景下有问题,回车在opera原生支持很好,所以暂时在opera去掉调用这个原生的command + //trace:2431 + if (!start && !browser.opera) { + + me.document.execCommand('formatBlock', false, '

    '); + + if (browser.gecko) { + range = me.selection.getRange(); + start = domUtils.findParentByTagName(range.startContainer, 'p', true); + start && domUtils.removeDirtyAttr(start); + } + + + } else { + hTag = start.tagName; + start.tagName.toLowerCase() == 'p' && browser.gecko && domUtils.removeDirtyAttr(start); + } + + } + + } else { + evt.preventDefault ? evt.preventDefault() : ( evt.returnValue = false); + + if (!range.collapsed) { + range.deleteContents(); + start = range.startContainer; + if (start.nodeType == 1 && (start = start.childNodes[range.startOffset])) { + while (start.nodeType == 1) { + if (dtd.$empty[start.tagName]) { + range.setStartBefore(start).setCursor(); + if (me.undoManger) { + me.undoManger.save(); + } + return false; + } + if (!start.firstChild) { + var br = range.document.createElement('br'); + start.appendChild(br); + range.setStart(start, 0).setCursor(); + if (me.undoManger) { + me.undoManger.save(); + } + return false; + } + start = start.firstChild; + } + if (start === range.startContainer.childNodes[range.startOffset]) { + br = range.document.createElement('br'); + range.insertNode(br).setCursor(); + + } else { + range.setStart(start, 0).setCursor(); + } + + + } else { + br = range.document.createElement('br'); + range.insertNode(br).setStartAfter(br).setCursor(); + } + + + } else { + br = range.document.createElement('br'); + range.insertNode(br); + var parent = br.parentNode; + if (parent.lastChild === br) { + br.parentNode.insertBefore(br.cloneNode(true), br); + range.setStartBefore(br); + } else { + range.setStartAfter(br); + } + range.setCursor(); + + } + + } + + } + }); +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/fiximgclick.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/fiximgclick.js new file mode 100644 index 000000000..658347c9e --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/fiximgclick.js @@ -0,0 +1,315 @@ +///import core +///commands 修复chrome下图片不能点击的问题,出现八个角可改变大小 +///commandsName FixImgClick +///commandsTitle 修复chrome下图片不能点击的问题,出现八个角可改变大小 +//修复chrome下图片不能点击的问题,出现八个角可改变大小 + +UE.plugins['fiximgclick'] = (function () { + + var elementUpdated = false; + function Scale() { + this.editor = null; + this.resizer = null; + this.cover = null; + this.doc = document; + this.prePos = {x: 0, y: 0}; + this.startPos = {x: 0, y: 0}; + } + + (function () { + var rect = [ + //[left, top, width, height] + [0, 0, -1, -1], + [0, 0, 0, -1], + [0, 0, 1, -1], + [0, 0, -1, 0], + [0, 0, 1, 0], + [0, 0, -1, 1], + [0, 0, 0, 1], + [0, 0, 1, 1] + ]; + + Scale.prototype = { + init: function (editor) { + var me = this; + me.editor = editor; + me.startPos = this.prePos = {x: 0, y: 0}; + me.dragId = -1; + + var hands = [], + cover = me.cover = document.createElement('div'), + resizer = me.resizer = document.createElement('div'); + + cover.id = me.editor.ui.id + '_imagescale_cover'; + cover.style.cssText = 'position:absolute;display:none;z-index:' + (me.editor.options.zIndex) + ';filter:alpha(opacity=0); opacity:0;background:#CCC;'; + domUtils.on(cover, 'mousedown click', function () { + me.hide(); + }); + + for (i = 0; i < 8; i++) { + hands.push(''); + } + resizer.id = me.editor.ui.id + '_imagescale'; + resizer.className = 'edui-editor-imagescale'; + resizer.innerHTML = hands.join(''); + resizer.style.cssText += ';display:none;border:1px solid #3b77ff;z-index:' + (me.editor.options.zIndex) + ';'; + + me.editor.ui.getDom().appendChild(cover); + me.editor.ui.getDom().appendChild(resizer); + + me.initStyle(); + me.initEvents(); + }, + initStyle: function () { + utils.cssRule('imagescale', '.edui-editor-imagescale{display:none;position:absolute;border:1px solid #38B2CE;cursor:hand;-webkit-box-sizing: content-box;-moz-box-sizing: content-box;box-sizing: content-box;}' + + '.edui-editor-imagescale span{position:absolute;width:6px;height:6px;overflow:hidden;font-size:0px;display:block;background-color:#3C9DD0;}' + + '.edui-editor-imagescale .edui-editor-imagescale-hand0{cursor:nw-resize;top:0;margin-top:-4px;left:0;margin-left:-4px;}' + + '.edui-editor-imagescale .edui-editor-imagescale-hand1{cursor:n-resize;top:0;margin-top:-4px;left:50%;margin-left:-4px;}' + + '.edui-editor-imagescale .edui-editor-imagescale-hand2{cursor:ne-resize;top:0;margin-top:-4px;left:100%;margin-left:-3px;}' + + '.edui-editor-imagescale .edui-editor-imagescale-hand3{cursor:w-resize;top:50%;margin-top:-4px;left:0;margin-left:-4px;}' + + '.edui-editor-imagescale .edui-editor-imagescale-hand4{cursor:e-resize;top:50%;margin-top:-4px;left:100%;margin-left:-3px;}' + + '.edui-editor-imagescale .edui-editor-imagescale-hand5{cursor:sw-resize;top:100%;margin-top:-3px;left:0;margin-left:-4px;}' + + '.edui-editor-imagescale .edui-editor-imagescale-hand6{cursor:s-resize;top:100%;margin-top:-3px;left:50%;margin-left:-4px;}' + + '.edui-editor-imagescale .edui-editor-imagescale-hand7{cursor:se-resize;top:100%;margin-top:-3px;left:100%;margin-left:-3px;}'); + }, + initEvents: function () { + var me = this; + + me.startPos.x = me.startPos.y = 0; + me.isDraging = false; + }, + _eventHandler: function (e) { + var me = this; + switch (e.type) { + case 'mousedown': + var hand = e.target || e.srcElement, hand; + if (hand.className.indexOf('edui-editor-imagescale-hand') != -1 && me.dragId == -1) { + me.dragId = hand.className.slice(-1); + me.startPos.x = me.prePos.x = e.clientX; + me.startPos.y = me.prePos.y = e.clientY; + domUtils.on(me.doc,'mousemove', me.proxy(me._eventHandler, me)); + } + break; + case 'mousemove': + if (me.dragId != -1) { + me.updateContainerStyle(me.dragId, {x: e.clientX - me.prePos.x, y: e.clientY - me.prePos.y}); + me.prePos.x = e.clientX; + me.prePos.y = e.clientY; + elementUpdated = true; + me.updateTargetElement(); + + } + break; + case 'mouseup': + if (me.dragId != -1) { + me.updateContainerStyle(me.dragId, {x: e.clientX - me.prePos.x, y: e.clientY - me.prePos.y}); + me.updateTargetElement(); + if (me.target.parentNode) me.attachTo(me.target); + me.dragId = -1; + } + domUtils.un(me.doc,'mousemove', me.proxy(me._eventHandler, me)); + //修复只是点击挪动点,但没有改变大小,不应该触发contentchange + if(elementUpdated){ + elementUpdated = false; + me.editor.fireEvent('contentchange'); + } + + break; + default: + break; + } + }, + updateTargetElement: function () { + var me = this; + domUtils.setStyles(me.target, { + 'width': me.resizer.style.width, + 'height': me.resizer.style.height + }); + me.target.width = parseInt(me.resizer.style.width); + me.target.height = parseInt(me.resizer.style.height); + me.attachTo(me.target); + }, + updateContainerStyle: function (dir, offset) { + var me = this, + dom = me.resizer, tmp; + + if (rect[dir][0] != 0) { + tmp = parseInt(dom.style.left) + offset.x; + dom.style.left = me._validScaledProp('left', tmp) + 'px'; + } + if (rect[dir][1] != 0) { + tmp = parseInt(dom.style.top) + offset.y; + dom.style.top = me._validScaledProp('top', tmp) + 'px'; + } + if (rect[dir][2] != 0) { + tmp = dom.clientWidth + rect[dir][2] * offset.x; + dom.style.width = me._validScaledProp('width', tmp) + 'px'; + } + if (rect[dir][3] != 0) { + tmp = dom.clientHeight + rect[dir][3] * offset.y; + dom.style.height = me._validScaledProp('height', tmp) + 'px'; + } + }, + _validScaledProp: function (prop, value) { + var ele = this.resizer, + wrap = document; + + value = isNaN(value) ? 0 : value; + switch (prop) { + case 'left': + return value < 0 ? 0 : (value + ele.clientWidth) > wrap.clientWidth ? wrap.clientWidth - ele.clientWidth : value; + case 'top': + return value < 0 ? 0 : (value + ele.clientHeight) > wrap.clientHeight ? wrap.clientHeight - ele.clientHeight : value; + case 'width': + return value <= 0 ? 1 : (value + ele.offsetLeft) > wrap.clientWidth ? wrap.clientWidth - ele.offsetLeft : value; + case 'height': + return value <= 0 ? 1 : (value + ele.offsetTop) > wrap.clientHeight ? wrap.clientHeight - ele.offsetTop : value; + } + }, + hideCover: function () { + this.cover.style.display = 'none'; + }, + showCover: function () { + var me = this, + editorPos = domUtils.getXY(me.editor.ui.getDom()), + iframePos = domUtils.getXY(me.editor.iframe); + + domUtils.setStyles(me.cover, { + 'width': me.editor.iframe.offsetWidth + 'px', + 'height': me.editor.iframe.offsetHeight + 'px', + 'top': iframePos.y - editorPos.y + 'px', + 'left': iframePos.x - editorPos.x + 'px', + 'position': 'absolute', + 'display': '' + }) + }, + show: function (targetObj) { + var me = this; + me.resizer.style.display = 'block'; + if(targetObj) me.attachTo(targetObj); + + domUtils.on(this.resizer, 'mousedown', me.proxy(me._eventHandler, me)); + domUtils.on(me.doc, 'mouseup', me.proxy(me._eventHandler, me)); + + me.showCover(); + me.editor.fireEvent('afterscaleshow', me); + me.editor.fireEvent('saveScene'); + }, + hide: function () { + var me = this; + me.hideCover(); + me.resizer.style.display = 'none'; + + domUtils.un(me.resizer, 'mousedown', me.proxy(me._eventHandler, me)); + domUtils.un(me.doc, 'mouseup', me.proxy(me._eventHandler, me)); + me.editor.fireEvent('afterscalehide', me); + }, + proxy: function( fn, context ) { + return function(e) { + return fn.apply( context || this, arguments); + }; + }, + attachTo: function (targetObj) { + var me = this, + target = me.target = targetObj, + resizer = this.resizer, + imgPos = domUtils.getXY(target), + iframePos = domUtils.getXY(me.editor.iframe), + editorPos = domUtils.getXY(resizer.parentNode); + + domUtils.setStyles(resizer, { + 'width': target.width + 'px', + 'height': target.height + 'px', + 'left': iframePos.x + imgPos.x - me.editor.document.body.scrollLeft - editorPos.x - parseInt(resizer.style.borderLeftWidth) + 'px', + 'top': iframePos.y + imgPos.y - me.editor.document.body.scrollTop - editorPos.y - parseInt(resizer.style.borderTopWidth) + 'px' + }); + } + } + })(); + + return function () { + var me = this, + imageScale; + + me.setOpt('imageScaleEnabled', true); + + if ( !browser.ie && me.options.imageScaleEnabled) { + me.addListener('click', function (type, e) { + + var range = me.selection.getRange(), + img = range.getClosedNode(); + + if (img && img.tagName == 'IMG' && me.body.contentEditable!="false") { + + if (img.className.indexOf("edui-faked-music") != -1 || + img.getAttribute("anchorname") || + domUtils.hasClass(img, 'loadingclass') || + domUtils.hasClass(img, 'loaderrorclass')) { return } + + if (!imageScale) { + imageScale = new Scale(); + imageScale.init(me); + me.ui.getDom().appendChild(imageScale.resizer); + + var _keyDownHandler = function (e) { + imageScale.hide(); + if(imageScale.target) me.selection.getRange().selectNode(imageScale.target).select(); + }, _mouseDownHandler = function (e) { + var ele = e.target || e.srcElement; + if (ele && (ele.className===undefined || ele.className.indexOf('edui-editor-imagescale') == -1)) { + _keyDownHandler(e); + } + }, timer; + + me.addListener('afterscaleshow', function (e) { + me.addListener('beforekeydown', _keyDownHandler); + me.addListener('beforemousedown', _mouseDownHandler); + domUtils.on(document, 'keydown', _keyDownHandler); + domUtils.on(document,'mousedown', _mouseDownHandler); + me.selection.getNative().removeAllRanges(); + }); + me.addListener('afterscalehide', function (e) { + me.removeListener('beforekeydown', _keyDownHandler); + me.removeListener('beforemousedown', _mouseDownHandler); + domUtils.un(document, 'keydown', _keyDownHandler); + domUtils.un(document,'mousedown', _mouseDownHandler); + var target = imageScale.target; + if (target.parentNode) { + me.selection.getRange().selectNode(target).select(); + } + }); + //TODO 有iframe的情况,mousedown不能往下传。。 + domUtils.on(imageScale.resizer, 'mousedown', function (e) { + me.selection.getNative().removeAllRanges(); + var ele = e.target || e.srcElement; + if (ele && ele.className.indexOf('edui-editor-imagescale-hand') == -1) { + timer = setTimeout(function () { + imageScale.hide(); + if(imageScale.target) me.selection.getRange().selectNode(ele).select(); + }, 200); + } + }); + domUtils.on(imageScale.resizer, 'mouseup', function (e) { + var ele = e.target || e.srcElement; + if (ele && ele.className.indexOf('edui-editor-imagescale-hand') == -1) { + clearTimeout(timer); + } + }); + } + imageScale.show(img); + } else { + if (imageScale && imageScale.resizer.style.display != 'none') imageScale.hide(); + } + }); + } + + if (browser.webkit) { + me.addListener('click', function (type, e) { + if (e.target.tagName == 'IMG' && me.body.contentEditable!="false") { + var range = new dom.Range(me.document); + range.selectNode(e.target).select(); + } + }); + } + } +})(); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/font.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/font.js new file mode 100644 index 000000000..e70d77af2 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/font.js @@ -0,0 +1,524 @@ +/** + * 字体颜色,背景色,字号,字体,下划线,删除线 + * @file + * @since 1.2.6.1 + */ + +/** + * 字体颜色 + * @command forecolor + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } value 色值(必须十六进制) + * @example + * ```javascript + * editor.execCommand( 'forecolor', '#000' ); + * ``` + */ +/** + * 返回选区字体颜色 + * @command forecolor + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回字体颜色 + * @example + * ```javascript + * editor.queryCommandValue( 'forecolor' ); + * ``` + */ + +/** + * 字体背景颜色 + * @command backcolor + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } value 色值(必须十六进制) + * @example + * ```javascript + * editor.execCommand( 'backcolor', '#000' ); + * ``` + */ +/** + * 返回选区字体颜色 + * @command backcolor + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回字体背景颜色 + * @example + * ```javascript + * editor.queryCommandValue( 'backcolor' ); + * ``` + */ + +/** + * 字体大小 + * @command fontsize + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } value 字体大小 + * @example + * ```javascript + * editor.execCommand( 'fontsize', '14px' ); + * ``` + */ +/** + * 返回选区字体大小 + * @command fontsize + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回字体大小 + * @example + * ```javascript + * editor.queryCommandValue( 'fontsize' ); + * ``` + */ + +/** + * 字体样式 + * @command fontfamily + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } value 字体样式 + * @example + * ```javascript + * editor.execCommand( 'fontfamily', '微软雅黑' ); + * ``` + */ +/** + * 返回选区字体样式 + * @command fontfamily + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回字体样式 + * @example + * ```javascript + * editor.queryCommandValue( 'fontfamily' ); + * ``` + */ + +/** + * 字体下划线,与删除线互斥 + * @command underline + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'underline' ); + * ``` + */ + +/** + * 字体删除线,与下划线互斥 + * @command strikethrough + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'strikethrough' ); + * ``` + */ + +/** + * 字体边框 + * @command fontborder + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'fontborder' ); + * ``` + */ + +UE.plugins['font'] = function () { + var me = this, + fonts = { + 'forecolor': 'color', + 'backcolor': 'background-color', + 'fontsize': 'font-size', + 'fontfamily': 'font-family', + 'underline': 'text-decoration', + 'strikethrough': 'text-decoration', + 'fontborder': 'border' + }, + needCmd = {'underline': 1, 'strikethrough': 1, 'fontborder': 1}, + needSetChild = { + 'forecolor': 'color', + 'backcolor': 'background-color', + 'fontsize': 'font-size', + 'fontfamily': 'font-family' + + }; + me.setOpt({ + 'fontfamily': [ + { name: 'songti', val: '宋体,SimSun'}, + { name: 'yahei', val: '微软雅黑,Microsoft YaHei'}, + { name: 'kaiti', val: '楷体,楷体_GB2312, SimKai'}, + { name: 'heiti', val: '黑体, SimHei'}, + { name: 'lishu', val: '隶书, SimLi'}, + { name: 'andaleMono', val: 'andale mono'}, + { name: 'arial', val: 'arial, helvetica,sans-serif'}, + { name: 'arialBlack', val: 'arial black,avant garde'}, + { name: 'comicSansMs', val: 'comic sans ms'}, + { name: 'impact', val: 'impact,chicago'}, + { name: 'timesNewRoman', val: 'times new roman'} + ], + 'fontsize': [10, 11, 12, 14, 16, 18, 20, 24, 36] + }); + + function mergeWithParent(node){ + var parent; + while(parent = node.parentNode){ + if(parent.tagName == 'SPAN' && domUtils.getChildCount(parent,function(child){ + return !domUtils.isBookmarkNode(child) && !domUtils.isBr(child) + }) == 1) { + parent.style.cssText += node.style.cssText; + domUtils.remove(node,true); + node = parent; + + }else{ + break; + } + } + + } + function mergeChild(rng,cmdName,value){ + if(needSetChild[cmdName]){ + rng.adjustmentBoundary(); + if(!rng.collapsed && rng.startContainer.nodeType == 1){ + var start = rng.startContainer.childNodes[rng.startOffset]; + if(start && domUtils.isTagNode(start,'span')){ + var bk = rng.createBookmark(); + utils.each(domUtils.getElementsByTagName(start, 'span'), function (span) { + if (!span.parentNode || domUtils.isBookmarkNode(span))return; + if(cmdName == 'backcolor' && domUtils.getComputedStyle(span,'background-color').toLowerCase() === value){ + return; + } + domUtils.removeStyle(span,needSetChild[cmdName]); + if(span.style.cssText.replace(/^\s+$/,'').length == 0){ + domUtils.remove(span,true) + } + }); + rng.moveToBookmark(bk) + } + } + } + + } + function mergesibling(rng,cmdName,value) { + var collapsed = rng.collapsed, + bk = rng.createBookmark(), common; + if (collapsed) { + common = bk.start.parentNode; + while (dtd.$inline[common.tagName]) { + common = common.parentNode; + } + } else { + common = domUtils.getCommonAncestor(bk.start, bk.end); + } + utils.each(domUtils.getElementsByTagName(common, 'span'), function (span) { + if (!span.parentNode || domUtils.isBookmarkNode(span))return; + if (/\s*border\s*:\s*none;?\s*/i.test(span.style.cssText)) { + if(/^\s*border\s*:\s*none;?\s*$/.test(span.style.cssText)){ + domUtils.remove(span, true); + }else{ + domUtils.removeStyle(span,'border'); + } + return + } + if (/border/i.test(span.style.cssText) && span.parentNode.tagName == 'SPAN' && /border/i.test(span.parentNode.style.cssText)) { + span.style.cssText = span.style.cssText.replace(/border[^:]*:[^;]+;?/gi, ''); + } + if(!(cmdName=='fontborder' && value=='none')){ + var next = span.nextSibling; + while (next && next.nodeType == 1 && next.tagName == 'SPAN' ) { + if(domUtils.isBookmarkNode(next) && cmdName == 'fontborder') { + span.appendChild(next); + next = span.nextSibling; + continue; + } + if (next.style.cssText == span.style.cssText) { + domUtils.moveChild(next, span); + domUtils.remove(next); + } + if (span.nextSibling === next) + break; + next = span.nextSibling; + } + } + + + mergeWithParent(span); + if(browser.ie && browser.version > 8 ){ + //拷贝父亲们的特别的属性,这里只做背景颜色的处理 + var parent = domUtils.findParent(span,function(n){return n.tagName == 'SPAN' && /background-color/.test(n.style.cssText)}); + if(parent && !/background-color/.test(span.style.cssText)){ + span.style.backgroundColor = parent.style.backgroundColor; + } + } + + }); + rng.moveToBookmark(bk); + mergeChild(rng,cmdName,value) + } + + me.addInputRule(function (root) { + utils.each(root.getNodesByTagName('u s del font strike'), function (node) { + if (node.tagName == 'font') { + var cssStyle = []; + for (var p in node.attrs) { + switch (p) { + case 'size': + cssStyle.push('font-size:' + + ({ + '1':'10', + '2':'12', + '3':'16', + '4':'18', + '5':'24', + '6':'32', + '7':'48' + }[node.attrs[p]] || node.attrs[p]) + 'px'); + break; + case 'color': + cssStyle.push('color:' + node.attrs[p]); + break; + case 'face': + cssStyle.push('font-family:' + node.attrs[p]); + break; + case 'style': + cssStyle.push(node.attrs[p]); + } + } + node.attrs = { + 'style': cssStyle.join(';') + }; + } else { + var val = node.tagName == 'u' ? 'underline' : 'line-through'; + node.attrs = { + 'style': (node.getAttr('style') || '') + 'text-decoration:' + val + ';' + } + } + node.tagName = 'span'; + }); +// utils.each(root.getNodesByTagName('span'), function (node) { +// var val; +// if(val = node.getAttr('class')){ +// if(/fontstrikethrough/.test(val)){ +// node.setStyle('text-decoration','line-through'); +// if(node.attrs['class']){ +// node.attrs['class'] = node.attrs['class'].replace(/fontstrikethrough/,''); +// }else{ +// node.setAttr('class') +// } +// } +// if(/fontborder/.test(val)){ +// node.setStyle('border','1px solid #000'); +// if(node.attrs['class']){ +// node.attrs['class'] = node.attrs['class'].replace(/fontborder/,''); +// }else{ +// node.setAttr('class') +// } +// } +// } +// }); + }); +// me.addOutputRule(function(root){ +// utils.each(root.getNodesByTagName('span'), function (node) { +// var val; +// if(val = node.getStyle('text-decoration')){ +// if(/line-through/.test(val)){ +// if(node.attrs['class']){ +// node.attrs['class'] += ' fontstrikethrough'; +// }else{ +// node.setAttr('class','fontstrikethrough') +// } +// } +// +// node.setStyle('text-decoration') +// } +// if(val = node.getStyle('border')){ +// if(/1px/.test(val) && /solid/.test(val)){ +// if(node.attrs['class']){ +// node.attrs['class'] += ' fontborder'; +// +// }else{ +// node.setAttr('class','fontborder') +// } +// } +// node.setStyle('border') +// +// } +// }); +// }); + for (var p in fonts) { + (function (cmd, style) { + UE.commands[cmd] = { + execCommand: function (cmdName, value) { + value = value || (this.queryCommandState(cmdName) ? 'none' : cmdName == 'underline' ? 'underline' : + cmdName == 'fontborder' ? '1px solid #000' : + 'line-through'); + var me = this, + range = this.selection.getRange(), + text; + + if (value == 'default') { + + if (range.collapsed) { + text = me.document.createTextNode('font'); + range.insertNode(text).select(); + + } + me.execCommand('removeFormat', 'span,a', style); + if (text) { + range.setStartBefore(text).collapse(true); + domUtils.remove(text); + } + mergesibling(range,cmdName,value); + range.select() + } else { + if (!range.collapsed) { + if (needCmd[cmd] && me.queryCommandValue(cmd)) { + me.execCommand('removeFormat', 'span,a', style); + } + range = me.selection.getRange(); + + range.applyInlineStyle('span', {'style': style + ':' + value}); + mergesibling(range, cmdName,value); + range.select(); + } else { + + var span = domUtils.findParentByTagName(range.startContainer, 'span', true); + text = me.document.createTextNode('font'); + if (span && !span.children.length && !span[browser.ie ? 'innerText' : 'textContent'].replace(fillCharReg, '').length) { + //for ie hack when enter + range.insertNode(text); + if (needCmd[cmd]) { + range.selectNode(text).select(); + me.execCommand('removeFormat', 'span,a', style, null); + + span = domUtils.findParentByTagName(text, 'span', true); + range.setStartBefore(text); + + } + span && (span.style.cssText += ';' + style + ':' + value); + range.collapse(true).select(); + + + } else { + range.insertNode(text); + range.selectNode(text).select(); + span = range.document.createElement('span'); + + if (needCmd[cmd]) { + //a标签内的不处理跳过 + if (domUtils.findParentByTagName(text, 'a', true)) { + range.setStartBefore(text).setCursor(); + domUtils.remove(text); + return; + } + me.execCommand('removeFormat', 'span,a', style); + } + + span.style.cssText = style + ':' + value; + + + text.parentNode.insertBefore(span, text); + //修复,span套span 但样式不继承的问题 + if (!browser.ie || browser.ie && browser.version == 9) { + var spanParent = span.parentNode; + while (!domUtils.isBlockElm(spanParent)) { + if (spanParent.tagName == 'SPAN') { + //opera合并style不会加入";" + span.style.cssText = spanParent.style.cssText + ";" + span.style.cssText; + } + spanParent = spanParent.parentNode; + } + } + + + if (opera) { + setTimeout(function () { + range.setStart(span, 0).collapse(true); + mergesibling(range, cmdName,value); + range.select(); + }); + } else { + range.setStart(span, 0).collapse(true); + mergesibling(range,cmdName,value); + range.select(); + } + + //trace:981 + //domUtils.mergeToParent(span) + } + domUtils.remove(text); + } + + + } + return true; + }, + queryCommandValue: function (cmdName) { + var startNode = this.selection.getStart(); + + //trace:946 + if (cmdName == 'underline' || cmdName == 'strikethrough') { + var tmpNode = startNode, value; + while (tmpNode && !domUtils.isBlockElm(tmpNode) && !domUtils.isBody(tmpNode)) { + if (tmpNode.nodeType == 1) { + value = domUtils.getComputedStyle(tmpNode, style); + if (value != 'none') { + return value; + } + } + + tmpNode = tmpNode.parentNode; + } + return 'none'; + } + if (cmdName == 'fontborder') { + var tmp = startNode, val; + while (tmp && dtd.$inline[tmp.tagName]) { + if (val = domUtils.getComputedStyle(tmp, 'border')) { + + if (/1px/.test(val) && /solid/.test(val)) { + return val; + } + } + tmp = tmp.parentNode; + } + return '' + } + + if( cmdName == 'FontSize' ) { + var styleVal = domUtils.getComputedStyle(startNode, style), + tmp = /^([\d\.]+)(\w+)$/.exec( styleVal ); + + if( tmp ) { + + return Math.floor( tmp[1] ) + tmp[2]; + + } + + return styleVal; + + } + + return domUtils.getComputedStyle(startNode, style); + }, + queryCommandState: function (cmdName) { + if (!needCmd[cmdName]) + return 0; + var val = this.queryCommandValue(cmdName); + if (cmdName == 'fontborder') { + return /1px/.test(val) && /solid/.test(val) + } else { + return cmdName == 'underline' ? /underline/.test(val) : /line\-through/.test(val); + + } + + } + }; + })(p, fonts[p]); + } +}; \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/formatmatch.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/formatmatch.js new file mode 100644 index 000000000..828b3a6c9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/formatmatch.js @@ -0,0 +1,137 @@ +/** + * 格式刷,只格式inline的 + * @file + * @since 1.2.6.1 + */ + +/** + * 格式刷 + * @command formatmatch + * @method execCommand + * @remind 该操作不能复制段落格式 + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * //editor是编辑器实例 + * //获取格式刷 + * editor.execCommand( 'formatmatch' ); + * ``` + */ +UE.plugins['formatmatch'] = function(){ + + var me = this, + list = [],img, + flag = 0; + + me.addListener('reset',function(){ + list = []; + flag = 0; + }); + + function addList(type,evt){ + + if(browser.webkit){ + var target = evt.target.tagName == 'IMG' ? evt.target : null; + } + + function addFormat(range){ + + if(text){ + range.selectNode(text); + } + return range.applyInlineStyle(list[list.length-1].tagName,null,list); + + } + + me.undoManger && me.undoManger.save(); + + var range = me.selection.getRange(), + imgT = target || range.getClosedNode(); + if(img && imgT && imgT.tagName == 'IMG'){ + //trace:964 + + imgT.style.cssText += ';float:' + (img.style.cssFloat || img.style.styleFloat ||'none') + ';display:' + (img.style.display||'inline'); + + img = null; + }else{ + if(!img){ + var collapsed = range.collapsed; + if(collapsed){ + var text = me.document.createTextNode('match'); + range.insertNode(text).select(); + + + } + me.__hasEnterExecCommand = true; + //不能把block上的属性干掉 + //trace:1553 + var removeFormatAttributes = me.options.removeFormatAttributes; + me.options.removeFormatAttributes = ''; + me.execCommand('removeformat'); + me.options.removeFormatAttributes = removeFormatAttributes; + me.__hasEnterExecCommand = false; + //trace:969 + range = me.selection.getRange(); + if(list.length){ + addFormat(range); + } + if(text){ + range.setStartBefore(text).collapse(true); + + } + range.select(); + text && domUtils.remove(text); + } + + } + + + + + me.undoManger && me.undoManger.save(); + me.removeListener('mouseup',addList); + flag = 0; + } + + me.commands['formatmatch'] = { + execCommand : function( cmdName ) { + + if(flag){ + flag = 0; + list = []; + me.removeListener('mouseup',addList); + return; + } + + + + var range = me.selection.getRange(); + img = range.getClosedNode(); + if(!img || img.tagName != 'IMG'){ + range.collapse(true).shrinkBoundary(); + var start = range.startContainer; + list = domUtils.findParents(start,true,function(node){ + return !domUtils.isBlockElm(node) && node.nodeType == 1; + }); + //a不能加入格式刷, 并且克隆节点 + for(var i=0,ci;ci=list[i];i++){ + if(ci.tagName == 'A'){ + list.splice(i,1); + break; + } + } + + } + + me.addListener('mouseup',addList); + flag = 1; + + + }, + queryCommandState : function() { + return flag; + }, + notNeedUndo : 1 + }; +}; + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/horizontal.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/horizontal.js new file mode 100644 index 000000000..1a4d7769f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/horizontal.js @@ -0,0 +1,104 @@ +/** + * 插入分割线插件 + * @file + * @since 1.2.6.1 + */ + +/** + * 插入分割线 + * @command horizontal + * @method execCommand + * @param { String } cmdName 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'horizontal' ); + * ``` + */ +UE.plugins['horizontal'] = function(){ + var me = this; + me.commands['horizontal'] = { + execCommand : function( cmdName ) { + var me = this; + if(me.queryCommandState(cmdName)!==-1){ + me.execCommand('insertHtml','


    '); + var range = me.selection.getRange(), + start = range.startContainer; + if(start.nodeType == 1 && !start.childNodes[range.startOffset] ){ + + var tmp; + if(tmp = start.childNodes[range.startOffset - 1]){ + if(tmp.nodeType == 1 && tmp.tagName == 'HR'){ + if(me.options.enterTag == 'p'){ + tmp = me.document.createElement('p'); + range.insertNode(tmp); + range.setStart(tmp,0).setCursor(); + + }else{ + tmp = me.document.createElement('br'); + range.insertNode(tmp); + range.setStartBefore(tmp).setCursor(); + } + } + } + + } + return true; + } + + }, + //边界在table里不能加分隔线 + queryCommandState : function() { + return domUtils.filterNodeList(this.selection.getStartElementPath(),'table') ? -1 : 0; + } + }; +// me.addListener('delkeyup',function(){ +// var rng = this.selection.getRange(); +// if(browser.ie && browser.version > 8){ +// rng.txtToElmBoundary(true); +// if(domUtils.isStartInblock(rng)){ +// var tmpNode = rng.startContainer; +// var pre = tmpNode.previousSibling; +// if(pre && domUtils.isTagNode(pre,'hr')){ +// domUtils.remove(pre); +// rng.select(); +// return; +// } +// } +// } +// if(domUtils.isBody(rng.startContainer)){ +// var hr = rng.startContainer.childNodes[rng.startOffset -1]; +// if(hr && hr.nodeName == 'HR'){ +// var next = hr.nextSibling; +// if(next){ +// rng.setStart(next,0) +// }else if(hr.previousSibling){ +// rng.setStartAtLast(hr.previousSibling) +// }else{ +// var p = this.document.createElement('p'); +// hr.parentNode.insertBefore(p,hr); +// domUtils.fillNode(this.document,p); +// rng.setStart(p,0); +// } +// domUtils.remove(hr); +// rng.setCursor(false,true); +// } +// } +// }) + me.addListener('delkeydown',function(name,evt){ + var rng = this.selection.getRange(); + rng.txtToElmBoundary(true); + if(domUtils.isStartInblock(rng)){ + var tmpNode = rng.startContainer; + var pre = tmpNode.previousSibling; + if(pre && domUtils.isTagNode(pre,'hr')){ + domUtils.remove(pre); + rng.select(); + domUtils.preventDefault(evt); + return true; + + } + } + + }) +}; + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/iframe.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/iframe.js new file mode 100644 index 000000000..ce3a6b971 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/iframe.js @@ -0,0 +1,19 @@ +///import core +///import plugins\inserthtml.js +///commands 插入框架 +///commandsName InsertFrame +///commandsTitle 插入Iframe +///commandsDialog dialogs\insertframe + +UE.plugins['insertframe'] = function() { + var me =this; + function deleteIframe(){ + me._iframe && delete me._iframe; + } + + me.addListener("selectionchange",function(){ + deleteIframe(); + }); + +}; + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/image.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/image.js new file mode 100644 index 000000000..1cd07cb2d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/image.js @@ -0,0 +1,273 @@ +/** + * 图片插入、排版插件 + * @file + * @since 1.2.6.1 + */ + +/** + * 图片对齐方式 + * @command imagefloat + * @method execCommand + * @remind 值center为独占一行居中 + * @param { String } cmd 命令字符串 + * @param { String } align 对齐方式,可传left、right、none、center + * @remaind center表示图片独占一行 + * @example + * ```javascript + * editor.execCommand( 'imagefloat', 'center' ); + * ``` + */ + +/** + * 如果选区所在位置是图片区域 + * @command imagefloat + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回图片对齐方式 + * @example + * ```javascript + * editor.queryCommandValue( 'imagefloat' ); + * ``` + */ + +UE.commands['imagefloat'] = { + execCommand:function (cmd, align) { + var me = this, + range = me.selection.getRange(); + if (!range.collapsed) { + var img = range.getClosedNode(); + if (img && img.tagName == 'IMG') { + switch (align) { + case 'left': + case 'right': + case 'none': + var pN = img.parentNode, tmpNode, pre, next; + while (dtd.$inline[pN.tagName] || pN.tagName == 'A') { + pN = pN.parentNode; + } + tmpNode = pN; + if (tmpNode.tagName == 'P' && domUtils.getStyle(tmpNode, 'text-align') == 'center') { + if (!domUtils.isBody(tmpNode) && domUtils.getChildCount(tmpNode, function (node) { + return !domUtils.isBr(node) && !domUtils.isWhitespace(node); + }) == 1) { + pre = tmpNode.previousSibling; + next = tmpNode.nextSibling; + if (pre && next && pre.nodeType == 1 && next.nodeType == 1 && pre.tagName == next.tagName && domUtils.isBlockElm(pre)) { + pre.appendChild(tmpNode.firstChild); + while (next.firstChild) { + pre.appendChild(next.firstChild); + } + domUtils.remove(tmpNode); + domUtils.remove(next); + } else { + domUtils.setStyle(tmpNode, 'text-align', ''); + } + + + } + + range.selectNode(img).select(); + } + domUtils.setStyle(img, 'float', align == 'none' ? '' : align); + if(align == 'none'){ + domUtils.removeAttributes(img,'align'); + } + + break; + case 'center': + if (me.queryCommandValue('imagefloat') != 'center') { + pN = img.parentNode; + domUtils.setStyle(img, 'float', ''); + domUtils.removeAttributes(img,'align'); + tmpNode = img; + while (pN && domUtils.getChildCount(pN, function (node) { + return !domUtils.isBr(node) && !domUtils.isWhitespace(node); + }) == 1 + && (dtd.$inline[pN.tagName] || pN.tagName == 'A')) { + tmpNode = pN; + pN = pN.parentNode; + } + range.setStartBefore(tmpNode).setCursor(false); + pN = me.document.createElement('div'); + pN.appendChild(tmpNode); + domUtils.setStyle(tmpNode, 'float', ''); + + me.execCommand('insertHtml', '

    ' + pN.innerHTML + '

    '); + + tmpNode = me.document.getElementById('_img_parent_tmp'); + tmpNode.removeAttribute('id'); + tmpNode = tmpNode.firstChild; + range.selectNode(tmpNode).select(); + //去掉后边多余的元素 + next = tmpNode.parentNode.nextSibling; + if (next && domUtils.isEmptyNode(next)) { + domUtils.remove(next); + } + + } + + break; + } + + } + } + }, + queryCommandValue:function () { + var range = this.selection.getRange(), + startNode, floatStyle; + if (range.collapsed) { + return 'none'; + } + startNode = range.getClosedNode(); + if (startNode && startNode.nodeType == 1 && startNode.tagName == 'IMG') { + floatStyle = domUtils.getComputedStyle(startNode, 'float') || startNode.getAttribute('align'); + + if (floatStyle == 'none') { + floatStyle = domUtils.getComputedStyle(startNode.parentNode, 'text-align') == 'center' ? 'center' : floatStyle; + } + return { + left:1, + right:1, + center:1 + }[floatStyle] ? floatStyle : 'none'; + } + return 'none'; + + + }, + queryCommandState:function () { + var range = this.selection.getRange(), + startNode; + + if (range.collapsed) return -1; + + startNode = range.getClosedNode(); + if (startNode && startNode.nodeType == 1 && startNode.tagName == 'IMG') { + return 0; + } + return -1; + } +}; + + +/** + * 插入图片 + * @command insertimage + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { Object } opt 属性键值对,这些属性都将被复制到当前插入图片 + * @remind 该命令第二个参数可接受一个图片配置项对象的数组,可以插入多张图片, + * 此时数组的每一个元素都是一个Object类型的图片属性集合。 + * @example + * ```javascript + * editor.execCommand( 'insertimage', { + * src:'a/b/c.jpg', + * width:'100', + * height:'100' + * } ); + * ``` + * @example + * ```javascript + * editor.execCommand( 'insertimage', [{ + * src:'a/b/c.jpg', + * width:'100', + * height:'100' + * },{ + * src:'a/b/d.jpg', + * width:'100', + * height:'100' + * }] ); + * ``` + */ + +UE.commands['insertimage'] = { + execCommand:function (cmd, opt) { + + opt = utils.isArray(opt) ? opt : [opt]; + if (!opt.length) { + return; + } + var me = this, + range = me.selection.getRange(), + img = range.getClosedNode(); + + if(me.fireEvent('beforeinsertimage', opt) === true){ + return; + } + + function unhtmlData(imgCi) { + + utils.each('width,height,border,hspace,vspace'.split(','), function (item) { + + if (imgCi[item]) { + imgCi[item] = parseInt(imgCi[item], 10) || 0; + } + }); + + utils.each('src,_src'.split(','), function (item) { + + if (imgCi[item]) { + imgCi[item] = utils.unhtmlForUrl(imgCi[item]); + } + }); + utils.each('title,alt'.split(','), function (item) { + + if (imgCi[item]) { + imgCi[item] = utils.unhtml(imgCi[item]); + } + }); + } + + if (img && /img/i.test(img.tagName) && (img.className != "edui-faked-video" || img.className.indexOf("edui-upload-video")!=-1) && !img.getAttribute("word_img")) { + var first = opt.shift(); + var floatStyle = first['floatStyle']; + delete first['floatStyle']; +//// img.style.border = (first.border||0) +"px solid #000"; +//// img.style.margin = (first.margin||0) +"px"; +// img.style.cssText += ';margin:' + (first.margin||0) +"px;" + 'border:' + (first.border||0) +"px solid #000"; + domUtils.setAttributes(img, first); + me.execCommand('imagefloat', floatStyle); + if (opt.length > 0) { + range.setStartAfter(img).setCursor(false, true); + me.execCommand('insertimage', opt); + } + + } else { + var html = [], str = '', ci; + ci = opt[0]; + if (opt.length == 1) { + unhtmlData(ci); + + str = '' + ci.alt + ''; + if (ci['floatStyle'] == 'center') { + str = '

    ' + str + '

    '; + } + html.push(str); + + } else { + for (var i = 0; ci = opt[i++];) { + unhtmlData(ci); + str = '

    '; + html.push(str); + } + } + + me.execCommand('insertHtml', html.join('')); + } + + me.fireEvent('afterinsertimage', opt) + } +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/indent.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/indent.js new file mode 100644 index 000000000..0afadada8 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/indent.js @@ -0,0 +1,27 @@ +/** + * 首行缩进 + * @file + * @since 1.2.6.1 + */ + +/** + * 缩进 + * @command indent + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'indent' ); + * ``` + */ +UE.commands['indent'] = { + execCommand : function() { + var me = this,value = me.queryCommandState("indent") ? "0em" : (me.options.indentValue || '2em'); + me.execCommand('Paragraph','p',{style:'text-indent:'+ value}); + }, + queryCommandState : function() { + var pN = domUtils.filterNodeList(this.selection.getStartElementPath(),'p h1 h2 h3 h4 h5 h6'); + return pN && pN.style.textIndent && parseInt(pN.style.textIndent) ? 1 : 0; + } + +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/insertcode.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/insertcode.js new file mode 100644 index 000000000..2155fd6b3 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/insertcode.js @@ -0,0 +1,540 @@ +/** + * 插入代码插件 + * @file + * @since 1.2.6.1 + */ + +UE.plugins['insertcode'] = function() { + var me = this; + me.ready(function(){ + utils.cssRule('pre','pre{margin:.5em 0;padding:.4em .6em;border-radius:8px;background:#f8f8f8;}', + me.document) + }); + me.setOpt('insertcode',{ + 'as3':'ActionScript3', + 'bash':'Bash/Shell', + 'cpp':'C/C++', + 'css':'Css', + 'cf':'CodeFunction', + 'c#':'C#', + 'delphi':'Delphi', + 'diff':'Diff', + 'erlang':'Erlang', + 'groovy':'Groovy', + 'html':'Html', + 'java':'Java', + 'jfx':'JavaFx', + 'js':'Javascript', + 'pl':'Perl', + 'php':'Php', + 'plain':'Plain Text', + 'ps':'PowerShell', + 'python':'Python', + 'ruby':'Ruby', + 'scala':'Scala', + 'sql':'Sql', + 'vb':'Vb', + 'xml':'Xml' + }); + + /** + * 插入代码 + * @command insertcode + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } lang 插入代码的语言 + * @example + * ```javascript + * editor.execCommand( 'insertcode', 'javascript' ); + * ``` + */ + + /** + * 如果选区所在位置是插入插入代码区域,返回代码的语言 + * @command insertcode + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回代码的语言 + * @example + * ```javascript + * editor.queryCommandValue( 'insertcode' ); + * ``` + */ + + me.commands['insertcode'] = { + execCommand : function(cmd,lang){ + var me = this, + rng = me.selection.getRange(), + pre = domUtils.findParentByTagName(rng.startContainer,'pre',true); + if(pre){ + pre.className = 'brush:'+lang+';toolbar:false;'; + }else{ + var code = ''; + if(rng.collapsed){ + code = browser.ie && browser.ie11below ? (browser.version <= 8 ? ' ':''):'
    '; + }else{ + var frag = rng.extractContents(); + var div = me.document.createElement('div'); + div.appendChild(frag); + + utils.each(UE.filterNode(UE.htmlparser(div.innerHTML.replace(/[\r\t]/g,'')),me.options.filterTxtRules).children,function(node){ + if(browser.ie && browser.ie11below && browser.version > 8){ + + if(node.type =='element'){ + if(node.tagName == 'br'){ + code += '\n' + }else if(!dtd.$empty[node.tagName]){ + utils.each(node.children,function(cn){ + if(cn.type =='element'){ + if(cn.tagName == 'br'){ + code += '\n' + }else if(!dtd.$empty[node.tagName]){ + code += cn.innerText(); + } + }else{ + code += cn.data + } + }) + if(!/\n$/.test(code)){ + code += '\n'; + } + } + }else{ + code += node.data + '\n' + } + if(!node.nextSibling() && /\n$/.test(code)){ + code = code.replace(/\n$/,''); + } + }else{ + if(browser.ie && browser.ie11below){ + + if(node.type =='element'){ + if(node.tagName == 'br'){ + code += '
    ' + }else if(!dtd.$empty[node.tagName]){ + utils.each(node.children,function(cn){ + if(cn.type =='element'){ + if(cn.tagName == 'br'){ + code += '
    ' + }else if(!dtd.$empty[node.tagName]){ + code += cn.innerText(); + } + }else{ + code += cn.data + } + }); + if(!/br>$/.test(code)){ + code += '
    '; + } + } + }else{ + code += node.data + '
    ' + } + if(!node.nextSibling() && /
    $/.test(code)){ + code = code.replace(/
    $/,''); + } + + }else{ + code += (node.type == 'element' ? (dtd.$empty[node.tagName] ? '' : node.innerText()) : node.data); + if(!/br\/?\s*>$/.test(code)){ + if(!node.nextSibling()) + return; + code += '
    ' + } + } + + } + + }); + } + me.execCommand('inserthtml','
    '+code+'
    ',true); + + pre = me.document.getElementById('coder'); + domUtils.removeAttributes(pre,'id'); + var tmpNode = pre.previousSibling; + + if(tmpNode && (tmpNode.nodeType == 3 && tmpNode.nodeValue.length == 1 && browser.ie && browser.version == 6 || domUtils.isEmptyBlock(tmpNode))){ + + domUtils.remove(tmpNode) + } + var rng = me.selection.getRange(); + if(domUtils.isEmptyBlock(pre)){ + rng.setStart(pre,0).setCursor(false,true) + }else{ + rng.selectNodeContents(pre).select() + } + } + + + + }, + queryCommandValue : function(){ + var path = this.selection.getStartElementPath(); + var lang = ''; + utils.each(path,function(node){ + if(node.nodeName =='PRE'){ + var match = node.className.match(/brush:([^;]+)/); + lang = match && match[1] ? match[1] : ''; + return false; + } + }); + return lang; + } + }; + + me.addInputRule(function(root){ + utils.each(root.getNodesByTagName('pre'),function(pre){ + var brs = pre.getNodesByTagName('br'); + if(brs.length){ + browser.ie && browser.ie11below && browser.version > 8 && utils.each(brs,function(br){ + var txt = UE.uNode.createText('\n'); + br.parentNode.insertBefore(txt,br); + br.parentNode.removeChild(br); + }); + return; + } + if(browser.ie && browser.ie11below && browser.version > 8) + return; + var code = pre.innerText().split(/\n/); + pre.innerHTML(''); + utils.each(code,function(c){ + if(c.length){ + pre.appendChild(UE.uNode.createText(c)); + } + pre.appendChild(UE.uNode.createElement('br')) + }) + }) + }); + me.addOutputRule(function(root){ + utils.each(root.getNodesByTagName('pre'),function(pre){ + var code = ''; + utils.each(pre.children,function(n){ + if(n.type == 'text'){ + //在ie下文本内容有可能末尾带有\n要去掉 + //trace:3396 + code += n.data.replace(/[ ]/g,' ').replace(/\n$/,''); + }else{ + if(n.tagName == 'br'){ + code += '\n' + }else{ + code += (!dtd.$empty[n.tagName] ? '' : n.innerText()); + } + + } + + }); + + pre.innerText(code.replace(/( |\n)+$/,'')) + }) + }); + //不需要判断highlight的command列表 + me.notNeedCodeQuery ={ + help:1, + undo:1, + redo:1, + source:1, + print:1, + searchreplace:1, + fullscreen:1, + preview:1, + insertparagraph:1, + elementpath:1, + insertcode:1, + inserthtml:1, + selectall:1 + }; + //将queyCommamndState重置 + var orgQuery = me.queryCommandState; + me.queryCommandState = function(cmd){ + var me = this; + + if(!me.notNeedCodeQuery[cmd.toLowerCase()] && me.selection && me.queryCommandValue('insertcode')){ + return -1; + } + return UE.Editor.prototype.queryCommandState.apply(this,arguments) + }; + me.addListener('beforeenterkeydown',function(){ + var rng = me.selection.getRange(); + var pre = domUtils.findParentByTagName(rng.startContainer,'pre',true); + if(pre){ + me.fireEvent('saveScene'); + if(!rng.collapsed){ + rng.deleteContents(); + } + if(!browser.ie || browser.ie9above){ + var tmpNode = me.document.createElement('br'),pre; + rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true); + var next = tmpNode.nextSibling; + if(!next && (!browser.ie || browser.version > 10)){ + rng.insertNode(tmpNode.cloneNode(false)); + }else{ + rng.setStartAfter(tmpNode); + } + pre = tmpNode.previousSibling; + var tmp; + while(pre ){ + tmp = pre; + pre = pre.previousSibling; + if(!pre || pre.nodeName == 'BR'){ + pre = tmp; + break; + } + } + if(pre){ + var str = ''; + while(pre && pre.nodeName != 'BR' && new RegExp('^[\\s'+domUtils.fillChar+']*$').test(pre.nodeValue)){ + str += pre.nodeValue; + pre = pre.nextSibling; + } + if(pre.nodeName != 'BR'){ + var match = pre.nodeValue.match(new RegExp('^([\\s'+domUtils.fillChar+']+)')); + if(match && match[1]){ + str += match[1] + } + + } + if(str){ + str = me.document.createTextNode(str); + rng.insertNode(str).setStartAfter(str); + } + } + rng.collapse(true).select(true); + }else{ + if(browser.version > 8){ + + var txt = me.document.createTextNode('\n'); + var start = rng.startContainer; + if(rng.startOffset == 0){ + var preNode = start.previousSibling; + if(preNode){ + rng.insertNode(txt); + var fillchar = me.document.createTextNode(' '); + rng.setStartAfter(txt).insertNode(fillchar).setStart(fillchar,0).collapse(true).select(true) + } + }else{ + rng.insertNode(txt).setStartAfter(txt); + var fillchar = me.document.createTextNode(' '); + start = rng.startContainer.childNodes[rng.startOffset]; + if(start && !/^\n/.test(start.nodeValue)){ + rng.setStartBefore(txt) + } + rng.insertNode(fillchar).setStart(fillchar,0).collapse(true).select(true) + } + + }else{ + var tmpNode = me.document.createElement('br'); + rng.insertNode(tmpNode); + rng.insertNode(me.document.createTextNode(domUtils.fillChar)); + rng.setStartAfter(tmpNode); + pre = tmpNode.previousSibling; + var tmp; + while(pre ){ + tmp = pre; + pre = pre.previousSibling; + if(!pre || pre.nodeName == 'BR'){ + pre = tmp; + break; + } + } + if(pre){ + var str = ''; + while(pre && pre.nodeName != 'BR' && new RegExp('^[ '+domUtils.fillChar+']*$').test(pre.nodeValue)){ + str += pre.nodeValue; + pre = pre.nextSibling; + } + if(pre.nodeName != 'BR'){ + var match = pre.nodeValue.match(new RegExp('^([ '+domUtils.fillChar+']+)')); + if(match && match[1]){ + str += match[1] + } + + } + + str = me.document.createTextNode(str); + rng.insertNode(str).setStartAfter(str); + } + rng.collapse(true).select(); + } + + + } + me.fireEvent('saveScene'); + return true; + } + + + }); + + me.addListener('tabkeydown',function(cmd,evt){ + var rng = me.selection.getRange(); + var pre = domUtils.findParentByTagName(rng.startContainer,'pre',true); + if(pre){ + me.fireEvent('saveScene'); + if(evt.shiftKey){ + + }else{ + if(!rng.collapsed){ + var bk = rng.createBookmark(); + var start = bk.start.previousSibling; + + while(start){ + if(pre.firstChild === start && !domUtils.isBr(start)){ + pre.insertBefore(me.document.createTextNode(' '),start); + + break; + } + if(domUtils.isBr(start)){ + pre.insertBefore(me.document.createTextNode(' '),start.nextSibling); + + break; + } + start = start.previousSibling; + } + var end = bk.end; + start = bk.start.nextSibling; + if(pre.firstChild === bk.start){ + pre.insertBefore(me.document.createTextNode(' '),start.nextSibling) + + } + while(start && start !== end){ + if(domUtils.isBr(start) && start.nextSibling){ + if(start.nextSibling === end){ + break; + } + pre.insertBefore(me.document.createTextNode(' '),start.nextSibling) + } + + start = start.nextSibling; + } + rng.moveToBookmark(bk).select(); + }else{ + var tmpNode = me.document.createTextNode(' '); + rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true).select(true); + } + } + + + me.fireEvent('saveScene'); + return true; + } + + + }); + + + me.addListener('beforeinserthtml',function(evtName,html){ + var me = this, + rng = me.selection.getRange(), + pre = domUtils.findParentByTagName(rng.startContainer,'pre',true); + if(pre){ + if(!rng.collapsed){ + rng.deleteContents() + } + var htmlstr = ''; + if(browser.ie && browser.version > 8){ + + utils.each(UE.filterNode(UE.htmlparser(html),me.options.filterTxtRules).children,function(node){ + if(node.type =='element'){ + if(node.tagName == 'br'){ + htmlstr += '\n' + }else if(!dtd.$empty[node.tagName]){ + utils.each(node.children,function(cn){ + if(cn.type =='element'){ + if(cn.tagName == 'br'){ + htmlstr += '\n' + }else if(!dtd.$empty[node.tagName]){ + htmlstr += cn.innerText(); + } + }else{ + htmlstr += cn.data + } + }) + if(!/\n$/.test(htmlstr)){ + htmlstr += '\n'; + } + } + }else{ + htmlstr += node.data + '\n' + } + if(!node.nextSibling() && /\n$/.test(htmlstr)){ + htmlstr = htmlstr.replace(/\n$/,''); + } + }); + var tmpNode = me.document.createTextNode(utils.html(htmlstr.replace(/ /g,' '))); + rng.insertNode(tmpNode).selectNode(tmpNode).select(); + }else{ + var frag = me.document.createDocumentFragment(); + + utils.each(UE.filterNode(UE.htmlparser(html),me.options.filterTxtRules).children,function(node){ + if(node.type =='element'){ + if(node.tagName == 'br'){ + frag.appendChild(me.document.createElement('br')) + }else if(!dtd.$empty[node.tagName]){ + utils.each(node.children,function(cn){ + if(cn.type =='element'){ + if(cn.tagName == 'br'){ + + frag.appendChild(me.document.createElement('br')) + }else if(!dtd.$empty[node.tagName]){ + frag.appendChild(me.document.createTextNode(utils.html(cn.innerText().replace(/ /g,' ')))); + + } + }else{ + frag.appendChild(me.document.createTextNode(utils.html( cn.data.replace(/ /g,' ')))); + + } + }) + if(frag.lastChild.nodeName != 'BR'){ + frag.appendChild(me.document.createElement('br')) + } + } + }else{ + frag.appendChild(me.document.createTextNode(utils.html( node.data.replace(/ /g,' ')))); + } + if(!node.nextSibling() && frag.lastChild.nodeName == 'BR'){ + frag.removeChild(frag.lastChild) + } + + + }); + rng.insertNode(frag).select(); + + } + + return true; + } + }); + //方向键的处理 + me.addListener('keydown',function(cmd,evt){ + var me = this,keyCode = evt.keyCode || evt.which; + if(keyCode == 40){ + var rng = me.selection.getRange(),pre,start = rng.startContainer; + if(rng.collapsed && (pre = domUtils.findParentByTagName(rng.startContainer,'pre',true)) && !pre.nextSibling){ + var last = pre.lastChild + while(last && last.nodeName == 'BR'){ + last = last.previousSibling; + } + if(last === start || rng.startContainer === pre && rng.startOffset == pre.childNodes.length){ + me.execCommand('insertparagraph'); + domUtils.preventDefault(evt) + } + + } + } + }); + //trace:3395 + me.addListener('delkeydown',function(type,evt){ + var rng = this.selection.getRange(); + rng.txtToElmBoundary(true); + var start = rng.startContainer; + if(domUtils.isTagNode(start,'pre') && rng.collapsed && domUtils.isStartInblock(rng)){ + var p = me.document.createElement('p'); + domUtils.fillNode(me.document,p); + start.parentNode.insertBefore(p,start); + domUtils.remove(start); + rng.setStart(p,0).setCursor(false,true); + domUtils.preventDefault(evt); + return true; + } + }) +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/insertfile.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/insertfile.js new file mode 100644 index 000000000..b4d685e22 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/insertfile.js @@ -0,0 +1,69 @@ +/** + * 插入附件 + */ +UE.plugin.register('insertfile', function (){ + + var me = this; + + function getFileIcon(url){ + var ext = url.substr(url.lastIndexOf('.') + 1).toLowerCase(), + maps = { + "rar":"icon_rar.gif", + "zip":"icon_rar.gif", + "tar":"icon_rar.gif", + "gz":"icon_rar.gif", + "bz2":"icon_rar.gif", + "doc":"icon_doc.gif", + "docx":"icon_doc.gif", + "pdf":"icon_pdf.gif", + "mp3":"icon_mp3.gif", + "xls":"icon_xls.gif", + "chm":"icon_chm.gif", + "ppt":"icon_ppt.gif", + "pptx":"icon_ppt.gif", + "avi":"icon_mv.gif", + "rmvb":"icon_mv.gif", + "wmv":"icon_mv.gif", + "flv":"icon_mv.gif", + "swf":"icon_mv.gif", + "rm":"icon_mv.gif", + "exe":"icon_exe.gif", + "psd":"icon_psd.gif", + "txt":"icon_txt.gif", + "jpg":"icon_jpg.gif", + "png":"icon_jpg.gif", + "jpeg":"icon_jpg.gif", + "gif":"icon_jpg.gif", + "ico":"icon_jpg.gif", + "bmp":"icon_jpg.gif" + }; + return maps[ext] ? maps[ext]:maps['txt']; + } + + return { + commands:{ + 'insertfile': { + execCommand: function (command, filelist){ + filelist = utils.isArray(filelist) ? filelist : [filelist]; + + var i, item, icon, title, + html = '', + URL = me.getOpt('UEDITOR_HOME_URL'), + iconDir = URL + (URL.substr(URL.length - 1) == '/' ? '':'/') + 'dialogs/attachment/fileTypeImages/'; + for (i = 0; i < filelist.length; i++) { + item = filelist[i]; + icon = iconDir + getFileIcon(item.url); + title = item.title || item.url.substr(item.url.lastIndexOf('/') + 1); + html += '

    ' + + '' + + '' + title + '' + + '

    '; + } + me.execCommand('insertHtml', html); + } + } + } + } +}); + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/inserthtml.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/inserthtml.js new file mode 100644 index 000000000..7063692a5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/inserthtml.js @@ -0,0 +1,255 @@ +/** + * 插入html字符串插件 + * @file + * @since 1.2.6.1 + */ + +/** + * 插入html代码 + * @command inserthtml + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } html 插入的html字符串 + * @remaind 插入的标签内容是在当前的选区位置上插入,如果当前是闭合状态,那直接插入内容, 如果当前是选中状态,将先清除当前选中内容后,再做插入 + * @warning 注意:该命令会对当前选区的位置,对插入的内容进行过滤转换处理。 过滤的规则遵循html语意化的原则。 + * @example + * ```javascript + * //xxx[BB]xxx 当前选区为非闭合选区,选中BB这两个文本 + * //执行命令,插入CC + * //插入后的效果 xxxCCxxx + * //

    xx|xxx

    当前选区为闭合状态 + * //插入

    CC

    + * //结果

    xx

    CC

    xxx

    + * //

    xxxx

    |

    xxx

    当前选区在两个p标签之间 + * //插入 xxxx + * //结果

    xxxx

    xxxx

    xxx

    + * ``` + */ + +UE.commands['inserthtml'] = { + execCommand: function (command,html,notNeedFilter){ + var me = this, + range, + div; + if(!html){ + return; + } + if(me.fireEvent('beforeinserthtml',html) === true){ + return; + } + range = me.selection.getRange(); + div = range.document.createElement( 'div' ); + div.style.display = 'inline'; + + if (!notNeedFilter) { + var root = UE.htmlparser(html); + //如果给了过滤规则就先进行过滤 + if(me.options.filterRules){ + UE.filterNode(root,me.options.filterRules); + } + //执行默认的处理 + me.filterInputRule(root); + html = root.toHtml() + } + div.innerHTML = utils.trim( html ); + + if ( !range.collapsed ) { + var tmpNode = range.startContainer; + if(domUtils.isFillChar(tmpNode)){ + range.setStartBefore(tmpNode) + } + tmpNode = range.endContainer; + if(domUtils.isFillChar(tmpNode)){ + range.setEndAfter(tmpNode) + } + range.txtToElmBoundary(); + //结束边界可能放到了br的前边,要把br包含进来 + // x[xxx]
    + if(range.endContainer && range.endContainer.nodeType == 1){ + tmpNode = range.endContainer.childNodes[range.endOffset]; + if(tmpNode && domUtils.isBr(tmpNode)){ + range.setEndAfter(tmpNode); + } + } + if(range.startOffset == 0){ + tmpNode = range.startContainer; + if(domUtils.isBoundaryNode(tmpNode,'firstChild') ){ + tmpNode = range.endContainer; + if(range.endOffset == (tmpNode.nodeType == 3 ? tmpNode.nodeValue.length : tmpNode.childNodes.length) && domUtils.isBoundaryNode(tmpNode,'lastChild')){ + me.body.innerHTML = '

    '+(browser.ie ? '' : '
    ')+'

    '; + range.setStart(me.body.firstChild,0).collapse(true) + + } + } + } + !range.collapsed && range.deleteContents(); + if(range.startContainer.nodeType == 1){ + var child = range.startContainer.childNodes[range.startOffset],pre; + if(child && domUtils.isBlockElm(child) && (pre = child.previousSibling) && domUtils.isBlockElm(pre)){ + range.setEnd(pre,pre.childNodes.length).collapse(); + while(child.firstChild){ + pre.appendChild(child.firstChild); + } + domUtils.remove(child); + } + } + + } + + + var child,parent,pre,tmp,hadBreak = 0, nextNode; + //如果当前位置选中了fillchar要干掉,要不会产生空行 + if(range.inFillChar()){ + child = range.startContainer; + if(domUtils.isFillChar(child)){ + range.setStartBefore(child).collapse(true); + domUtils.remove(child); + }else if(domUtils.isFillChar(child,true)){ + child.nodeValue = child.nodeValue.replace(fillCharReg,''); + range.startOffset--; + range.collapsed && range.collapse(true) + } + } + //列表单独处理 + var li = domUtils.findParentByTagName(range.startContainer,'li',true); + if(li){ + var next,last; + while(child = div.firstChild){ + //针对hr单独处理一下先 + while(child && (child.nodeType == 3 || !domUtils.isBlockElm(child) || child.tagName=='HR' )){ + next = child.nextSibling; + range.insertNode( child).collapse(); + last = child; + child = next; + + } + if(child){ + if(/^(ol|ul)$/i.test(child.tagName)){ + while(child.firstChild){ + last = child.firstChild; + domUtils.insertAfter(li,child.firstChild); + li = li.nextSibling; + } + domUtils.remove(child) + }else{ + var tmpLi; + next = child.nextSibling; + tmpLi = me.document.createElement('li'); + domUtils.insertAfter(li,tmpLi); + tmpLi.appendChild(child); + last = child; + child = next; + li = tmpLi; + } + } + } + li = domUtils.findParentByTagName(range.startContainer,'li',true); + if(domUtils.isEmptyBlock(li)){ + domUtils.remove(li) + } + if(last){ + + range.setStartAfter(last).collapse(true).select(true) + } + }else{ + while ( child = div.firstChild ) { + if(hadBreak){ + var p = me.document.createElement('p'); + while(child && (child.nodeType == 3 || !dtd.$block[child.tagName])){ + nextNode = child.nextSibling; + p.appendChild(child); + child = nextNode; + } + if(p.firstChild){ + + child = p + } + } + range.insertNode( child ); + nextNode = child.nextSibling; + if ( !hadBreak && child.nodeType == domUtils.NODE_ELEMENT && domUtils.isBlockElm( child ) ){ + + parent = domUtils.findParent( child,function ( node ){ return domUtils.isBlockElm( node ); } ); + if ( parent && parent.tagName.toLowerCase() != 'body' && !(dtd[parent.tagName][child.nodeName] && child.parentNode === parent)){ + if(!dtd[parent.tagName][child.nodeName]){ + pre = parent; + }else{ + tmp = child.parentNode; + while (tmp !== parent){ + pre = tmp; + tmp = tmp.parentNode; + + } + } + + + domUtils.breakParent( child, pre || tmp ); + //去掉break后前一个多余的节点

    |<[p> ==>

    |

    + var pre = child.previousSibling; + domUtils.trimWhiteTextNode(pre); + if(!pre.childNodes.length){ + domUtils.remove(pre); + } + //trace:2012,在非ie的情况,切开后剩下的节点有可能不能点入光标添加br占位 + + if(!browser.ie && + (next = child.nextSibling) && + domUtils.isBlockElm(next) && + next.lastChild && + !domUtils.isBr(next.lastChild)){ + next.appendChild(me.document.createElement('br')); + } + hadBreak = 1; + } + } + var next = child.nextSibling; + if(!div.firstChild && next && domUtils.isBlockElm(next)){ + + range.setStart(next,0).collapse(true); + break; + } + range.setEndAfter( child ).collapse(); + + } + + child = range.startContainer; + + if(nextNode && domUtils.isBr(nextNode)){ + domUtils.remove(nextNode) + } + //用chrome可能有空白展位符 + if(domUtils.isBlockElm(child) && domUtils.isEmptyNode(child)){ + if(nextNode = child.nextSibling){ + domUtils.remove(child); + if(nextNode.nodeType == 1 && dtd.$block[nextNode.tagName]){ + + range.setStart(nextNode,0).collapse(true).shrinkBoundary() + } + }else{ + + try{ + child.innerHTML = browser.ie ? domUtils.fillChar : '
    '; + }catch(e){ + range.setStartBefore(child); + domUtils.remove(child) + } + + } + + } + //加上true因为在删除表情等时会删两次,第一次是删的fillData + try{ + range.select(true); + }catch(e){} + + } + + + + setTimeout(function(){ + range = me.selection.getRange(); + range.scrollToView(me.autoHeightEnabled,me.autoHeightEnabled ? domUtils.getXY(me.iframe).y:0); + me.fireEvent('afterinserthtml', html); + },200); + } +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/insertparagraph.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/insertparagraph.js new file mode 100644 index 000000000..ad2ad2756 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/insertparagraph.js @@ -0,0 +1,44 @@ +/** + * 插入段落 + * @file + * @since 1.2.6.1 + */ + + +/** + * 插入段落 + * @command insertparagraph + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * //editor是编辑器实例 + * editor.execCommand( 'insertparagraph' ); + * ``` + */ + +UE.commands['insertparagraph'] = { + execCommand : function( cmdName,front) { + var me = this, + range = me.selection.getRange(), + start = range.startContainer,tmpNode; + while(start ){ + if(domUtils.isBody(start)){ + break; + } + tmpNode = start; + start = start.parentNode; + } + if(tmpNode){ + var p = me.document.createElement('p'); + if(front){ + tmpNode.parentNode.insertBefore(p,tmpNode) + }else{ + tmpNode.parentNode.insertBefore(p,tmpNode.nextSibling) + } + domUtils.fillNode(me.document,p); + range.setStart(p,0).setCursor(false,true); + } + } +}; + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/justify.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/justify.js new file mode 100644 index 000000000..8663ea864 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/justify.js @@ -0,0 +1,114 @@ +/** + * 段落格式 + * @file + * @since 1.2.6.1 + */ + +/** + * 段落对齐方式 + * @command justify + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } align 对齐方式:left => 居左,right => 居右,center => 居中,justify => 两端对齐 + * @example + * ```javascript + * editor.execCommand( 'justify', 'center' ); + * ``` + */ +/** + * 如果选区所在位置是段落区域,返回当前段落对齐方式 + * @command justify + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回段落对齐方式 + * @example + * ```javascript + * editor.queryCommandValue( 'justify' ); + * ``` + */ + +UE.plugins['justify']=function(){ + var me=this, + block = domUtils.isBlockElm, + defaultValue = { + left:1, + right:1, + center:1, + justify:1 + }, + doJustify = function (range, style) { + var bookmark = range.createBookmark(), + filterFn = function (node) { + return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' && !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace(node); + }; + + range.enlarge(true); + var bookmark2 = range.createBookmark(), + current = domUtils.getNextDomNode(bookmark2.start, false, filterFn), + tmpRange = range.cloneRange(), + tmpNode; + while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) { + if (current.nodeType == 3 || !block(current)) { + tmpRange.setStartBefore(current); + while (current && current !== bookmark2.end && !block(current)) { + tmpNode = current; + current = domUtils.getNextDomNode(current, false, null, function (node) { + return !block(node); + }); + } + tmpRange.setEndAfter(tmpNode); + var common = tmpRange.getCommonAncestor(); + if (!domUtils.isBody(common) && block(common)) { + domUtils.setStyles(common, utils.isString(style) ? {'text-align':style} : style); + current = common; + } else { + var p = range.document.createElement('p'); + domUtils.setStyles(p, utils.isString(style) ? {'text-align':style} : style); + var frag = tmpRange.extractContents(); + p.appendChild(frag); + tmpRange.insertNode(p); + current = p; + } + current = domUtils.getNextDomNode(current, false, filterFn); + } else { + current = domUtils.getNextDomNode(current, true, filterFn); + } + } + return range.moveToBookmark(bookmark2).moveToBookmark(bookmark); + }; + + UE.commands['justify'] = { + execCommand:function (cmdName, align) { + var range = this.selection.getRange(), + txt; + + //闭合时单独处理 + if (range.collapsed) { + txt = this.document.createTextNode('p'); + range.insertNode(txt); + } + doJustify(range, align); + if (txt) { + range.setStartBefore(txt).collapse(true); + domUtils.remove(txt); + } + + range.select(); + + + return true; + }, + queryCommandValue:function () { + var startNode = this.selection.getStart(), + value = domUtils.getComputedStyle(startNode, 'text-align'); + return defaultValue[value] ? value : 'left'; + }, + queryCommandState:function () { + var start = this.selection.getStart(), + cell = start && domUtils.findParentByTagName(start, ["td", "th","caption"], true); + + return cell? -1:0; + } + + }; +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/keystrokes.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/keystrokes.js new file mode 100644 index 000000000..b82e75d36 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/keystrokes.js @@ -0,0 +1,214 @@ +/* 处理特殊键的兼容性问题 */ +UE.plugins['keystrokes'] = function() { + var me = this; + var collapsed = true; + me.addListener('keydown', function(type, evt) { + var keyCode = evt.keyCode || evt.which, + rng = me.selection.getRange(); + + //处理全选的情况 + if(!rng.collapsed && !(evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) && (keyCode >= 65 && keyCode <=90 + || keyCode >= 48 && keyCode <= 57 || + keyCode >= 96 && keyCode <= 111 || { + 13:1, + 8:1, + 46:1 + }[keyCode]) + ){ + + var tmpNode = rng.startContainer; + if(domUtils.isFillChar(tmpNode)){ + rng.setStartBefore(tmpNode) + } + tmpNode = rng.endContainer; + if(domUtils.isFillChar(tmpNode)){ + rng.setEndAfter(tmpNode) + } + rng.txtToElmBoundary(); + //结束边界可能放到了br的前边,要把br包含进来 + // x[xxx]
    + if(rng.endContainer && rng.endContainer.nodeType == 1){ + tmpNode = rng.endContainer.childNodes[rng.endOffset]; + if(tmpNode && domUtils.isBr(tmpNode)){ + rng.setEndAfter(tmpNode); + } + } + if(rng.startOffset == 0){ + tmpNode = rng.startContainer; + if(domUtils.isBoundaryNode(tmpNode,'firstChild') ){ + tmpNode = rng.endContainer; + if(rng.endOffset == (tmpNode.nodeType == 3 ? tmpNode.nodeValue.length : tmpNode.childNodes.length) && domUtils.isBoundaryNode(tmpNode,'lastChild')){ + me.fireEvent('saveScene'); + me.body.innerHTML = '

    '+(browser.ie ? '' : '
    ')+'

    '; + rng.setStart(me.body.firstChild,0).setCursor(false,true); + me._selectionChange(); + return; + } + } + } + } + + //处理backspace + if (keyCode == keymap.Backspace) { + rng = me.selection.getRange(); + collapsed = rng.collapsed; + if(me.fireEvent('delkeydown',evt)){ + return; + } + var start,end; + //避免按两次删除才能生效的问题 + if(rng.collapsed && rng.inFillChar()){ + start = rng.startContainer; + + if(domUtils.isFillChar(start)){ + rng.setStartBefore(start).shrinkBoundary(true).collapse(true); + domUtils.remove(start) + }else{ + start.nodeValue = start.nodeValue.replace(new RegExp('^' + domUtils.fillChar ),''); + rng.startOffset--; + rng.collapse(true).select(true) + } + } + + //解决选中control元素不能删除的问题 + if (start = rng.getClosedNode()) { + me.fireEvent('saveScene'); + rng.setStartBefore(start); + domUtils.remove(start); + rng.setCursor(); + me.fireEvent('saveScene'); + domUtils.preventDefault(evt); + return; + } + //阻止在table上的删除 + if (!browser.ie) { + start = domUtils.findParentByTagName(rng.startContainer, 'table', true); + end = domUtils.findParentByTagName(rng.endContainer, 'table', true); + if (start && !end || !start && end || start !== end) { + evt.preventDefault(); + return; + } + } + + } + //处理tab键的逻辑 + if (keyCode == keymap.Tab) { + //不处理以下标签 + var excludeTagNameForTabKey = { + 'ol' : 1, + 'ul' : 1, + 'table':1 + }; + //处理组件里的tab按下事件 + if(me.fireEvent('tabkeydown',evt)){ + domUtils.preventDefault(evt); + return; + } + var range = me.selection.getRange(); + me.fireEvent('saveScene'); + for (var i = 0,txt = '',tabSize = me.options.tabSize|| 4,tabNode = me.options.tabNode || ' '; i < tabSize; i++) { + txt += tabNode; + } + var span = me.document.createElement('span'); + span.innerHTML = txt + domUtils.fillChar; + if (range.collapsed) { + range.insertNode(span.cloneNode(true).firstChild).setCursor(true); + } else { + var filterFn = function(node) { + return domUtils.isBlockElm(node) && !excludeTagNameForTabKey[node.tagName.toLowerCase()] + + }; + //普通的情况 + start = domUtils.findParent(range.startContainer, filterFn,true); + end = domUtils.findParent(range.endContainer, filterFn,true); + if (start && end && start === end) { + range.deleteContents(); + range.insertNode(span.cloneNode(true).firstChild).setCursor(true); + } else { + var bookmark = range.createBookmark(); + range.enlarge(true); + var bookmark2 = range.createBookmark(), + current = domUtils.getNextDomNode(bookmark2.start, false, filterFn); + while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) { + current.insertBefore(span.cloneNode(true).firstChild, current.firstChild); + current = domUtils.getNextDomNode(current, false, filterFn); + } + range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select(); + } + } + domUtils.preventDefault(evt) + } + //trace:1634 + //ff的del键在容器空的时候,也会删除 + if(browser.gecko && keyCode == 46){ + range = me.selection.getRange(); + if(range.collapsed){ + start = range.startContainer; + if(domUtils.isEmptyBlock(start)){ + var parent = start.parentNode; + while(domUtils.getChildCount(parent) == 1 && !domUtils.isBody(parent)){ + start = parent; + parent = parent.parentNode; + } + if(start === parent.lastChild) + evt.preventDefault(); + return; + } + } + } + }); + me.addListener('keyup', function(type, evt) { + var keyCode = evt.keyCode || evt.which, + rng,me = this; + if(keyCode == keymap.Backspace){ + if(me.fireEvent('delkeyup')){ + return; + } + rng = me.selection.getRange(); + if(rng.collapsed){ + var tmpNode, + autoClearTagName = ['h1','h2','h3','h4','h5','h6']; + if(tmpNode = domUtils.findParentByTagName(rng.startContainer,autoClearTagName,true)){ + if(domUtils.isEmptyBlock(tmpNode)){ + var pre = tmpNode.previousSibling; + if(pre && pre.nodeName != 'TABLE'){ + domUtils.remove(tmpNode); + rng.setStartAtLast(pre).setCursor(false,true); + return; + }else{ + var next = tmpNode.nextSibling; + if(next && next.nodeName != 'TABLE'){ + domUtils.remove(tmpNode); + rng.setStartAtFirst(next).setCursor(false,true); + return; + } + } + } + } + //处理当删除到body时,要重新给p标签展位 + if(domUtils.isBody(rng.startContainer)){ + var tmpNode = domUtils.createElement(me.document,'p',{ + 'innerHTML' : browser.ie ? domUtils.fillChar : '
    ' + }); + rng.insertNode(tmpNode).setStart(tmpNode,0).setCursor(false,true); + } + } + + + //chrome下如果删除了inline标签,浏览器会有记忆,在输入文字还是会套上刚才删除的标签,所以这里再选一次就不会了 + if( !collapsed && (rng.startContainer.nodeType == 3 || rng.startContainer.nodeType == 1 && domUtils.isEmptyBlock(rng.startContainer))){ + if(browser.ie){ + var span = rng.document.createElement('span'); + rng.insertNode(span).setStartBefore(span).collapse(true); + rng.select(); + domUtils.remove(span) + }else{ + rng.select() + } + + } + } + + + }) +}; \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/lineheight.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/lineheight.js new file mode 100644 index 000000000..b89c5fb9b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/lineheight.js @@ -0,0 +1,48 @@ +/** + * 设置行内间距 + * @file + * @since 1.2.6.1 + */ +UE.plugins['lineheight'] = function(){ + var me = this; + me.setOpt({'lineheight':['1', '1.5','1.75','2', '3', '4', '5']}); + + /** + * 行距 + * @command lineheight + * @method execCommand + * @param { String } cmdName 命令字符串 + * @param { String } value 传入的行高值, 该值是当前字体的倍数, 例如: 1.5, 1.75 + * @example + * ```javascript + * editor.execCommand( 'lineheight', 1.5); + * ``` + */ + /** + * 查询当前选区内容的行高大小 + * @command lineheight + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回当前行高大小 + * @example + * ```javascript + * editor.queryCommandValue( 'lineheight' ); + * ``` + */ + + me.commands['lineheight'] = { + execCommand : function( cmdName,value ) { + this.execCommand('paragraph','p',{style:'line-height:'+ (value == "1" ? "normal" : value + 'em') }); + return true; + }, + queryCommandValue : function() { + var pN = domUtils.filterNodeList(this.selection.getStartElementPath(),function(node){return domUtils.isBlockElm(node)}); + if(pN){ + var value = domUtils.getComputedStyle(pN,'line-height'); + return value == 'normal' ? 1 : value.replace(/[^\d.]*/ig,""); + } + } + }; +}; + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/link.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/link.js new file mode 100644 index 000000000..0519c8a9f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/link.js @@ -0,0 +1,174 @@ +/** + * 超链接 + * @file + * @since 1.2.6.1 + */ + +/** + * 插入超链接 + * @command link + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { Object } options 设置自定义属性,例如:url、title、target + * @example + * ```javascript + * editor.execCommand( 'link', '{ + * url:'ueditor.baidu.com', + * title:'ueditor', + * target:'_blank' + * }' ); + * ``` + */ +/** + * 返回当前选中的第一个超链接节点 + * @command link + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { Element } 超链接节点 + * @example + * ```javascript + * editor.queryCommandValue( 'link' ); + * ``` + */ + +/** + * 取消超链接 + * @command unlink + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'unlink'); + * ``` + */ + +UE.plugins['link'] = function(){ + function optimize( range ) { + var start = range.startContainer,end = range.endContainer; + + if ( start = domUtils.findParentByTagName( start, 'a', true ) ) { + range.setStartBefore( start ); + } + if ( end = domUtils.findParentByTagName( end, 'a', true ) ) { + range.setEndAfter( end ); + } + } + + + UE.commands['unlink'] = { + execCommand : function() { + var range = this.selection.getRange(), + bookmark; + if(range.collapsed && !domUtils.findParentByTagName( range.startContainer, 'a', true )){ + return; + } + bookmark = range.createBookmark(); + optimize( range ); + range.removeInlineStyle( 'a' ).moveToBookmark( bookmark ).select(); + }, + queryCommandState : function(){ + return !this.highlight && this.queryCommandValue('link') ? 0 : -1; + } + + }; + function doLink(range,opt,me){ + var rngClone = range.cloneRange(), + link = me.queryCommandValue('link'); + optimize( range = range.adjustmentBoundary() ); + var start = range.startContainer; + if(start.nodeType == 1 && link){ + start = start.childNodes[range.startOffset]; + if(start && start.nodeType == 1 && start.tagName == 'A' && /^(?:https?|ftp|file)\s*:\s*\/\//.test(start[browser.ie?'innerText':'textContent'])){ + start[browser.ie ? 'innerText' : 'textContent'] = utils.html(opt.textValue||opt.href); + + } + } + if( !rngClone.collapsed || link){ + range.removeInlineStyle( 'a' ); + rngClone = range.cloneRange(); + } + + if ( rngClone.collapsed ) { + var a = range.document.createElement( 'a'), + text = ''; + if(opt.textValue){ + + text = utils.html(opt.textValue); + delete opt.textValue; + }else{ + text = utils.html(opt.href); + + } + domUtils.setAttributes( a, opt ); + start = domUtils.findParentByTagName( rngClone.startContainer, 'a', true ); + if(start && domUtils.isInNodeEndBoundary(rngClone,start)){ + range.setStartAfter(start).collapse(true); + + } + a[browser.ie ? 'innerText' : 'textContent'] = text; + range.insertNode(a).selectNode( a ); + } else { + range.applyInlineStyle( 'a', opt ); + + } + } + UE.commands['link'] = { + execCommand : function( cmdName, opt ) { + var range; + opt._href && (opt._href = utils.unhtml(opt._href,/[<">]/g)); + opt.href && (opt.href = utils.unhtml(opt.href,/[<">]/g)); + opt.textValue && (opt.textValue = utils.unhtml(opt.textValue,/[<">]/g)); + doLink(range=this.selection.getRange(),opt,this); + //闭合都不加占位符,如果加了会在a后边多个占位符节点,导致a是图片背景组成的列表,出现空白问题 + range.collapse().select(true); + + }, + queryCommandValue : function() { + var range = this.selection.getRange(), + node; + if ( range.collapsed ) { +// node = this.selection.getStart(); + //在ie下getstart()取值偏上了 + node = range.startContainer; + node = node.nodeType == 1 ? node : node.parentNode; + + if ( node && (node = domUtils.findParentByTagName( node, 'a', true )) && ! domUtils.isInNodeEndBoundary(range,node)) { + + return node; + } + } else { + //trace:1111 如果是

    xx

    startContainer是p就会找不到a + range.shrinkBoundary(); + var start = range.startContainer.nodeType == 3 || !range.startContainer.childNodes[range.startOffset] ? range.startContainer : range.startContainer.childNodes[range.startOffset], + end = range.endContainer.nodeType == 3 || range.endOffset == 0 ? range.endContainer : range.endContainer.childNodes[range.endOffset-1], + common = range.getCommonAncestor(); + node = domUtils.findParentByTagName( common, 'a', true ); + if ( !node && common.nodeType == 1){ + + var as = common.getElementsByTagName( 'a' ), + ps,pe; + + for ( var i = 0,ci; ci = as[i++]; ) { + ps = domUtils.getPosition( ci, start ),pe = domUtils.getPosition( ci,end); + if ( (ps & domUtils.POSITION_FOLLOWING || ps & domUtils.POSITION_CONTAINS) + && + (pe & domUtils.POSITION_PRECEDING || pe & domUtils.POSITION_CONTAINS) + ) { + node = ci; + break; + } + } + } + return node; + } + + }, + queryCommandState : function() { + //判断如果是视频的话连接不可用 + //fix 853 + var img = this.selection.getRange().getClosedNode(), + flag = img && (img.className == "edui-faked-video" || img.className.indexOf("edui-upload-video")!=-1); + return flag ? -1 : 0; + } + }; +}; \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/list.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/list.js new file mode 100644 index 000000000..6b8cf40f6 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/list.js @@ -0,0 +1,1246 @@ +/** + * 有序列表,无序列表插件 + * @file + * @since 1.2.6.1 + */ + +UE.plugins['list'] = function () { + var me = this, + notExchange = { + 'TD':1, + 'PRE':1, + 'BLOCKQUOTE':1 + }; + var customStyle = { + 'cn' : 'cn-1-', + 'cn1' : 'cn-2-', + 'cn2' : 'cn-3-', + 'num': 'num-1-', + 'num1' : 'num-2-', + 'num2' : 'num-3-', + 'dash' : 'dash', + 'dot':'dot' + }; + + me.setOpt( { + 'autoTransWordToList':false, + 'insertorderedlist':{ + 'num':'', + 'num1':'', + 'num2':'', + 'cn':'', + 'cn1':'', + 'cn2':'', + 'decimal':'', + 'lower-alpha':'', + 'lower-roman':'', + 'upper-alpha':'', + 'upper-roman':'' + }, + 'insertunorderedlist':{ + 'circle':'', + 'disc':'', + 'square':'', + 'dash' : '', + 'dot':'' + }, + listDefaultPaddingLeft : '30', + listiconpath : 'http://bs.baidu.com/listicon/', + maxListLevel : -1,//-1不限制 + disablePInList:false + } ); + function listToArray(list){ + var arr = []; + for(var p in list){ + arr.push(p) + } + return arr; + } + var listStyle = { + 'OL':listToArray(me.options.insertorderedlist), + 'UL':listToArray(me.options.insertunorderedlist) + }; + var liiconpath = me.options.listiconpath; + + //根据用户配置,调整customStyle + for(var s in customStyle){ + if(!me.options.insertorderedlist.hasOwnProperty(s) && !me.options.insertunorderedlist.hasOwnProperty(s)){ + delete customStyle[s]; + } + } + + me.ready(function () { + var customCss = []; + for(var p in customStyle){ + if(p == 'dash' || p == 'dot'){ + customCss.push('li.list-' + customStyle[p] + '{background-image:url(' + liiconpath +customStyle[p]+'.gif)}'); + customCss.push('ul.custom_'+p+'{list-style:none;}ul.custom_'+p+' li{background-position:0 3px;background-repeat:no-repeat}'); + }else{ + for(var i= 0;i<99;i++){ + customCss.push('li.list-' + customStyle[p] + i + '{background-image:url(' + liiconpath + 'list-'+customStyle[p] + i + '.gif)}') + } + customCss.push('ol.custom_'+p+'{list-style:none;}ol.custom_'+p+' li{background-position:0 3px;background-repeat:no-repeat}'); + } + switch(p){ + case 'cn': + customCss.push('li.list-'+p+'-paddingleft-1{padding-left:25px}'); + customCss.push('li.list-'+p+'-paddingleft-2{padding-left:40px}'); + customCss.push('li.list-'+p+'-paddingleft-3{padding-left:55px}'); + break; + case 'cn1': + customCss.push('li.list-'+p+'-paddingleft-1{padding-left:30px}'); + customCss.push('li.list-'+p+'-paddingleft-2{padding-left:40px}'); + customCss.push('li.list-'+p+'-paddingleft-3{padding-left:55px}'); + break; + case 'cn2': + customCss.push('li.list-'+p+'-paddingleft-1{padding-left:40px}'); + customCss.push('li.list-'+p+'-paddingleft-2{padding-left:55px}'); + customCss.push('li.list-'+p+'-paddingleft-3{padding-left:68px}'); + break; + case 'num': + case 'num1': + customCss.push('li.list-'+p+'-paddingleft-1{padding-left:25px}'); + break; + case 'num2': + customCss.push('li.list-'+p+'-paddingleft-1{padding-left:35px}'); + customCss.push('li.list-'+p+'-paddingleft-2{padding-left:40px}'); + break; + case 'dash': + customCss.push('li.list-'+p+'-paddingleft{padding-left:35px}'); + break; + case 'dot': + customCss.push('li.list-'+p+'-paddingleft{padding-left:20px}'); + } + } + customCss.push('.list-paddingleft-1{padding-left:0}'); + customCss.push('.list-paddingleft-2{padding-left:'+me.options.listDefaultPaddingLeft+'px}'); + customCss.push('.list-paddingleft-3{padding-left:'+me.options.listDefaultPaddingLeft*2+'px}'); + //如果不给宽度会在自定应样式里出现滚动条 + utils.cssRule('list', 'ol,ul{margin:0;pading:0;'+(browser.ie ? '' : 'width:95%')+'}li{clear:both;}'+customCss.join('\n'), me.document); + }); + //单独处理剪切的问题 + me.ready(function(){ + domUtils.on(me.body,'cut',function(){ + setTimeout(function(){ + var rng = me.selection.getRange(),li; + //trace:3416 + if(!rng.collapsed){ + if(li = domUtils.findParentByTagName(rng.startContainer,'li',true)){ + if(!li.nextSibling && domUtils.isEmptyBlock(li)){ + var pn = li.parentNode,node; + if(node = pn.previousSibling){ + domUtils.remove(pn); + rng.setStartAtLast(node).collapse(true); + rng.select(true); + }else if(node = pn.nextSibling){ + domUtils.remove(pn); + rng.setStartAtFirst(node).collapse(true); + rng.select(true); + }else{ + var tmpNode = me.document.createElement('p'); + domUtils.fillNode(me.document,tmpNode); + pn.parentNode.insertBefore(tmpNode,pn); + domUtils.remove(pn); + rng.setStart(tmpNode,0).collapse(true); + rng.select(true); + } + } + } + } + + }) + }) + }); + + function getStyle(node){ + var cls = node.className; + if(domUtils.hasClass(node,/custom_/)){ + return cls.match(/custom_(\w+)/)[1] + } + return domUtils.getStyle(node, 'list-style-type') + + } + + me.addListener('beforepaste',function(type,html){ + var me = this, + rng = me.selection.getRange(),li; + var root = UE.htmlparser(html.html,true); + if(li = domUtils.findParentByTagName(rng.startContainer,'li',true)){ + var list = li.parentNode,tagName = list.tagName == 'OL' ? 'ul':'ol'; + utils.each(root.getNodesByTagName(tagName),function(n){ + n.tagName = list.tagName; + n.setAttr(); + if(n.parentNode === root){ + type = getStyle(list) || (list.tagName == 'OL' ? 'decimal' : 'disc') + }else{ + var className = n.parentNode.getAttr('class'); + if(className && /custom_/.test(className)){ + type = className.match(/custom_(\w+)/)[1] + }else{ + type = n.parentNode.getStyle('list-style-type'); + } + if(!type){ + type = list.tagName == 'OL' ? 'decimal' : 'disc'; + } + } + var index = utils.indexOf(listStyle[list.tagName], type); + if(n.parentNode !== root) + index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1; + var currentStyle = listStyle[list.tagName][index]; + if(customStyle[currentStyle]){ + n.setAttr('class', 'custom_' + currentStyle) + + }else{ + n.setStyle('list-style-type',currentStyle) + } + }) + + } + + html.html = root.toHtml(); + }); + //导出时,去掉p标签 + me.getOpt('disablePInList') === true && me.addOutputRule(function(root){ + utils.each(root.getNodesByTagName('li'),function(li){ + var newChildrens = [],index=0; + utils.each(li.children,function(n){ + if(n.tagName == 'p'){ + var tmpNode; + while(tmpNode = n.children.pop()) { + newChildrens.splice(index,0,tmpNode); + tmpNode.parentNode = li; + lastNode = tmpNode; + } + tmpNode = newChildrens[newChildrens.length-1]; + if(!tmpNode || tmpNode.type != 'element' || tmpNode.tagName != 'br'){ + var br = UE.uNode.createElement('br'); + br.parentNode = li; + newChildrens.push(br); + } + + index = newChildrens.length; + } + }); + if(newChildrens.length){ + li.children = newChildrens; + } + }); + }); + //进入编辑器的li要套p标签 + me.addInputRule(function(root){ + utils.each(root.getNodesByTagName('li'),function(li){ + var tmpP = UE.uNode.createElement('p'); + for(var i= 0,ci;ci=li.children[i];){ + if(ci.type == 'text' || dtd.p[ci.tagName]){ + tmpP.appendChild(ci); + }else{ + if(tmpP.firstChild()){ + li.insertBefore(tmpP,ci); + tmpP = UE.uNode.createElement('p'); + i = i + 2; + }else{ + i++; + } + + } + } + if(tmpP.firstChild() && !tmpP.parentNode || !li.firstChild()){ + li.appendChild(tmpP); + } + //trace:3357 + //p不能为空 + if (!tmpP.firstChild()) { + tmpP.innerHTML(browser.ie ? ' ' : '
    ') + } + //去掉末尾的空白 + var p = li.firstChild(); + var lastChild = p.lastChild(); + if(lastChild && lastChild.type == 'text' && /^\s*$/.test(lastChild.data)){ + p.removeChild(lastChild) + } + }); + if(me.options.autoTransWordToList){ + var orderlisttype = { + 'num1':/^\d+\)/, + 'decimal':/^\d+\./, + 'lower-alpha':/^[a-z]+\)/, + 'upper-alpha':/^[A-Z]+\./, + 'cn':/^[\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+[\u3001]/, + 'cn2':/^\([\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+\)/ + }, + unorderlisttype = { + 'square':'n' + }; + function checkListType(content,container){ + var span = container.firstChild(); + if(span && span.type == 'element' && span.tagName == 'span' && /Wingdings|Symbol/.test(span.getStyle('font-family'))){ + for(var p in unorderlisttype){ + if(unorderlisttype[p] == span.data){ + return p + } + } + return 'disc' + } + for(var p in orderlisttype){ + if(orderlisttype[p].test(content)){ + return p; + } + } + + } + utils.each(root.getNodesByTagName('p'),function(node){ + if(node.getAttr('class') != 'MsoListParagraph'){ + return + } + + //word粘贴过来的会带有margin要去掉,但这样也可能会误命中一些央视 + node.setStyle('margin',''); + node.setStyle('margin-left',''); + node.setAttr('class',''); + + function appendLi(list,p,type){ + if(list.tagName == 'ol'){ + if(browser.ie){ + var first = p.firstChild(); + if(first.type =='element' && first.tagName == 'span' && orderlisttype[type].test(first.innerText())){ + p.removeChild(first); + } + }else{ + p.innerHTML(p.innerHTML().replace(orderlisttype[type],'')); + } + }else{ + p.removeChild(p.firstChild()) + } + + var li = UE.uNode.createElement('li'); + li.appendChild(p); + list.appendChild(li); + } + var tmp = node,type,cacheNode = node; + + if(node.parentNode.tagName != 'li' && (type = checkListType(node.innerText(),node))){ + + var list = UE.uNode.createElement(me.options.insertorderedlist.hasOwnProperty(type) ? 'ol' : 'ul'); + if(customStyle[type]){ + list.setAttr('class','custom_'+type) + }else{ + list.setStyle('list-style-type',type) + } + while(node && node.parentNode.tagName != 'li' && checkListType(node.innerText(),node)){ + tmp = node.nextSibling(); + if(!tmp){ + node.parentNode.insertBefore(list,node) + } + appendLi(list,node,type); + node = tmp; + } + if(!list.parentNode && node && node.parentNode){ + node.parentNode.insertBefore(list,node) + } + } + var span = cacheNode.firstChild(); + if(span && span.type == 'element' && span.tagName == 'span' && /^\s*( )+\s*$/.test(span.innerText())){ + span.parentNode.removeChild(span) + } + }) + } + + }); + + //调整索引标签 + me.addListener('contentchange',function(){ + adjustListStyle(me.document) + }); + + function adjustListStyle(doc,ignore){ + utils.each(domUtils.getElementsByTagName(doc,'ol ul'),function(node){ + + if(!domUtils.inDoc(node,doc)) + return; + + var parent = node.parentNode; + if(parent.tagName == node.tagName){ + var nodeStyleType = getStyle(node) || (node.tagName == 'OL' ? 'decimal' : 'disc'), + parentStyleType = getStyle(parent) || (parent.tagName == 'OL' ? 'decimal' : 'disc'); + if(nodeStyleType == parentStyleType){ + var styleIndex = utils.indexOf(listStyle[node.tagName], nodeStyleType); + styleIndex = styleIndex + 1 == listStyle[node.tagName].length ? 0 : styleIndex + 1; + setListStyle(node,listStyle[node.tagName][styleIndex]) + } + + } + var index = 0,type = 2; + if( domUtils.hasClass(node,/custom_/)){ + if(!(/[ou]l/i.test(parent.tagName) && domUtils.hasClass(parent,/custom_/))){ + type = 1; + } + }else{ + if(/[ou]l/i.test(parent.tagName) && domUtils.hasClass(parent,/custom_/)){ + type = 3; + } + } + + var style = domUtils.getStyle(node, 'list-style-type'); + style && (node.style.cssText = 'list-style-type:' + style); + node.className = utils.trim(node.className.replace(/list-paddingleft-\w+/,'')) + ' list-paddingleft-' + type; + utils.each(domUtils.getElementsByTagName(node,'li'),function(li){ + li.style.cssText && (li.style.cssText = ''); + if(!li.firstChild){ + domUtils.remove(li); + return; + } + if(li.parentNode !== node){ + return; + } + index++; + if(domUtils.hasClass(node,/custom_/) ){ + var paddingLeft = 1,currentStyle = getStyle(node); + if(node.tagName == 'OL'){ + if(currentStyle){ + switch(currentStyle){ + case 'cn' : + case 'cn1': + case 'cn2': + if(index > 10 && (index % 10 == 0 || index > 10 && index < 20)){ + paddingLeft = 2 + }else if(index > 20){ + paddingLeft = 3 + } + break; + case 'num2' : + if(index > 9){ + paddingLeft = 2 + } + } + } + li.className = 'list-'+customStyle[currentStyle]+ index + ' ' + 'list-'+currentStyle+'-paddingleft-' + paddingLeft; + }else{ + li.className = 'list-'+customStyle[currentStyle] + ' ' + 'list-'+currentStyle+'-paddingleft'; + } + }else{ + li.className = li.className.replace(/list-[\w\-]+/gi,''); + } + var className = li.getAttribute('class'); + if(className !== null && !className.replace(/\s/g,'')){ + domUtils.removeAttributes(li,'class') + } + }); + !ignore && adjustList(node,node.tagName.toLowerCase(),getStyle(node)||domUtils.getStyle(node, 'list-style-type'),true); + }) + } + function adjustList(list, tag, style,ignoreEmpty) { + var nextList = list.nextSibling; + if (nextList && nextList.nodeType == 1 && nextList.tagName.toLowerCase() == tag && (getStyle(nextList) || domUtils.getStyle(nextList, 'list-style-type') || (tag == 'ol' ? 'decimal' : 'disc')) == style) { + domUtils.moveChild(nextList, list); + if (nextList.childNodes.length == 0) { + domUtils.remove(nextList); + } + } + if(nextList && domUtils.isFillChar(nextList)){ + domUtils.remove(nextList); + } + var preList = list.previousSibling; + if (preList && preList.nodeType == 1 && preList.tagName.toLowerCase() == tag && (getStyle(preList) || domUtils.getStyle(preList, 'list-style-type') || (tag == 'ol' ? 'decimal' : 'disc')) == style) { + domUtils.moveChild(list, preList); + } + if(preList && domUtils.isFillChar(preList)){ + domUtils.remove(preList); + } + !ignoreEmpty && domUtils.isEmptyBlock(list) && domUtils.remove(list); + if(getStyle(list)){ + adjustListStyle(list.ownerDocument,true) + } + } + + function setListStyle(list,style){ + if(customStyle[style]){ + list.className = 'custom_' + style; + } + try{ + domUtils.setStyle(list, 'list-style-type', style); + }catch(e){} + } + function clearEmptySibling(node) { + var tmpNode = node.previousSibling; + if (tmpNode && domUtils.isEmptyBlock(tmpNode)) { + domUtils.remove(tmpNode); + } + tmpNode = node.nextSibling; + if (tmpNode && domUtils.isEmptyBlock(tmpNode)) { + domUtils.remove(tmpNode); + } + } + + me.addListener('keydown', function (type, evt) { + function preventAndSave() { + evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); + me.fireEvent('contentchange'); + me.undoManger && me.undoManger.save(); + } + function findList(node,filterFn){ + while(node && !domUtils.isBody(node)){ + if(filterFn(node)){ + return null + } + if(node.nodeType == 1 && /[ou]l/i.test(node.tagName)){ + return node; + } + node = node.parentNode; + } + return null; + } + var keyCode = evt.keyCode || evt.which; + if (keyCode == 13 && !evt.shiftKey) {//回车 + var rng = me.selection.getRange(), + parent = domUtils.findParent(rng.startContainer,function(node){return domUtils.isBlockElm(node)},true), + li = domUtils.findParentByTagName(rng.startContainer,'li',true); + if(parent && parent.tagName != 'PRE' && !li){ + var html = parent.innerHTML.replace(new RegExp(domUtils.fillChar, 'g'),''); + if(/^\s*1\s*\.[^\d]/.test(html)){ + parent.innerHTML = html.replace(/^\s*1\s*\./,''); + rng.setStartAtLast(parent).collapse(true).select(); + me.__hasEnterExecCommand = true; + me.execCommand('insertorderedlist'); + me.__hasEnterExecCommand = false; + } + } + var range = me.selection.getRange(), + start = findList(range.startContainer,function (node) { + return node.tagName == 'TABLE'; + }), + end = range.collapsed ? start : findList(range.endContainer,function (node) { + return node.tagName == 'TABLE'; + }); + + if (start && end && start === end) { + + if (!range.collapsed) { + start = domUtils.findParentByTagName(range.startContainer, 'li', true); + end = domUtils.findParentByTagName(range.endContainer, 'li', true); + if (start && end && start === end) { + range.deleteContents(); + li = domUtils.findParentByTagName(range.startContainer, 'li', true); + if (li && domUtils.isEmptyBlock(li)) { + + pre = li.previousSibling; + next = li.nextSibling; + p = me.document.createElement('p'); + + domUtils.fillNode(me.document, p); + parentList = li.parentNode; + if (pre && next) { + range.setStart(next, 0).collapse(true).select(true); + domUtils.remove(li); + + } else { + if (!pre && !next || !pre) { + + parentList.parentNode.insertBefore(p, parentList); + + + } else { + li.parentNode.parentNode.insertBefore(p, parentList.nextSibling); + } + domUtils.remove(li); + if (!parentList.firstChild) { + domUtils.remove(parentList); + } + range.setStart(p, 0).setCursor(); + + + } + preventAndSave(); + return; + + } + } else { + var tmpRange = range.cloneRange(), + bk = tmpRange.collapse(false).createBookmark(); + + range.deleteContents(); + tmpRange.moveToBookmark(bk); + var li = domUtils.findParentByTagName(tmpRange.startContainer, 'li', true); + + clearEmptySibling(li); + tmpRange.select(); + preventAndSave(); + return; + } + } + + + li = domUtils.findParentByTagName(range.startContainer, 'li', true); + + if (li) { + if (domUtils.isEmptyBlock(li)) { + bk = range.createBookmark(); + var parentList = li.parentNode; + if (li !== parentList.lastChild) { + domUtils.breakParent(li, parentList); + clearEmptySibling(li); + } else { + + parentList.parentNode.insertBefore(li, parentList.nextSibling); + if (domUtils.isEmptyNode(parentList)) { + domUtils.remove(parentList); + } + } + //嵌套不处理 + if (!dtd.$list[li.parentNode.tagName]) { + + if (!domUtils.isBlockElm(li.firstChild)) { + p = me.document.createElement('p'); + li.parentNode.insertBefore(p, li); + while (li.firstChild) { + p.appendChild(li.firstChild); + } + domUtils.remove(li); + } else { + domUtils.remove(li, true); + } + } + range.moveToBookmark(bk).select(); + + + } else { + var first = li.firstChild; + if (!first || !domUtils.isBlockElm(first)) { + var p = me.document.createElement('p'); + + !li.firstChild && domUtils.fillNode(me.document, p); + while (li.firstChild) { + + p.appendChild(li.firstChild); + } + li.appendChild(p); + first = p; + } + + var span = me.document.createElement('span'); + + range.insertNode(span); + domUtils.breakParent(span, li); + + var nextLi = span.nextSibling; + first = nextLi.firstChild; + + if (!first) { + p = me.document.createElement('p'); + + domUtils.fillNode(me.document, p); + nextLi.appendChild(p); + first = p; + } + if (domUtils.isEmptyNode(first)) { + first.innerHTML = ''; + domUtils.fillNode(me.document, first); + } + + range.setStart(first, 0).collapse(true).shrinkBoundary().select(); + domUtils.remove(span); + var pre = nextLi.previousSibling; + if (pre && domUtils.isEmptyBlock(pre)) { + pre.innerHTML = '

    '; + domUtils.fillNode(me.document, pre.firstChild); + } + + } +// } + preventAndSave(); + } + + + } + + + } + if (keyCode == 8) { + //修中ie中li下的问题 + range = me.selection.getRange(); + if (range.collapsed && domUtils.isStartInblock(range)) { + tmpRange = range.cloneRange().trimBoundary(); + li = domUtils.findParentByTagName(range.startContainer, 'li', true); + //要在li的最左边,才能处理 + if (li && domUtils.isStartInblock(tmpRange)) { + start = domUtils.findParentByTagName(range.startContainer, 'p', true); + if (start && start !== li.firstChild) { + var parentList = domUtils.findParentByTagName(start,['ol','ul']); + domUtils.breakParent(start,parentList); + clearEmptySibling(start); + me.fireEvent('contentchange'); + range.setStart(start,0).setCursor(false,true); + me.fireEvent('saveScene'); + domUtils.preventDefault(evt); + return; + } + + if (li && (pre = li.previousSibling)) { + if (keyCode == 46 && li.childNodes.length) { + return; + } + //有可能上边的兄弟节点是个2级菜单,要追加到2级菜单的最后的li + if (dtd.$list[pre.tagName]) { + pre = pre.lastChild; + } + me.undoManger && me.undoManger.save(); + first = li.firstChild; + if (domUtils.isBlockElm(first)) { + if (domUtils.isEmptyNode(first)) { +// range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true); + pre.appendChild(first); + range.setStart(first, 0).setCursor(false, true); + //first不是唯一的节点 + while (li.firstChild) { + pre.appendChild(li.firstChild); + } + } else { + + span = me.document.createElement('span'); + range.insertNode(span); + //判断pre是否是空的节点,如果是


    类型的空节点,干掉p标签防止它占位 + if (domUtils.isEmptyBlock(pre)) { + pre.innerHTML = ''; + } + domUtils.moveChild(li, pre); + range.setStartBefore(span).collapse(true).select(true); + + domUtils.remove(span); + + } + } else { + if (domUtils.isEmptyNode(li)) { + var p = me.document.createElement('p'); + pre.appendChild(p); + range.setStart(p, 0).setCursor(); +// range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true); + } else { + range.setEnd(pre, pre.childNodes.length).collapse().select(true); + while (li.firstChild) { + pre.appendChild(li.firstChild); + } + } + } + domUtils.remove(li); + me.fireEvent('contentchange'); + me.fireEvent('saveScene'); + domUtils.preventDefault(evt); + return; + + } + //trace:980 + + if (li && !li.previousSibling) { + var parentList = li.parentNode; + var bk = range.createBookmark(); + if(domUtils.isTagNode(parentList.parentNode,'ol ul')){ + parentList.parentNode.insertBefore(li,parentList); + if(domUtils.isEmptyNode(parentList)){ + domUtils.remove(parentList) + } + }else{ + + while(li.firstChild){ + parentList.parentNode.insertBefore(li.firstChild,parentList); + } + + domUtils.remove(li); + if(domUtils.isEmptyNode(parentList)){ + domUtils.remove(parentList) + } + + } + range.moveToBookmark(bk).setCursor(false,true); + me.fireEvent('contentchange'); + me.fireEvent('saveScene'); + domUtils.preventDefault(evt); + return; + + } + + + } + + + } + + } + }); + + me.addListener('keyup',function(type, evt){ + var keyCode = evt.keyCode || evt.which; + if (keyCode == 8) { + var rng = me.selection.getRange(),list; + if(list = domUtils.findParentByTagName(rng.startContainer,['ol', 'ul'],true)){ + adjustList(list,list.tagName.toLowerCase(),getStyle(list)||domUtils.getComputedStyle(list,'list-style-type'),true) + } + } + }); + //处理tab键 + me.addListener('tabkeydown',function(){ + + var range = me.selection.getRange(); + + //控制级数 + function checkLevel(li){ + if(me.options.maxListLevel != -1){ + var level = li.parentNode,levelNum = 0; + while(/[ou]l/i.test(level.tagName)){ + levelNum++; + level = level.parentNode; + } + if(levelNum >= me.options.maxListLevel){ + return true; + } + } + } + //只以开始为准 + //todo 后续改进 + var li = domUtils.findParentByTagName(range.startContainer, 'li', true); + if(li){ + + var bk; + if(range.collapsed){ + if(checkLevel(li)) + return true; + var parentLi = li.parentNode, + list = me.document.createElement(parentLi.tagName), + index = utils.indexOf(listStyle[list.tagName], getStyle(parentLi)||domUtils.getComputedStyle(parentLi, 'list-style-type')); + index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1; + var currentStyle = listStyle[list.tagName][index]; + setListStyle(list,currentStyle); + if(domUtils.isStartInblock(range)){ + me.fireEvent('saveScene'); + bk = range.createBookmark(); + parentLi.insertBefore(list, li); + list.appendChild(li); + adjustList(list,list.tagName.toLowerCase(),currentStyle); + me.fireEvent('contentchange'); + range.moveToBookmark(bk).select(true); + return true; + } + }else{ + me.fireEvent('saveScene'); + bk = range.createBookmark(); + for(var i= 0,closeList,parents = domUtils.findParents(li),ci;ci=parents[i++];){ + if(domUtils.isTagNode(ci,'ol ul')){ + closeList = ci; + break; + } + } + var current = li; + if(bk.end){ + while(current && !(domUtils.getPosition(current, bk.end) & domUtils.POSITION_FOLLOWING)){ + if(checkLevel(current)){ + current = domUtils.getNextDomNode(current,false,null,function(node){return node !== closeList}); + continue; + } + var parentLi = current.parentNode, + list = me.document.createElement(parentLi.tagName), + index = utils.indexOf(listStyle[list.tagName], getStyle(parentLi)||domUtils.getComputedStyle(parentLi, 'list-style-type')); + var currentIndex = index + 1 == listStyle[list.tagName].length ? 0 : index + 1; + var currentStyle = listStyle[list.tagName][currentIndex]; + setListStyle(list,currentStyle); + parentLi.insertBefore(list, current); + while(current && !(domUtils.getPosition(current, bk.end) & domUtils.POSITION_FOLLOWING)){ + li = current.nextSibling; + list.appendChild(current); + if(!li || domUtils.isTagNode(li,'ol ul')){ + if(li){ + while(li = li.firstChild){ + if(li.tagName == 'LI'){ + break; + } + } + }else{ + li = domUtils.getNextDomNode(current,false,null,function(node){return node !== closeList}); + } + break; + } + current = li; + } + adjustList(list,list.tagName.toLowerCase(),currentStyle); + current = li; + } + } + me.fireEvent('contentchange'); + range.moveToBookmark(bk).select(); + return true; + } + } + + }); + function getLi(start){ + while(start && !domUtils.isBody(start)){ + if(start.nodeName == 'TABLE'){ + return null; + } + if(start.nodeName == 'LI'){ + return start + } + start = start.parentNode; + } + } + + /** + * 有序列表,与“insertunorderedlist”命令互斥 + * @command insertorderedlist + * @method execCommand + * @param { String } command 命令字符串 + * @param { String } style 插入的有序列表类型,值为:decimal,lower-alpha,lower-roman,upper-alpha,upper-roman,cn,cn1,cn2,num,num1,num2 + * @example + * ```javascript + * editor.execCommand( 'insertorderedlist','decimal'); + * ``` + */ + /** + * 查询当前选区内容是否有序列表 + * @command insertorderedlist + * @method queryCommandState + * @param { String } cmd 命令字符串 + * @return { int } 如果当前选区是有序列表返回1,否则返回0 + * @example + * ```javascript + * editor.queryCommandState( 'insertorderedlist' ); + * ``` + */ + /** + * 查询当前选区内容是否有序列表 + * @command insertorderedlist + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回当前有序列表的类型,值为null或decimal,lower-alpha,lower-roman,upper-alpha,upper-roman,cn,cn1,cn2,num,num1,num2 + * @example + * ```javascript + * editor.queryCommandValue( 'insertorderedlist' ); + * ``` + */ + + /** + * 无序列表,与“insertorderedlist”命令互斥 + * @command insertunorderedlist + * @method execCommand + * @param { String } command 命令字符串 + * @param { String } style 插入的无序列表类型,值为:circle,disc,square,dash,dot + * @example + * ```javascript + * editor.execCommand( 'insertunorderedlist','circle'); + * ``` + */ + /** + * 查询当前是否有word文档粘贴进来的图片 + * @command insertunorderedlist + * @method insertunorderedlist + * @param { String } command 命令字符串 + * @return { int } 如果当前选区是无序列表返回1,否则返回0 + * @example + * ```javascript + * editor.queryCommandState( 'insertunorderedlist' ); + * ``` + */ + /** + * 查询当前选区内容是否有序列表 + * @command insertunorderedlist + * @method queryCommandValue + * @param { String } command 命令字符串 + * @return { String } 返回当前无序列表的类型,值为null或circle,disc,square,dash,dot + * @example + * ```javascript + * editor.queryCommandValue( 'insertunorderedlist' ); + * ``` + */ + + me.commands['insertorderedlist'] = + me.commands['insertunorderedlist'] = { + execCommand:function (command, style) { + + if (!style) { + style = command.toLowerCase() == 'insertorderedlist' ? 'decimal' : 'disc'; + } + var me = this, + range = this.selection.getRange(), + filterFn = function (node) { + return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' : !domUtils.isWhitespace(node); + }, + tag = command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul', + frag = me.document.createDocumentFragment(); + //去掉是因为会出现选到末尾,导致adjustmentBoundary缩到ol/ul的位置 + //range.shrinkBoundary();//.adjustmentBoundary(); + range.adjustmentBoundary().shrinkBoundary(); + var bko = range.createBookmark(true), + start = getLi(me.document.getElementById(bko.start)), + modifyStart = 0, + end = getLi(me.document.getElementById(bko.end)), + modifyEnd = 0, + startParent, endParent, + list, tmp; + + if (start || end) { + start && (startParent = start.parentNode); + if (!bko.end) { + end = start; + } + end && (endParent = end.parentNode); + + if (startParent === endParent) { + while (start !== end) { + tmp = start; + start = start.nextSibling; + if (!domUtils.isBlockElm(tmp.firstChild)) { + var p = me.document.createElement('p'); + while (tmp.firstChild) { + p.appendChild(tmp.firstChild); + } + tmp.appendChild(p); + } + frag.appendChild(tmp); + } + tmp = me.document.createElement('span'); + startParent.insertBefore(tmp, end); + if (!domUtils.isBlockElm(end.firstChild)) { + p = me.document.createElement('p'); + while (end.firstChild) { + p.appendChild(end.firstChild); + } + end.appendChild(p); + } + frag.appendChild(end); + domUtils.breakParent(tmp, startParent); + if (domUtils.isEmptyNode(tmp.previousSibling)) { + domUtils.remove(tmp.previousSibling); + } + if (domUtils.isEmptyNode(tmp.nextSibling)) { + domUtils.remove(tmp.nextSibling) + } + var nodeStyle = getStyle(startParent) || domUtils.getComputedStyle(startParent, 'list-style-type') || (command.toLowerCase() == 'insertorderedlist' ? 'decimal' : 'disc'); + if (startParent.tagName.toLowerCase() == tag && nodeStyle == style) { + for (var i = 0, ci, tmpFrag = me.document.createDocumentFragment(); ci = frag.firstChild;) { + if(domUtils.isTagNode(ci,'ol ul')){ +// 删除时,子列表不处理 +// utils.each(domUtils.getElementsByTagName(ci,'li'),function(li){ +// while(li.firstChild){ +// tmpFrag.appendChild(li.firstChild); +// } +// +// }); + tmpFrag.appendChild(ci); + }else{ + while (ci.firstChild) { + + tmpFrag.appendChild(ci.firstChild); + domUtils.remove(ci); + } + } + + } + tmp.parentNode.insertBefore(tmpFrag, tmp); + } else { + list = me.document.createElement(tag); + setListStyle(list,style); + list.appendChild(frag); + tmp.parentNode.insertBefore(list, tmp); + } + + domUtils.remove(tmp); + list && adjustList(list, tag, style); + range.moveToBookmark(bko).select(); + return; + } + //开始 + if (start) { + while (start) { + tmp = start.nextSibling; + if (domUtils.isTagNode(start, 'ol ul')) { + frag.appendChild(start); + } else { + var tmpfrag = me.document.createDocumentFragment(), + hasBlock = 0; + while (start.firstChild) { + if (domUtils.isBlockElm(start.firstChild)) { + hasBlock = 1; + } + tmpfrag.appendChild(start.firstChild); + } + if (!hasBlock) { + var tmpP = me.document.createElement('p'); + tmpP.appendChild(tmpfrag); + frag.appendChild(tmpP); + } else { + frag.appendChild(tmpfrag); + } + domUtils.remove(start); + } + + start = tmp; + } + startParent.parentNode.insertBefore(frag, startParent.nextSibling); + if (domUtils.isEmptyNode(startParent)) { + range.setStartBefore(startParent); + domUtils.remove(startParent); + } else { + range.setStartAfter(startParent); + } + modifyStart = 1; + } + + if (end && domUtils.inDoc(endParent, me.document)) { + //结束 + start = endParent.firstChild; + while (start && start !== end) { + tmp = start.nextSibling; + if (domUtils.isTagNode(start, 'ol ul')) { + frag.appendChild(start); + } else { + tmpfrag = me.document.createDocumentFragment(); + hasBlock = 0; + while (start.firstChild) { + if (domUtils.isBlockElm(start.firstChild)) { + hasBlock = 1; + } + tmpfrag.appendChild(start.firstChild); + } + if (!hasBlock) { + tmpP = me.document.createElement('p'); + tmpP.appendChild(tmpfrag); + frag.appendChild(tmpP); + } else { + frag.appendChild(tmpfrag); + } + domUtils.remove(start); + } + start = tmp; + } + var tmpDiv = domUtils.createElement(me.document, 'div', { + 'tmpDiv':1 + }); + domUtils.moveChild(end, tmpDiv); + + frag.appendChild(tmpDiv); + domUtils.remove(end); + endParent.parentNode.insertBefore(frag, endParent); + range.setEndBefore(endParent); + if (domUtils.isEmptyNode(endParent)) { + domUtils.remove(endParent); + } + + modifyEnd = 1; + } + + + } + + if (!modifyStart) { + range.setStartBefore(me.document.getElementById(bko.start)); + } + if (bko.end && !modifyEnd) { + range.setEndAfter(me.document.getElementById(bko.end)); + } + range.enlarge(true, function (node) { + return notExchange[node.tagName]; + }); + + frag = me.document.createDocumentFragment(); + + var bk = range.createBookmark(), + current = domUtils.getNextDomNode(bk.start, false, filterFn), + tmpRange = range.cloneRange(), + tmpNode, + block = domUtils.isBlockElm; + + while (current && current !== bk.end && (domUtils.getPosition(current, bk.end) & domUtils.POSITION_PRECEDING)) { + + if (current.nodeType == 3 || dtd.li[current.tagName]) { + if (current.nodeType == 1 && dtd.$list[current.tagName]) { + while (current.firstChild) { + frag.appendChild(current.firstChild); + } + tmpNode = domUtils.getNextDomNode(current, false, filterFn); + domUtils.remove(current); + current = tmpNode; + continue; + + } + tmpNode = current; + tmpRange.setStartBefore(current); + + while (current && current !== bk.end && (!block(current) || domUtils.isBookmarkNode(current) )) { + tmpNode = current; + current = domUtils.getNextDomNode(current, false, null, function (node) { + return !notExchange[node.tagName]; + }); + } + + if (current && block(current)) { + tmp = domUtils.getNextDomNode(tmpNode, false, filterFn); + if (tmp && domUtils.isBookmarkNode(tmp)) { + current = domUtils.getNextDomNode(tmp, false, filterFn); + tmpNode = tmp; + } + } + tmpRange.setEndAfter(tmpNode); + + current = domUtils.getNextDomNode(tmpNode, false, filterFn); + + var li = range.document.createElement('li'); + + li.appendChild(tmpRange.extractContents()); + if(domUtils.isEmptyNode(li)){ + var tmpNode = range.document.createElement('p'); + while(li.firstChild){ + tmpNode.appendChild(li.firstChild) + } + li.appendChild(tmpNode); + } + frag.appendChild(li); + } else { + current = domUtils.getNextDomNode(current, true, filterFn); + } + } + range.moveToBookmark(bk).collapse(true); + list = me.document.createElement(tag); + setListStyle(list,style); + list.appendChild(frag); + range.insertNode(list); + //当前list上下看能否合并 + adjustList(list, tag, style); + //去掉冗余的tmpDiv + for (var i = 0, ci, tmpDivs = domUtils.getElementsByTagName(list, 'div'); ci = tmpDivs[i++];) { + if (ci.getAttribute('tmpDiv')) { + domUtils.remove(ci, true) + } + } + range.moveToBookmark(bko).select(); + + }, + queryCommandState:function (command) { + var tag = command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul'; + var path = this.selection.getStartElementPath(); + for(var i= 0,ci;ci = path[i++];){ + if(ci.nodeName == 'TABLE'){ + return 0 + } + if(tag == ci.nodeName.toLowerCase()){ + return 1 + }; + } + return 0; + + }, + queryCommandValue:function (command) { + var tag = command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul'; + var path = this.selection.getStartElementPath(), + node; + for(var i= 0,ci;ci = path[i++];){ + if(ci.nodeName == 'TABLE'){ + node = null; + break; + } + if(tag == ci.nodeName.toLowerCase()){ + node = ci; + break; + }; + } + return node ? getStyle(node) || domUtils.getComputedStyle(node, 'list-style-type') : null; + } + }; +}; + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/music.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/music.js new file mode 100644 index 000000000..287d56239 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/music.js @@ -0,0 +1,79 @@ +/** + * 插入音乐命令 + * @file + */ +UE.plugin.register('music', function (){ + var me = this; + function creatInsertStr(url,width,height,align,cssfloat,toEmbed){ + return !toEmbed ? + '' + : + ''; + } + return { + outputRule: function(root){ + utils.each(root.getNodesByTagName('img'),function(node){ + var html; + if(node.getAttr('class') == 'edui-faked-music'){ + var cssfloat = node.getStyle('float'); + var align = node.getAttr('align'); + html = creatInsertStr(node.getAttr("_url"), node.getAttr('width'), node.getAttr('height'), align, cssfloat, true); + var embed = UE.uNode.createElement(html); + node.parentNode.replaceChild(embed,node); + } + }) + }, + inputRule:function(root){ + utils.each(root.getNodesByTagName('embed'),function(node){ + if(node.getAttr('class') == 'edui-faked-music'){ + var cssfloat = node.getStyle('float'); + var align = node.getAttr('align'); + html = creatInsertStr(node.getAttr("src"), node.getAttr('width'), node.getAttr('height'), align, cssfloat,false); + var img = UE.uNode.createElement(html); + node.parentNode.replaceChild(img,node); + } + }) + + }, + commands:{ + /** + * 插入音乐 + * @command music + * @method execCommand + * @param { Object } musicOptions 插入音乐的参数项, 支持的key有: url=>音乐地址; + * width=>音乐容器宽度;height=>音乐容器高度;align=>音乐文件的对齐方式, 可选值有: left, center, right, none + * @example + * ```javascript + * //editor是编辑器实例 + * //在编辑器里插入一个“植物大战僵尸”的APP + * editor.execCommand( 'music' , { + * width: 400, + * height: 95, + * align: "center", + * url: "音乐地址" + * } ); + * ``` + */ + 'music':{ + execCommand:function (cmd, musicObj) { + var me = this, + str = creatInsertStr(musicObj.url, musicObj.width || 400, musicObj.height || 95, "none", false); + me.execCommand("inserthtml",str); + }, + queryCommandState:function () { + var me = this, + img = me.selection.getRange().getClosedNode(), + flag = img && (img.className == "edui-faked-music"); + return flag ? 1 : 0; + } + } + } + } +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/pagebreak.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/pagebreak.js new file mode 100644 index 000000000..b21850908 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/pagebreak.js @@ -0,0 +1,160 @@ +/** + * 分页功能插件 + * @file + * @since 1.2.6.1 + */ +UE.plugins['pagebreak'] = function () { + var me = this, + notBreakTags = ['td']; + me.setOpt('pageBreakTag','_ueditor_page_break_tag_'); + + function fillNode(node){ + if(domUtils.isEmptyBlock(node)){ + var firstChild = node.firstChild,tmpNode; + + while(firstChild && firstChild.nodeType == 1 && domUtils.isEmptyBlock(firstChild)){ + tmpNode = firstChild; + firstChild = firstChild.firstChild; + } + !tmpNode && (tmpNode = node); + domUtils.fillNode(me.document,tmpNode); + } + } + //分页符样式添加 + + me.ready(function(){ + utils.cssRule('pagebreak','.pagebreak{display:block;clear:both !important;cursor:default !important;width: 100% !important;margin:0;}',me.document); + }); + function isHr(node){ + return node && node.nodeType == 1 && node.tagName == 'HR' && node.className == 'pagebreak'; + } + me.addInputRule(function(root){ + root.traversal(function(node){ + if(node.type == 'text' && node.data == me.options.pageBreakTag){ + var hr = UE.uNode.createElement('
    '); + node.parentNode.insertBefore(hr,node); + node.parentNode.removeChild(node) + } + }) + }); + me.addOutputRule(function(node){ + utils.each(node.getNodesByTagName('hr'),function(n){ + if(n.getAttr('class') == 'pagebreak'){ + var txt = UE.uNode.createText(me.options.pageBreakTag); + n.parentNode.insertBefore(txt,n); + n.parentNode.removeChild(n); + } + }) + + }); + + /** + * 插入分页符 + * @command pagebreak + * @method execCommand + * @param { String } cmd 命令字符串 + * @remind 在表格中插入分页符会把表格切分成两部分 + * @remind 获取编辑器内的数据时, 编辑器会把分页符转换成“_ueditor_page_break_tag_”字符串, + * 以便于提交数据到服务器端后处理分页。 + * @example + * ```javascript + * editor.execCommand( 'pagebreak'); //插入一个hr标签,带有样式类名pagebreak + * ``` + */ + + me.commands['pagebreak'] = { + execCommand:function () { + var range = me.selection.getRange(),hr = me.document.createElement('hr'); + domUtils.setAttributes(hr,{ + 'class' : 'pagebreak', + noshade:"noshade", + size:"5" + }); + domUtils.unSelectable(hr); + //table单独处理 + var node = domUtils.findParentByTagName(range.startContainer, notBreakTags, true), + + parents = [], pN; + if (node) { + switch (node.tagName) { + case 'TD': + pN = node.parentNode; + if (!pN.previousSibling) { + var table = domUtils.findParentByTagName(pN, 'table'); +// var tableWrapDiv = table.parentNode; +// if(tableWrapDiv && tableWrapDiv.nodeType == 1 +// && tableWrapDiv.tagName == 'DIV' +// && tableWrapDiv.getAttribute('dropdrag') +// ){ +// domUtils.remove(tableWrapDiv,true); +// } + table.parentNode.insertBefore(hr, table); + parents = domUtils.findParents(hr, true); + + } else { + pN.parentNode.insertBefore(hr, pN); + parents = domUtils.findParents(hr); + + } + pN = parents[1]; + if (hr !== pN) { + domUtils.breakParent(hr, pN); + + } + //table要重写绑定一下拖拽 + me.fireEvent('afteradjusttable',me.document); + } + + } else { + + if (!range.collapsed) { + range.deleteContents(); + var start = range.startContainer; + while ( !domUtils.isBody(start) && domUtils.isBlockElm(start) && domUtils.isEmptyNode(start)) { + range.setStartBefore(start).collapse(true); + domUtils.remove(start); + start = range.startContainer; + } + + } + range.insertNode(hr); + + var pN = hr.parentNode, nextNode; + while (!domUtils.isBody(pN)) { + domUtils.breakParent(hr, pN); + nextNode = hr.nextSibling; + if (nextNode && domUtils.isEmptyBlock(nextNode)) { + domUtils.remove(nextNode); + } + pN = hr.parentNode; + } + nextNode = hr.nextSibling; + var pre = hr.previousSibling; + if(isHr(pre)){ + domUtils.remove(pre); + }else{ + pre && fillNode(pre); + } + + if(!nextNode){ + var p = me.document.createElement('p'); + + hr.parentNode.appendChild(p); + domUtils.fillNode(me.document,p); + range.setStart(p,0).collapse(true); + }else{ + if(isHr(nextNode)){ + domUtils.remove(nextNode); + }else{ + fillNode(nextNode); + } + range.setEndAfter(hr).collapse(false); + } + + range.select(true); + + } + + } + }; +}; \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/paragraph.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/paragraph.js new file mode 100644 index 000000000..64b5f2867 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/paragraph.js @@ -0,0 +1,170 @@ +/** + * 段落样式 + * @file + * @since 1.2.6.1 + */ + +/** + * 段落格式 + * @command paragraph + * @method execCommand + * @param { String } cmd 命令字符串 + * @param {String} style 标签值为:'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' + * @param {Object} attrs 标签的属性 + * @example + * ```javascript + * editor.execCommand( 'Paragraph','h1','{ + * class:'test' + * }' ); + * ``` + */ + +/** + * 返回选区内节点标签名 + * @command paragraph + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 节点标签名 + * @example + * ```javascript + * editor.queryCommandValue( 'Paragraph' ); + * ``` + */ + +UE.plugins['paragraph'] = function() { + var me = this, + block = domUtils.isBlockElm, + notExchange = ['TD','LI','PRE'], + + doParagraph = function(range,style,attrs,sourceCmdName){ + var bookmark = range.createBookmark(), + filterFn = function( node ) { + return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' && !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace( node ); + }, + para; + + range.enlarge( true ); + var bookmark2 = range.createBookmark(), + current = domUtils.getNextDomNode( bookmark2.start, false, filterFn ), + tmpRange = range.cloneRange(), + tmpNode; + while ( current && !(domUtils.getPosition( current, bookmark2.end ) & domUtils.POSITION_FOLLOWING) ) { + if ( current.nodeType == 3 || !block( current ) ) { + tmpRange.setStartBefore( current ); + while ( current && current !== bookmark2.end && !block( current ) ) { + tmpNode = current; + current = domUtils.getNextDomNode( current, false, null, function( node ) { + return !block( node ); + } ); + } + tmpRange.setEndAfter( tmpNode ); + + para = range.document.createElement( style ); + if(attrs){ + domUtils.setAttributes(para,attrs); + if(sourceCmdName && sourceCmdName == 'customstyle' && attrs.style){ + para.style.cssText = attrs.style; + } + } + para.appendChild( tmpRange.extractContents() ); + //需要内容占位 + if(domUtils.isEmptyNode(para)){ + domUtils.fillChar(range.document,para); + + } + + tmpRange.insertNode( para ); + + var parent = para.parentNode; + //如果para上一级是一个block元素且不是body,td就删除它 + if ( block( parent ) && !domUtils.isBody( para.parentNode ) && utils.indexOf(notExchange,parent.tagName)==-1) { + //存储dir,style + if(!(sourceCmdName && sourceCmdName == 'customstyle')){ + parent.getAttribute('dir') && para.setAttribute('dir',parent.getAttribute('dir')); + //trace:1070 + parent.style.cssText && (para.style.cssText = parent.style.cssText + ';' + para.style.cssText); + //trace:1030 + parent.style.textAlign && !para.style.textAlign && (para.style.textAlign = parent.style.textAlign); + parent.style.textIndent && !para.style.textIndent && (para.style.textIndent = parent.style.textIndent); + parent.style.padding && !para.style.padding && (para.style.padding = parent.style.padding); + } + + //trace:1706 选择的就是h1-6要删除 + if(attrs && /h\d/i.test(parent.tagName) && !/h\d/i.test(para.tagName) ){ + domUtils.setAttributes(parent,attrs); + if(sourceCmdName && sourceCmdName == 'customstyle' && attrs.style){ + parent.style.cssText = attrs.style; + } + domUtils.remove(para,true); + para = parent; + }else{ + domUtils.remove( para.parentNode, true ); + } + + } + if( utils.indexOf(notExchange,parent.tagName)!=-1){ + current = parent; + }else{ + current = para; + } + + + current = domUtils.getNextDomNode( current, false, filterFn ); + } else { + current = domUtils.getNextDomNode( current, true, filterFn ); + } + } + return range.moveToBookmark( bookmark2 ).moveToBookmark( bookmark ); + }; + me.setOpt('paragraph',{'p':'', 'h1':'', 'h2':'', 'h3':'', 'h4':'', 'h5':'', 'h6':''}); + me.commands['paragraph'] = { + execCommand : function( cmdName, style,attrs,sourceCmdName ) { + var range = this.selection.getRange(); + //闭合时单独处理 + if(range.collapsed){ + var txt = this.document.createTextNode('p'); + range.insertNode(txt); + //去掉冗余的fillchar + if(browser.ie){ + var node = txt.previousSibling; + if(node && domUtils.isWhitespace(node)){ + domUtils.remove(node); + } + node = txt.nextSibling; + if(node && domUtils.isWhitespace(node)){ + domUtils.remove(node); + } + } + + } + range = doParagraph(range,style,attrs,sourceCmdName); + if(txt){ + range.setStartBefore(txt).collapse(true); + pN = txt.parentNode; + + domUtils.remove(txt); + + if(domUtils.isBlockElm(pN)&&domUtils.isEmptyNode(pN)){ + domUtils.fillNode(this.document,pN); + } + + } + + if(browser.gecko && range.collapsed && range.startContainer.nodeType == 1){ + var child = range.startContainer.childNodes[range.startOffset]; + if(child && child.nodeType == 1 && child.tagName.toLowerCase() == style){ + range.setStart(child,0).collapse(true); + } + } + //trace:1097 原来有true,原因忘了,但去了就不能清除多余的占位符了 + range.select(); + + + return true; + }, + queryCommandValue : function() { + var node = domUtils.filterNodeList(this.selection.getStartElementPath(),'p h1 h2 h3 h4 h5 h6'); + return node ? node.tagName.toLowerCase() : ''; + } + }; +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/paste.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/paste.js new file mode 100644 index 000000000..04aa52e86 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/paste.js @@ -0,0 +1,305 @@ +///import core +///import plugins/inserthtml.js +///import plugins/undo.js +///import plugins/serialize.js +///commands 粘贴 +///commandsName PastePlain +///commandsTitle 纯文本粘贴模式 +/** + * @description 粘贴 + * @author zhanyi + */ +UE.plugins['paste'] = function () { + function getClipboardData(callback) { + var doc = this.document; + if (doc.getElementById('baidu_pastebin')) { + return; + } + var range = this.selection.getRange(), + bk = range.createBookmark(), + //创建剪贴的容器div + pastebin = doc.createElement('div'); + pastebin.id = 'baidu_pastebin'; + // Safari 要求div必须有内容,才能粘贴内容进来 + browser.webkit && pastebin.appendChild(doc.createTextNode(domUtils.fillChar + domUtils.fillChar)); + doc.body.appendChild(pastebin); + //trace:717 隐藏的span不能得到top + //bk.start.innerHTML = ' '; + bk.start.style.display = ''; + pastebin.style.cssText = "position:absolute;width:1px;height:1px;overflow:hidden;left:-1000px;white-space:nowrap;top:" + + //要在现在光标平行的位置加入,否则会出现跳动的问题 + domUtils.getXY(bk.start).y + 'px'; + + range.selectNodeContents(pastebin).select(true); + + setTimeout(function () { + if (browser.webkit) { + for (var i = 0, pastebins = doc.querySelectorAll('#baidu_pastebin'), pi; pi = pastebins[i++];) { + if (domUtils.isEmptyNode(pi)) { + domUtils.remove(pi); + } else { + pastebin = pi; + break; + } + } + } + try { + pastebin.parentNode.removeChild(pastebin); + } catch (e) { + } + range.moveToBookmark(bk).select(true); + callback(pastebin); + }, 0); + } + + var me = this; + + me.setOpt({ + retainOnlyLabelPasted : false + }); + + var txtContent, htmlContent, address; + + function getPureHtml(html){ + return html.replace(/<(\/?)([\w\-]+)([^>]*)>/gi, function (a, b, tagName, attrs) { + tagName = tagName.toLowerCase(); + if ({img: 1}[tagName]) { + return a; + } + attrs = attrs.replace(/([\w\-]*?)\s*=\s*(("([^"]*)")|('([^']*)')|([^\s>]+))/gi, function (str, atr, val) { + if ({ + 'src': 1, + 'href': 1, + 'name': 1 + }[atr.toLowerCase()]) { + return atr + '=' + val + ' ' + } + return '' + }); + if ({ + 'span': 1, + 'div': 1 + }[tagName]) { + return '' + } else { + + return '<' + b + tagName + ' ' + utils.trim(attrs) + '>' + } + + }); + } + function filter(div) { + var html; + if (div.firstChild) { + //去掉cut中添加的边界值 + var nodes = domUtils.getElementsByTagName(div, 'span'); + for (var i = 0, ni; ni = nodes[i++];) { + if (ni.id == '_baidu_cut_start' || ni.id == '_baidu_cut_end') { + domUtils.remove(ni); + } + } + + if (browser.webkit) { + + var brs = div.querySelectorAll('div br'); + for (var i = 0, bi; bi = brs[i++];) { + var pN = bi.parentNode; + if (pN.tagName == 'DIV' && pN.childNodes.length == 1) { + pN.innerHTML = '


    '; + domUtils.remove(pN); + } + } + var divs = div.querySelectorAll('#baidu_pastebin'); + for (var i = 0, di; di = divs[i++];) { + var tmpP = me.document.createElement('p'); + di.parentNode.insertBefore(tmpP, di); + while (di.firstChild) { + tmpP.appendChild(di.firstChild); + } + domUtils.remove(di); + } + + var metas = div.querySelectorAll('meta'); + for (var i = 0, ci; ci = metas[i++];) { + domUtils.remove(ci); + } + + var brs = div.querySelectorAll('br'); + for (i = 0; ci = brs[i++];) { + if (/^apple-/i.test(ci.className)) { + domUtils.remove(ci); + } + } + } + if (browser.gecko) { + var dirtyNodes = div.querySelectorAll('[_moz_dirty]'); + for (i = 0; ci = dirtyNodes[i++];) { + ci.removeAttribute('_moz_dirty'); + } + } + if (!browser.ie) { + var spans = div.querySelectorAll('span.Apple-style-span'); + for (var i = 0, ci; ci = spans[i++];) { + domUtils.remove(ci, true); + } + } + + //ie下使用innerHTML会产生多余的\r\n字符,也会产生 这里过滤掉 + html = div.innerHTML;//.replace(/>(?:(\s| )*?)<'); + + //过滤word粘贴过来的冗余属性 + html = UE.filterWord(html); + //取消了忽略空白的第二个参数,粘贴过来的有些是有空白的,会被套上相关的标签 + var root = UE.htmlparser(html); + //如果给了过滤规则就先进行过滤 + if (me.options.filterRules) { + UE.filterNode(root, me.options.filterRules); + } + //执行默认的处理 + me.filterInputRule(root); + //针对chrome的处理 + if (browser.webkit) { + var br = root.lastChild(); + if (br && br.type == 'element' && br.tagName == 'br') { + root.removeChild(br) + } + utils.each(me.body.querySelectorAll('div'), function (node) { + if (domUtils.isEmptyBlock(node)) { + domUtils.remove(node,true) + } + }) + } + html = {'html': root.toHtml()}; + me.fireEvent('beforepaste', html, root); + //抢了默认的粘贴,那后边的内容就不执行了,比如表格粘贴 + if(!html.html){ + return; + } + root = UE.htmlparser(html.html,true); + //如果开启了纯文本模式 + if (me.queryCommandState('pasteplain') === 1) { + me.execCommand('insertHtml', UE.filterNode(root, me.options.filterTxtRules).toHtml(), true); + } else { + //文本模式 + UE.filterNode(root, me.options.filterTxtRules); + txtContent = root.toHtml(); + //完全模式 + htmlContent = html.html; + + address = me.selection.getRange().createAddress(true); + me.execCommand('insertHtml', me.getOpt('retainOnlyLabelPasted') === true ? getPureHtml(htmlContent) : htmlContent, true); + } + me.fireEvent("afterpaste", html); + } + } + + me.addListener('pasteTransfer', function (cmd, plainType) { + + if (address && txtContent && htmlContent && txtContent != htmlContent) { + var range = me.selection.getRange(); + range.moveToAddress(address, true); + + if (!range.collapsed) { + + while (!domUtils.isBody(range.startContainer) + ) { + var start = range.startContainer; + if(start.nodeType == 1){ + start = start.childNodes[range.startOffset]; + if(!start){ + range.setStartBefore(range.startContainer); + continue; + } + var pre = start.previousSibling; + + if(pre && pre.nodeType == 3 && new RegExp('^[\n\r\t '+domUtils.fillChar+']*$').test(pre.nodeValue)){ + range.setStartBefore(pre) + } + } + if(range.startOffset == 0){ + range.setStartBefore(range.startContainer); + }else{ + break; + } + + } + while (!domUtils.isBody(range.endContainer) + ) { + var end = range.endContainer; + if(end.nodeType == 1){ + end = end.childNodes[range.endOffset]; + if(!end){ + range.setEndAfter(range.endContainer); + continue; + } + var next = end.nextSibling; + if(next && next.nodeType == 3 && new RegExp('^[\n\r\t'+domUtils.fillChar+']*$').test(next.nodeValue)){ + range.setEndAfter(next) + } + } + if(range.endOffset == range.endContainer[range.endContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length){ + range.setEndAfter(range.endContainer); + }else{ + break; + } + + } + + } + + range.deleteContents(); + range.select(true); + me.__hasEnterExecCommand = true; + var html = htmlContent; + if (plainType === 2 ) { + html = getPureHtml(html); + } else if (plainType) { + html = txtContent; + } + me.execCommand('inserthtml', html, true); + me.__hasEnterExecCommand = false; + var rng = me.selection.getRange(); + while (!domUtils.isBody(rng.startContainer) && !rng.startOffset && + rng.startContainer[rng.startContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length + ) { + rng.setStartBefore(rng.startContainer); + } + var tmpAddress = rng.createAddress(true); + address.endAddress = tmpAddress.startAddress; + } + }); + + me.addListener('ready', function () { + domUtils.on(me.body, 'cut', function () { + var range = me.selection.getRange(); + if (!range.collapsed && me.undoManger) { + me.undoManger.save(); + } + }); + + //ie下beforepaste在点击右键时也会触发,所以用监控键盘才处理 + domUtils.on(me.body, browser.ie || browser.opera ? 'keydown' : 'paste', function (e) { + if ((browser.ie || browser.opera) && ((!e.ctrlKey && !e.metaKey) || e.keyCode != '86')) { + return; + } + getClipboardData.call(me, function (div) { + filter(div); + }); + }); + + }); + + me.commands['paste'] = { + execCommand: function (cmd) { + if (browser.ie) { + getClipboardData.call(me, function (div) { + filter(div); + }); + me.document.execCommand('paste'); + } else { + alert(me.getLang('pastemsg')); + } + } + } +}; + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/preview.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/preview.js new file mode 100644 index 000000000..712a7f56c --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/preview.js @@ -0,0 +1,28 @@ +/** + * 预览 + * @file + * @since 1.2.6.1 + */ + +/** + * 预览 + * @command preview + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'preview' ); + * ``` + */ +UE.commands['preview'] = { + execCommand : function(){ + var w = window.open('', '_blank', ''), + d = w.document; + d.open(); + d.write('
    '+this.getContent(null,null,true)+'
    '); + d.close(); + }, + notNeedUndo : 1 +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/print.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/print.js new file mode 100644 index 000000000..597e23ffe --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/print.js @@ -0,0 +1,23 @@ +/** + * 打印 + * @file + * @since 1.2.6.1 + */ + +/** + * 打印 + * @command print + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'print' ); + * ``` + */ +UE.commands['print'] = { + execCommand : function(){ + this.window.print(); + }, + notNeedUndo : 1 +}; + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/puretxtpaste.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/puretxtpaste.js new file mode 100644 index 000000000..e016f88de --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/puretxtpaste.js @@ -0,0 +1,98 @@ +/** + * 纯文本粘贴插件 + * @file + * @since 1.2.6.1 + */ + +UE.plugins['pasteplain'] = function(){ + var me = this; + me.setOpt({ + 'pasteplain':false, + 'filterTxtRules' : function(){ + function transP(node){ + node.tagName = 'p'; + node.setStyle(); + } + function removeNode(node){ + node.parentNode.removeChild(node,true) + } + return { + //直接删除及其字节点内容 + '-' : 'script style object iframe embed input select', + 'p': {$:{}}, + 'br':{$:{}}, + div: function (node) { + var tmpNode, p = UE.uNode.createElement('p'); + while (tmpNode = node.firstChild()) { + if (tmpNode.type == 'text' || !UE.dom.dtd.$block[tmpNode.tagName]) { + p.appendChild(tmpNode); + } else { + if (p.firstChild()) { + node.parentNode.insertBefore(p, node); + p = UE.uNode.createElement('p'); + } else { + node.parentNode.insertBefore(tmpNode, node); + } + } + } + if (p.firstChild()) { + node.parentNode.insertBefore(p, node); + } + node.parentNode.removeChild(node); + }, + ol: removeNode, + ul: removeNode, + dl:removeNode, + dt:removeNode, + dd:removeNode, + 'li':removeNode, + 'caption':transP, + 'th':transP, + 'tr':transP, + 'h1':transP,'h2':transP,'h3':transP,'h4':transP,'h5':transP,'h6':transP, + 'td':function(node){ + //没有内容的td直接删掉 + var txt = !!node.innerText(); + if(txt){ + node.parentNode.insertAfter(UE.uNode.createText('    '),node); + } + node.parentNode.removeChild(node,node.innerText()) + } + } + }() + }); + //暂时这里支持一下老版本的属性 + var pasteplain = me.options.pasteplain; + + /** + * 启用或取消纯文本粘贴模式 + * @command pasteplain + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.queryCommandState( 'pasteplain' ); + * ``` + */ + + /** + * 查询当前是否处于纯文本粘贴模式 + * @command pasteplain + * @method queryCommandState + * @param { String } cmd 命令字符串 + * @return { int } 如果处于纯文本模式,返回1,否则,返回0 + * @example + * ```javascript + * editor.queryCommandState( 'pasteplain' ); + * ``` + */ + me.commands['pasteplain'] = { + queryCommandState: function (){ + return pasteplain ? 1 : 0; + }, + execCommand: function (){ + pasteplain = !pasteplain|0; + }, + notNeedUndo : 1 + }; +}; \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/removeformat.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/removeformat.js new file mode 100644 index 000000000..2b8601183 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/removeformat.js @@ -0,0 +1,182 @@ +/** + * 清除格式 + * @file + * @since 1.2.6.1 + */ + +/** + * 清除文字样式 + * @command removeformat + * @method execCommand + * @param { String } cmd 命令字符串 + * @param {String} tags 以逗号隔开的标签。如:strong + * @param {String} style 样式如:color + * @param {String} attrs 属性如:width + * @example + * ```javascript + * editor.execCommand( 'removeformat', 'strong','color','width' ); + * ``` + */ + +UE.plugins['removeformat'] = function(){ + var me = this; + me.setOpt({ + 'removeFormatTags': 'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var', + 'removeFormatAttributes':'class,style,lang,width,height,align,hspace,valign' + }); + me.commands['removeformat'] = { + execCommand : function( cmdName, tags, style, attrs,notIncludeA ) { + + var tagReg = new RegExp( '^(?:' + (tags || this.options.removeFormatTags).replace( /,/g, '|' ) + ')$', 'i' ) , + removeFormatAttributes = style ? [] : (attrs || this.options.removeFormatAttributes).split( ',' ), + range = new dom.Range( this.document ), + bookmark,node,parent, + filter = function( node ) { + return node.nodeType == 1; + }; + + function isRedundantSpan (node) { + if (node.nodeType == 3 || node.tagName.toLowerCase() != 'span'){ + return 0; + } + if (browser.ie) { + //ie 下判断实效,所以只能简单用style来判断 + //return node.style.cssText == '' ? 1 : 0; + var attrs = node.attributes; + if ( attrs.length ) { + for ( var i = 0,l = attrs.length; i + var node = range.startContainer, + tmp, + collapsed = range.collapsed; + while(node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]){ + tmp = node.parentNode; + range.setStartBefore(node); + //trace:937 + //更新结束边界 + if(range.startContainer === range.endContainer){ + range.endOffset--; + } + domUtils.remove(node); + node = tmp; + } + + if(!collapsed){ + node = range.endContainer; + while(node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]){ + tmp = node.parentNode; + range.setEndBefore(node); + domUtils.remove(node); + + node = tmp; + } + + + } + } + + + + range = this.selection.getRange(); + doRemove( range ); + range.select(); + + } + + }; + +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/rowspacing.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/rowspacing.js new file mode 100644 index 000000000..3dca5b188 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/rowspacing.js @@ -0,0 +1,46 @@ +/** + * 段前段后间距插件 + * @file + * @since 1.2.6.1 + */ + +/** + * 设置段间距 + * @command rowspacing + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } value 段间距的值,以px为单位 + * @param { String } dir 间距位置,top或bottom,分别表示段前和段后 + * @example + * ```javascript + * editor.execCommand( 'rowspacing', '10', 'top' ); + * ``` + */ + +UE.plugins['rowspacing'] = function(){ + var me = this; + me.setOpt({ + 'rowspacingtop':['5', '10', '15', '20', '25'], + 'rowspacingbottom':['5', '10', '15', '20', '25'] + + }); + me.commands['rowspacing'] = { + execCommand : function( cmdName,value,dir ) { + this.execCommand('paragraph','p',{style:'margin-'+dir+':'+value + 'px'}); + return true; + }, + queryCommandValue : function(cmdName,dir) { + var pN = domUtils.filterNodeList(this.selection.getStartElementPath(),function(node){return domUtils.isBlockElm(node) }), + value; + //trace:1026 + if(pN){ + value = domUtils.getComputedStyle(pN,'margin-'+dir).replace(/[^\d]/g,''); + return !value ? 0 : value; + } + return 0; + + } + }; +}; + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/scrawl.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/scrawl.js new file mode 100644 index 000000000..b7e17a3a6 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/scrawl.js @@ -0,0 +1,10 @@ +///import core +///commands 涂鸦 +///commandsName Scrawl +///commandsTitle 涂鸦 +///commandsDialog dialogs\scrawl +UE.commands['scrawl'] = { + queryCommandState : function(){ + return ( browser.ie && browser.version <= 8 ) ? -1 :0; + } +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/searchreplace.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/searchreplace.js new file mode 100644 index 000000000..f1504c1c3 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/searchreplace.js @@ -0,0 +1,193 @@ +///import core +///commands 查找替换 +///commandsName SearchReplace +///commandsTitle 查询替换 +///commandsDialog dialogs\searchreplace +/** + * @description 查找替换 + * @author zhanyi + */ + +UE.plugin.register('searchreplace',function(){ + var me = this; + + var _blockElm = {'table':1,'tbody':1,'tr':1,'ol':1,'ul':1}; + + function findTextInString(textContent,opt,currentIndex){ + var str = opt.searchStr; + if(opt.dir == -1){ + textContent = textContent.split('').reverse().join(''); + str = str.split('').reverse().join(''); + currentIndex = textContent.length - currentIndex; + + } + var reg = new RegExp(str,'g' + (opt.casesensitive ? '' : 'i')),match; + + while(match = reg.exec(textContent)){ + if(match.index >= currentIndex){ + return opt.dir == -1 ? textContent.length - match.index - opt.searchStr.length : match.index; + } + } + return -1 + } + function findTextBlockElm(node,currentIndex,opt){ + var textContent,index,methodName = opt.all || opt.dir == 1 ? 'getNextDomNode' : 'getPreDomNode'; + if(domUtils.isBody(node)){ + node = node.firstChild; + } + var first = 1; + while(node){ + textContent = node.nodeType == 3 ? node.nodeValue : node[browser.ie ? 'innerText' : 'textContent']; + index = findTextInString(textContent,opt,currentIndex ); + first = 0; + if(index!=-1){ + return { + 'node':node, + 'index':index + } + } + node = domUtils[methodName](node); + while(node && _blockElm[node.nodeName.toLowerCase()]){ + node = domUtils[methodName](node,true); + } + if(node){ + currentIndex = opt.dir == -1 ? (node.nodeType == 3 ? node.nodeValue : node[browser.ie ? 'innerText' : 'textContent']).length : 0; + } + + } + } + function findNTextInBlockElm(node,index,str){ + var currentIndex = 0, + currentNode = node.firstChild, + currentNodeLength = 0, + result; + while(currentNode){ + if(currentNode.nodeType == 3){ + currentNodeLength = currentNode.nodeValue.replace(/(^[\t\r\n]+)|([\t\r\n]+$)/,'').length; + currentIndex += currentNodeLength; + if(currentIndex >= index){ + return { + 'node':currentNode, + 'index': currentNodeLength - (currentIndex - index) + } + } + }else if(!dtd.$empty[currentNode.tagName]){ + currentNodeLength = currentNode[browser.ie ? 'innerText' : 'textContent'].replace(/(^[\t\r\n]+)|([\t\r\n]+$)/,'').length + currentIndex += currentNodeLength; + if(currentIndex >= index){ + result = findNTextInBlockElm(currentNode,currentNodeLength - (currentIndex - index),str); + if(result){ + return result; + } + } + } + currentNode = domUtils.getNextDomNode(currentNode); + + } + } + + function searchReplace(me,opt){ + + var rng = me.selection.getRange(), + startBlockNode, + searchStr = opt.searchStr, + span = me.document.createElement('span'); + span.innerHTML = '$$ueditor_searchreplace_key$$'; + + rng.shrinkBoundary(true); + + //判断是不是第一次选中 + if(!rng.collapsed){ + rng.select(); + var rngText = me.selection.getText(); + if(new RegExp('^' + opt.searchStr + '$',(opt.casesensitive ? '' : 'i')).test(rngText)){ + if(opt.replaceStr != undefined){ + replaceText(rng,opt.replaceStr); + rng.select(); + return true; + }else{ + rng.collapse(opt.dir == -1) + } + + } + } + + + rng.insertNode(span); + rng.enlargeToBlockElm(true); + startBlockNode = rng.startContainer; + var currentIndex = startBlockNode[browser.ie ? 'innerText' : 'textContent'].indexOf('$$ueditor_searchreplace_key$$'); + rng.setStartBefore(span); + domUtils.remove(span); + var result = findTextBlockElm(startBlockNode,currentIndex,opt); + if(result){ + var rngStart = findNTextInBlockElm(result.node,result.index,searchStr); + var rngEnd = findNTextInBlockElm(result.node,result.index + searchStr.length,searchStr); + rng.setStart(rngStart.node,rngStart.index).setEnd(rngEnd.node,rngEnd.index); + + if(opt.replaceStr !== undefined){ + replaceText(rng,opt.replaceStr) + } + rng.select(); + return true; + }else{ + rng.setCursor() + } + + } + function replaceText(rng,str){ + + str = me.document.createTextNode(str); + rng.deleteContents().insertNode(str); + + } + return { + commands:{ + 'searchreplace':{ + execCommand:function(cmdName,opt){ + utils.extend(opt,{ + all : false, + casesensitive : false, + dir : 1 + },true); + var num = 0; + if(opt.all){ + + var rng = me.selection.getRange(), + first = me.body.firstChild; + if(first && first.nodeType == 1){ + rng.setStart(first,0); + rng.shrinkBoundary(true); + }else if(first.nodeType == 3){ + rng.setStartBefore(first) + } + rng.collapse(true).select(true); + if(opt.replaceStr !== undefined){ + me.fireEvent('saveScene'); + } + while(searchReplace(this,opt)){ + num++; + } + if(num){ + me.fireEvent('saveScene'); + } + }else{ + if(opt.replaceStr !== undefined){ + me.fireEvent('saveScene'); + } + if(searchReplace(this,opt)){ + num++ + } + if(num){ + me.fireEvent('saveScene'); + } + + } + + return num; + }, + notNeedUndo:1 + } + } + } +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/section.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/section.js new file mode 100644 index 000000000..07f206e78 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/section.js @@ -0,0 +1,269 @@ +/** + * 目录大纲支持插件 + * @file + * @since 1.3.0 + */ +UE.plugin.register('section', function (){ + /* 目录节点对象 */ + function Section(option){ + this.tag = ''; + this.level = -1, + this.dom = null; + this.nextSection = null; + this.previousSection = null; + this.parentSection = null; + this.startAddress = []; + this.endAddress = []; + this.children = []; + } + function getSection(option) { + var section = new Section(); + return utils.extend(section, option); + } + function getNodeFromAddress(startAddress, root) { + var current = root; + for(var i = 0;i < startAddress.length; i++) { + if(!current.childNodes) return null; + current = current.childNodes[startAddress[i]]; + } + return current; + } + + var me = this; + + return { + bindMultiEvents:{ + type: 'aftersetcontent afterscencerestore', + handler: function(){ + me.fireEvent('updateSections'); + } + }, + bindEvents:{ + /* 初始化、拖拽、粘贴、执行setcontent之后 */ + 'ready': function (){ + me.fireEvent('updateSections'); + domUtils.on(me.body, 'drop paste', function(){ + me.fireEvent('updateSections'); + }); + }, + /* 执行paragraph命令之后 */ + 'afterexeccommand': function (type, cmd) { + if(cmd == 'paragraph') { + me.fireEvent('updateSections'); + } + }, + /* 部分键盘操作,触发updateSections事件 */ + 'keyup': function (type, e) { + var me = this, + range = me.selection.getRange(); + if(range.collapsed != true) { + me.fireEvent('updateSections'); + } else { + var keyCode = e.keyCode || e.which; + if(keyCode == 13 || keyCode == 8 || keyCode == 46) { + me.fireEvent('updateSections'); + } + } + } + }, + commands:{ + 'getsections': { + execCommand: function (cmd, levels) { + var levelFn = levels || ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']; + + for (var i = 0; i < levelFn.length; i++) { + if (typeof levelFn[i] == 'string') { + levelFn[i] = function(fn){ + return function(node){ + return node.tagName == fn.toUpperCase() + }; + }(levelFn[i]); + } else if (typeof levelFn[i] != 'function') { + levelFn[i] = function (node) { + return null; + } + } + } + function getSectionLevel(node) { + for (var i = 0; i < levelFn.length; i++) { + if (levelFn[i](node)) return i; + } + return -1; + } + + var me = this, + Directory = getSection({'level':-1, 'title':'root'}), + previous = Directory; + + function traversal(node, Directory) { + var level, + tmpSection = null, + parent, + child, + children = node.childNodes; + for (var i = 0, len = children.length; i < len; i++) { + child = children[i]; + level = getSectionLevel(child); + if (level >= 0) { + var address = me.selection.getRange().selectNode(child).createAddress(true).startAddress, + current = getSection({ + 'tag': child.tagName, + 'title': child.innerText || child.textContent || '', + 'level': level, + 'dom': child, + 'startAddress': utils.clone(address, []), + 'endAddress': utils.clone(address, []), + 'children': [] + }); + previous.nextSection = current; + current.previousSection = previous; + parent = previous; + while(level <= parent.level){ + parent = parent.parentSection; + } + current.parentSection = parent; + parent.children.push(current); + tmpSection = previous = current; + } else { + child.nodeType === 1 && traversal(child, Directory); + tmpSection && tmpSection.endAddress[tmpSection.endAddress.length - 1] ++; + } + } + } + traversal(me.body, Directory); + return Directory; + }, + notNeedUndo: true + }, + 'movesection': { + execCommand: function (cmd, sourceSection, targetSection, isAfter) { + + var me = this, + targetAddress, + target; + + if(!sourceSection || !targetSection || targetSection.level == -1) return; + + targetAddress = isAfter ? targetSection.endAddress:targetSection.startAddress; + target = getNodeFromAddress(targetAddress, me.body); + + /* 判断目标地址是否被源章节包含 */ + if(!targetAddress || !target || isContainsAddress(sourceSection.startAddress, sourceSection.endAddress, targetAddress)) return; + + var startNode = getNodeFromAddress(sourceSection.startAddress, me.body), + endNode = getNodeFromAddress(sourceSection.endAddress, me.body), + current, + nextNode; + + if(isAfter) { + current = endNode; + while ( current && !(domUtils.getPosition( startNode, current ) & domUtils.POSITION_FOLLOWING) ) { + nextNode = current.previousSibling; + domUtils.insertAfter(target, current); + if(current == startNode) break; + current = nextNode; + } + } else { + current = startNode; + while ( current && !(domUtils.getPosition( current, endNode ) & domUtils.POSITION_FOLLOWING) ) { + nextNode = current.nextSibling; + target.parentNode.insertBefore(current, target); + if(current == endNode) break; + current = nextNode; + } + } + + me.fireEvent('updateSections'); + + /* 获取地址的包含关系 */ + function isContainsAddress(startAddress, endAddress, addressTarget){ + var isAfterStartAddress = false, + isBeforeEndAddress = false; + for(var i = 0; i< startAddress.length; i++){ + if(i >= addressTarget.length) break; + if(addressTarget[i] > startAddress[i]) { + isAfterStartAddress = true; + break; + } else if(addressTarget[i] < startAddress[i]) { + break; + } + } + for(var i = 0; i< endAddress.length; i++){ + if(i >= addressTarget.length) break; + if(addressTarget[i] < startAddress[i]) { + isBeforeEndAddress = true; + break; + } else if(addressTarget[i] > startAddress[i]) { + break; + } + } + return isAfterStartAddress && isBeforeEndAddress; + } + } + }, + 'deletesection': { + execCommand: function (cmd, section, keepChildren) { + var me = this; + + if(!section) return; + + function getNodeFromAddress(startAddress) { + var current = me.body; + for(var i = 0;i < startAddress.length; i++) { + if(!current.childNodes) return null; + current = current.childNodes[startAddress[i]]; + } + return current; + } + + var startNode = getNodeFromAddress(section.startAddress), + endNode = getNodeFromAddress(section.endAddress), + current = startNode, + nextNode; + + if(!keepChildren) { + while ( current && domUtils.inDoc(endNode, me.document) && !(domUtils.getPosition( current, endNode ) & domUtils.POSITION_FOLLOWING) ) { + nextNode = current.nextSibling; + domUtils.remove(current); + current = nextNode; + } + } else { + domUtils.remove(current); + } + + me.fireEvent('updateSections'); + } + }, + 'selectsection': { + execCommand: function (cmd, section) { + if(!section && !section.dom) return false; + var me = this, + range = me.selection.getRange(), + address = { + 'startAddress':utils.clone(section.startAddress, []), + 'endAddress':utils.clone(section.endAddress, []) + }; + address.endAddress[address.endAddress.length - 1]++; + range.moveToAddress(address).select().scrollToView(); + return true; + }, + notNeedUndo: true + }, + 'scrolltosection': { + execCommand: function (cmd, section) { + if(!section && !section.dom) return false; + var me = this, + range = me.selection.getRange(), + address = { + 'startAddress':section.startAddress, + 'endAddress':section.endAddress + }; + address.endAddress[address.endAddress.length - 1]++; + range.moveToAddress(address).scrollToView(); + return true; + }, + notNeedUndo: true + } + } + } +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/selectall.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/selectall.js new file mode 100644 index 000000000..04bbaf81b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/selectall.js @@ -0,0 +1,42 @@ +/** + * 全选 + * @file + * @since 1.2.6.1 + */ + +/** + * 选中所有内容 + * @command selectall + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'selectall' ); + * ``` + */ +UE.plugins['selectall'] = function(){ + var me = this; + me.commands['selectall'] = { + execCommand : function(){ + //去掉了原生的selectAll,因为会出现报错和当内容为空时,不能出现闭合状态的光标 + var me = this,body = me.body, + range = me.selection.getRange(); + range.selectNodeContents(body); + if(domUtils.isEmptyBlock(body)){ + //opera不能自动合并到元素的里边,要手动处理一下 + if(browser.opera && body.firstChild && body.firstChild.nodeType == 1){ + range.setStartAtFirst(body.firstChild); + } + range.collapse(true); + } + range.select(true); + }, + notNeedUndo : 1 + }; + + + //快捷键 + me.addshortcutkey({ + "selectAll" : "ctrl+65" + }); +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/serverparam.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/serverparam.js new file mode 100644 index 000000000..6dbc9e041 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/serverparam.js @@ -0,0 +1,107 @@ +/** + * 服务器提交的额外参数列表设置插件 + * @file + * @since 1.2.6.1 + */ +UE.plugin.register('serverparam', function (){ + + var me = this, + serverParam = {}; + + return { + commands:{ + /** + * 修改服务器提交的额外参数列表,清除所有项 + * @command serverparam + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand('serverparam'); + * editor.queryCommandValue('serverparam'); //返回空 + * ``` + */ + /** + * 修改服务器提交的额外参数列表,删除指定项 + * @command serverparam + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } key 要清除的属性 + * @example + * ```javascript + * editor.execCommand('serverparam', 'name'); //删除属性name + * ``` + */ + /** + * 修改服务器提交的额外参数列表,使用键值添加项 + * @command serverparam + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } key 要添加的属性 + * @param { String } value 要添加属性的值 + * @example + * ```javascript + * editor.execCommand('serverparam', 'name', 'hello'); + * editor.queryCommandValue('serverparam'); //返回对象 {'name': 'hello'} + * ``` + */ + /** + * 修改服务器提交的额外参数列表,传入键值对对象添加多项 + * @command serverparam + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { Object } key 传入的键值对对象 + * @example + * ```javascript + * editor.execCommand('serverparam', {'name': 'hello'}); + * editor.queryCommandValue('serverparam'); //返回对象 {'name': 'hello'} + * ``` + */ + /** + * 修改服务器提交的额外参数列表,使用自定义函数添加多项 + * @command serverparam + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { Function } key 自定义获取参数的函数 + * @example + * ```javascript + * editor.execCommand('serverparam', function(editor){ + * return {'key': 'value'}; + * }); + * editor.queryCommandValue('serverparam'); //返回对象 {'key': 'value'} + * ``` + */ + + /** + * 获取服务器提交的额外参数列表 + * @command serverparam + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.queryCommandValue( 'serverparam' ); //返回对象 {'key': 'value'} + * ``` + */ + 'serverparam':{ + execCommand:function (cmd, key, value) { + if (key === undefined || key === null) { //不传参数,清空列表 + serverParam = {}; + } else if (utils.isString(key)) { //传入键值 + if(value === undefined || value === null) { + delete serverParam[key]; + } else { + serverParam[key] = value; + } + } else if (utils.isObject(key)) { //传入对象,覆盖列表项 + utils.extend(serverParam, key, true); + } else if (utils.isFunction(key)){ //传入函数,添加列表项 + utils.extend(serverParam, key(), true); + } + }, + queryCommandValue: function(){ + return serverParam || {}; + } + } + } + } +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/shortcutmenu.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/shortcutmenu.js new file mode 100644 index 000000000..400b10e83 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/shortcutmenu.js @@ -0,0 +1,79 @@ +///import core +///commands 弹出菜单 +// commandsName popupmenu +///commandsTitle 弹出菜单 +/** + * 弹出菜单 + * @function + * @name baidu.editor.plugins.popupmenu + * @author xuheng + */ + +UE.plugins['shortcutmenu'] = function () { + var me = this, + menu, + items = me.options.shortcutMenu || []; + + if (!items.length) { + return; + } + + me.addListener ('contextmenu mouseup' , function (type , e) { + var me = this, + customEvt = { + type : type , + target : e.target || e.srcElement , + screenX : e.screenX , + screenY : e.screenY , + clientX : e.clientX , + clientY : e.clientY + }; + + setTimeout (function () { + var rng = me.selection.getRange (); + if (rng.collapsed === false || type == "contextmenu") { + + if (!menu) { + menu = new baidu.editor.ui.ShortCutMenu ({ + editor : me , + items : items , + theme : me.options.theme , + className : 'edui-shortcutmenu' + }); + + menu.render (); + me.fireEvent ("afterrendershortcutmenu" , menu); + } + + menu.show (customEvt , !!UE.plugins['contextmenu']); + } + }); + + if (type == 'contextmenu') { + domUtils.preventDefault (e); + if (browser.ie9below) { + var ieRange; + try { + ieRange = me.selection.getNative().createRange(); + } catch (e) { + return; + } + if (ieRange.item) { + var range = new dom.Range (me.document); + range.selectNode (ieRange.item (0)).select (true , true); + + } + } + } + }); + + me.addListener ('keydown' , function (type) { + if (type == "keydown") { + menu && !menu.isHidden && menu.hide (); + } + + }); + +}; + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/simpleupload.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/simpleupload.js new file mode 100644 index 000000000..f706d4417 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/simpleupload.js @@ -0,0 +1,172 @@ +/** + * @description + * 简单上传:点击按钮,直接选择文件上传 + * @author Jinqn + * @date 2014-03-31 + */ +UE.plugin.register('simpleupload', function (){ + var me = this, + isLoaded = false, + containerBtn; + + function initUploadBtn(){ + var w = containerBtn.offsetWidth || 20, + h = containerBtn.offsetHeight || 20, + btnIframe = document.createElement('iframe'), + btnStyle = 'display:block;width:' + w + 'px;height:' + h + 'px;overflow:hidden;border:0;margin:0;padding:0;position:absolute;top:0;left:0;filter:alpha(opacity=0);-moz-opacity:0;-khtml-opacity: 0;opacity: 0;cursor:pointer;'; + + domUtils.on(btnIframe, 'load', function(){ + + var timestrap = (+new Date()).toString(36), + wrapper, + btnIframeDoc, + btnIframeBody; + + btnIframeDoc = (btnIframe.contentDocument || btnIframe.contentWindow.document); + btnIframeBody = btnIframeDoc.body; + wrapper = btnIframeDoc.createElement('div'); + + wrapper.innerHTML = '
    ' + + '' + + '
    ' + + ''; + + wrapper.className = 'edui-' + me.options.theme; + wrapper.id = me.ui.id + '_iframeupload'; + btnIframeBody.style.cssText = btnStyle; + btnIframeBody.style.width = w + 'px'; + btnIframeBody.style.height = h + 'px'; + btnIframeBody.appendChild(wrapper); + + if (btnIframeBody.parentNode) { + btnIframeBody.parentNode.style.width = w + 'px'; + btnIframeBody.parentNode.style.height = w + 'px'; + } + + var form = btnIframeDoc.getElementById('edui_form_' + timestrap); + var input = btnIframeDoc.getElementById('edui_input_' + timestrap); + var iframe = btnIframeDoc.getElementById('edui_iframe_' + timestrap); + + domUtils.on(input, 'change', function(){ + if(!input.value) return; + var loadingId = 'loading_' + (+new Date()).toString(36); + var params = utils.serializeParam(me.queryCommandValue('serverparam')) || ''; + + var imageActionUrl = me.getActionUrl(me.getOpt('imageActionName')); + var allowFiles = me.getOpt('imageAllowFiles'); + + me.focus(); + me.execCommand('inserthtml', ''); + + function callback(){ + try{ + var link, json, loader, + body = (iframe.contentDocument || iframe.contentWindow.document).body, + result = body.innerText || body.textContent || ''; + json = (new Function("return " + result))(); + link = me.options.imageUrlPrefix + json.url; + if(json.state == 'SUCCESS' && json.url) { + loader = me.document.getElementById(loadingId); + loader.setAttribute('src', link); + loader.setAttribute('_src', link); + loader.setAttribute('title', json.title || ''); + loader.setAttribute('alt', json.original || ''); + loader.removeAttribute('id'); + domUtils.removeClasses(loader, 'loadingclass'); + } else { + showErrorLoader && showErrorLoader(json.state); + } + }catch(er){ + showErrorLoader && showErrorLoader(me.getLang('simpleupload.loadError')); + } + form.reset(); + domUtils.un(iframe, 'load', callback); + } + function showErrorLoader(title){ + if(loadingId) { + var loader = me.document.getElementById(loadingId); + loader && domUtils.remove(loader); + me.fireEvent('showmessage', { + 'id': loadingId, + 'content': title, + 'type': 'error', + 'timeout': 4000 + }); + } + } + + /* 判断后端配置是否没有加载成功 */ + if (!me.getOpt('imageActionName')) { + errorHandler(me.getLang('autoupload.errorLoadConfig')); + return; + } + // 判断文件格式是否错误 + var filename = input.value, + fileext = filename ? filename.substr(filename.lastIndexOf('.')):''; + if (!fileext || (allowFiles && (allowFiles.join('') + '.').indexOf(fileext.toLowerCase() + '.') == -1)) { + showErrorLoader(me.getLang('simpleupload.exceedTypeError')); + return; + } + + domUtils.on(iframe, 'load', callback); + form.action = utils.formatUrl(imageActionUrl + (imageActionUrl.indexOf('?') == -1 ? '?':'&') + params); + form.submit(); + }); + + var stateTimer; + me.addListener('selectionchange', function () { + clearTimeout(stateTimer); + stateTimer = setTimeout(function() { + var state = me.queryCommandState('simpleupload'); + if (state == -1) { + input.disabled = 'disabled'; + } else { + input.disabled = false; + } + }, 400); + }); + isLoaded = true; + }); + + btnIframe.style.cssText = btnStyle; + containerBtn.appendChild(btnIframe); + } + + return { + bindEvents:{ + 'ready': function() { + //设置loading的样式 + utils.cssRule('loading', + '.loadingclass{display:inline-block;cursor:default;background: url(\'' + + this.options.themePath + + this.options.theme +'/images/loading.gif\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;}\n' + + '.loaderrorclass{display:inline-block;cursor:default;background: url(\'' + + this.options.themePath + + this.options.theme +'/images/loaderror.png\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;' + + '}', + this.document); + }, + /* 初始化简单上传按钮 */ + 'simpleuploadbtnready': function(type, container) { + containerBtn = container; + me.afterConfigReady(initUploadBtn); + } + }, + outputRule: function(root){ + utils.each(root.getNodesByTagName('img'),function(n){ + if (/\b(loaderrorclass)|(bloaderrorclass)\b/.test(n.getAttr('class'))) { + n.parentNode.removeChild(n); + } + }); + }, + commands: { + 'simpleupload': { + queryCommandState: function () { + return isLoaded ? 0:-1; + } + } + } + } +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/snapscreen.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/snapscreen.js new file mode 100644 index 000000000..150644188 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/snapscreen.js @@ -0,0 +1,101 @@ +/** + * 截屏插件,为UEditor提供插入支持 + * @file + * @since 1.4.2 + */ +UE.plugin.register('snapscreen', function (){ + + var me = this; + var snapplugin; + + function getLocation(url){ + var search, + a = document.createElement('a'), + params = utils.serializeParam(me.queryCommandValue('serverparam')) || ''; + + a.href = url; + if (browser.ie) { + a.href = a.href; + } + + + search = a.search; + if (params) { + search = search + (search.indexOf('?') == -1 ? '?':'&')+ params; + search = search.replace(/[&]+/ig, '&'); + } + return { + 'port': a.port, + 'hostname': a.hostname, + 'path': a.pathname + search || + a.hash + } + } + + return { + commands:{ + /** + * 字体背景颜色 + * @command snapscreen + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand('snapscreen'); + * ``` + */ + 'snapscreen':{ + execCommand:function (cmd) { + var url, local, res; + var lang = me.getLang("snapScreen_plugin"); + + if(!snapplugin){ + var container = me.container; + var doc = me.container.ownerDocument || me.container.document; + snapplugin = doc.createElement("object"); + try{snapplugin.type = "application/x-pluginbaidusnap";}catch(e){ + return; + } + snapplugin.style.cssText = "position:absolute;left:-9999px;width:0;height:0;"; + snapplugin.setAttribute("width","0"); + snapplugin.setAttribute("height","0"); + container.appendChild(snapplugin); + } + + function onSuccess(rs){ + try{ + rs = eval("("+ rs +")"); + if(rs.state == 'SUCCESS'){ + var opt = me.options; + me.execCommand('insertimage', { + src: opt.snapscreenUrlPrefix + rs.url, + _src: opt.snapscreenUrlPrefix + rs.url, + alt: rs.title || '', + floatStyle: opt.snapscreenImgAlign + }); + } else { + alert(rs.state); + } + }catch(e){ + alert(lang.callBackErrorMsg); + } + } + url = me.getActionUrl(me.getOpt('snapscreenActionName')); + local = getLocation(url); + setTimeout(function () { + try{ + res =snapplugin.saveSnapshot(local.hostname, local.path, local.port); + }catch(e){ + me.ui._dialogs['snapscreenDialog'].open(); + return; + } + + onSuccess(res); + }, 50); + }, + queryCommandState: function(){ + return (navigator.userAgent.indexOf("Windows",0) != -1) ? 0:-1; + } + } + } + } +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/source.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/source.js new file mode 100644 index 000000000..8503af617 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/source.js @@ -0,0 +1,300 @@ +/** + * 源码编辑插件 + * @file + * @since 1.2.6.1 + */ + +(function (){ + var sourceEditors = { + textarea: function (editor, holder){ + var textarea = holder.ownerDocument.createElement('textarea'); + textarea.style.cssText = 'position:absolute;resize:none;width:100%;height:100%;border:0;padding:0;margin:0;overflow-y:auto;'; + // todo: IE下只有onresize属性可用... 很纠结 + if (browser.ie && browser.version < 8) { + textarea.style.width = holder.offsetWidth + 'px'; + textarea.style.height = holder.offsetHeight + 'px'; + holder.onresize = function (){ + textarea.style.width = holder.offsetWidth + 'px'; + textarea.style.height = holder.offsetHeight + 'px'; + }; + } + holder.appendChild(textarea); + return { + setContent: function (content){ + textarea.value = content; + }, + getContent: function (){ + return textarea.value; + }, + select: function (){ + var range; + if (browser.ie) { + range = textarea.createTextRange(); + range.collapse(true); + range.select(); + } else { + //todo: chrome下无法设置焦点 + textarea.setSelectionRange(0, 0); + textarea.focus(); + } + }, + dispose: function (){ + holder.removeChild(textarea); + // todo + holder.onresize = null; + textarea = null; + holder = null; + } + }; + }, + codemirror: function (editor, holder){ + + var codeEditor = window.CodeMirror(holder, { + mode: "text/html", + tabMode: "indent", + lineNumbers: true, + lineWrapping:true + }); + var dom = codeEditor.getWrapperElement(); + dom.style.cssText = 'position:absolute;left:0;top:0;width:100%;height:100%;font-family:consolas,"Courier new",monospace;font-size:13px;'; + codeEditor.getScrollerElement().style.cssText = 'position:absolute;left:0;top:0;width:100%;height:100%;'; + codeEditor.refresh(); + return { + getCodeMirror:function(){ + return codeEditor; + }, + setContent: function (content){ + codeEditor.setValue(content); + }, + getContent: function (){ + return codeEditor.getValue(); + }, + select: function (){ + codeEditor.focus(); + }, + dispose: function (){ + holder.removeChild(dom); + dom = null; + codeEditor = null; + } + }; + } + }; + + UE.plugins['source'] = function (){ + var me = this; + var opt = this.options; + var sourceMode = false; + var sourceEditor; + var orgSetContent; + opt.sourceEditor = browser.ie ? 'textarea' : (opt.sourceEditor || 'codemirror'); + + me.setOpt({ + sourceEditorFirst:false + }); + function createSourceEditor(holder){ + return sourceEditors[opt.sourceEditor == 'codemirror' && window.CodeMirror ? 'codemirror' : 'textarea'](me, holder); + } + + var bakCssText; + //解决在源码模式下getContent不能得到最新的内容问题 + var oldGetContent, + bakAddress; + + /** + * 切换源码模式和编辑模式 + * @command source + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'source'); + * ``` + */ + + /** + * 查询当前编辑区域的状态是源码模式还是可视化模式 + * @command source + * @method queryCommandState + * @param { String } cmd 命令字符串 + * @return { int } 如果当前是源码编辑模式,返回1,否则返回0 + * @example + * ```javascript + * editor.queryCommandState( 'source' ); + * ``` + */ + + me.commands['source'] = { + execCommand: function (){ + + sourceMode = !sourceMode; + if (sourceMode) { + bakAddress = me.selection.getRange().createAddress(false,true); + me.undoManger && me.undoManger.save(true); + if(browser.gecko){ + me.body.contentEditable = false; + } + + bakCssText = me.iframe.style.cssText; + me.iframe.style.cssText += 'position:absolute;left:-32768px;top:-32768px;'; + + + me.fireEvent('beforegetcontent'); + var root = UE.htmlparser(me.body.innerHTML); + me.filterOutputRule(root); + root.traversal(function (node) { + if (node.type == 'element') { + switch (node.tagName) { + case 'td': + case 'th': + case 'caption': + if(node.children && node.children.length == 1){ + if(node.firstChild().tagName == 'br' ){ + node.removeChild(node.firstChild()) + } + }; + break; + case 'pre': + node.innerText(node.innerText().replace(/ /g,' ')) + + } + } + }); + + me.fireEvent('aftergetcontent'); + + var content = root.toHtml(true); + + sourceEditor = createSourceEditor(me.iframe.parentNode); + + sourceEditor.setContent(content); + + orgSetContent = me.setContent; + + me.setContent = function(html){ + //这里暂时不触发事件,防止报错 + var root = UE.htmlparser(html); + me.filterInputRule(root); + html = root.toHtml(); + sourceEditor.setContent(html); + }; + + setTimeout(function (){ + sourceEditor.select(); + me.addListener('fullscreenchanged', function(){ + try{ + sourceEditor.getCodeMirror().refresh() + }catch(e){} + }); + }); + + //重置getContent,源码模式下取值也能是最新的数据 + oldGetContent = me.getContent; + me.getContent = function (){ + return sourceEditor.getContent() || '

    ' + (browser.ie ? '' : '
    ')+'

    '; + }; + } else { + me.iframe.style.cssText = bakCssText; + var cont = sourceEditor.getContent() || '

    ' + (browser.ie ? '' : '
    ')+'

    '; + //处理掉block节点前后的空格,有可能会误命中,暂时不考虑 + cont = cont.replace(new RegExp('[\\r\\t\\n ]*<\/?(\\w+)\\s*(?:[^>]*)>','g'), function(a,b){ + if(b && !dtd.$inlineWithA[b.toLowerCase()]){ + return a.replace(/(^[\n\r\t ]*)|([\n\r\t ]*$)/g,''); + } + return a.replace(/(^[\n\r\t]*)|([\n\r\t]*$)/g,'') + }); + + me.setContent = orgSetContent; + + me.setContent(cont); + sourceEditor.dispose(); + sourceEditor = null; + //还原getContent方法 + me.getContent = oldGetContent; + var first = me.body.firstChild; + //trace:1106 都删除空了,下边会报错,所以补充一个p占位 + if(!first){ + me.body.innerHTML = '

    '+(browser.ie?'':'
    ')+'

    '; + first = me.body.firstChild; + } + + + //要在ifm为显示时ff才能取到selection,否则报错 + //这里不能比较位置了 + me.undoManger && me.undoManger.save(true); + + if(browser.gecko){ + + var input = document.createElement('input'); + input.style.cssText = 'position:absolute;left:0;top:-32768px'; + + document.body.appendChild(input); + + me.body.contentEditable = false; + setTimeout(function(){ + domUtils.setViewportOffset(input, { left: -32768, top: 0 }); + input.focus(); + setTimeout(function(){ + me.body.contentEditable = true; + me.selection.getRange().moveToAddress(bakAddress).select(true); + domUtils.remove(input); + }); + + }); + }else{ + //ie下有可能报错,比如在代码顶头的情况 + try{ + me.selection.getRange().moveToAddress(bakAddress).select(true); + }catch(e){} + + } + } + this.fireEvent('sourcemodechanged', sourceMode); + }, + queryCommandState: function (){ + return sourceMode|0; + }, + notNeedUndo : 1 + }; + var oldQueryCommandState = me.queryCommandState; + + me.queryCommandState = function (cmdName){ + cmdName = cmdName.toLowerCase(); + if (sourceMode) { + //源码模式下可以开启的命令 + return cmdName in { + 'source' : 1, + 'fullscreen' : 1 + } ? 1 : -1 + } + return oldQueryCommandState.apply(this, arguments); + }; + + if(opt.sourceEditor == "codemirror"){ + + me.addListener("ready",function(){ + utils.loadFile(document,{ + src : opt.codeMirrorJsUrl || opt.UEDITOR_HOME_URL + "third-party/codemirror/codemirror.js", + tag : "script", + type : "text/javascript", + defer : "defer" + },function(){ + if(opt.sourceEditorFirst){ + setTimeout(function(){ + me.execCommand("source"); + },0); + } + }); + utils.loadFile(document,{ + tag : "link", + rel : "stylesheet", + type : "text/css", + href : opt.codeMirrorCssUrl || opt.UEDITOR_HOME_URL + "third-party/codemirror/codemirror.css" + }); + + }); + } + + }; + +})(); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/table.action.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/table.action.js new file mode 100644 index 000000000..7b54cadc9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/table.action.js @@ -0,0 +1,1875 @@ +/** + * Created with JetBrains PhpStorm. + * User: taoqili + * Date: 12-10-12 + * Time: 上午10:05 + * To change this template use File | Settings | File Templates. + */ +UE.plugins['table'] = function () { + var me = this, + tabTimer = null, + //拖动计时器 + tableDragTimer = null, + //双击计时器 + tableResizeTimer = null, + //单元格最小宽度 + cellMinWidth = 5, + isInResizeBuffer = false, + //单元格边框大小 + cellBorderWidth = 5, + //鼠标偏移距离 + offsetOfTableCell = 10, + //记录在有限时间内的点击状态, 共有3个取值, 0, 1, 2。 0代表未初始化, 1代表单击了1次,2代表2次 + singleClickState = 0, + userActionStatus = null, + //双击允许的时间范围 + dblclickTime = 360, + UT = UE.UETable, + getUETable = function (tdOrTable) { + return UT.getUETable(tdOrTable); + }, + getUETableBySelected = function (editor) { + return UT.getUETableBySelected(editor); + }, + getDefaultValue = function (editor, table) { + return UT.getDefaultValue(editor, table); + }, + removeSelectedClass = function (cells) { + return UT.removeSelectedClass(cells); + }; + + function showError(e) { +// throw e; + } + me.ready(function(){ + var me = this; + var orgGetText = me.selection.getText; + me.selection.getText = function(){ + var table = getUETableBySelected(me); + if(table){ + var str = ''; + utils.each(table.selectedTds,function(td){ + str += td[browser.ie?'innerText':'textContent']; + }) + return str; + }else{ + return orgGetText.call(me.selection) + } + + } + }) + + //处理拖动及框选相关方法 + var startTd = null, //鼠标按下时的锚点td + currentTd = null, //当前鼠标经过时的td + onDrag = "", //指示当前拖动状态,其值可为"","h","v" ,分别表示未拖动状态,横向拖动状态,纵向拖动状态,用于鼠标移动过程中的判断 + onBorder = false, //检测鼠标按下时是否处在单元格边缘位置 + dragButton = null, + dragOver = false, + dragLine = null, //模拟的拖动线 + dragTd = null; //发生拖动的目标td + + var mousedown = false, + //todo 判断混乱模式 + needIEHack = true; + + me.setOpt({ + 'maxColNum':20, + 'maxRowNum':100, + 'defaultCols':5, + 'defaultRows':5, + 'tdvalign':'top', + 'cursorpath':me.options.UEDITOR_HOME_URL + "themes/default/images/cursor_", + 'tableDragable':false, + 'classList':["ue-table-interlace-color-single","ue-table-interlace-color-double"] + }); + me.getUETable = getUETable; + var commands = { + 'deletetable':1, + 'inserttable':1, + 'cellvalign':1, + 'insertcaption':1, + 'deletecaption':1, + 'inserttitle':1, + 'deletetitle':1, + "mergeright":1, + "mergedown":1, + "mergecells":1, + "insertrow":1, + "insertrownext":1, + "deleterow":1, + "insertcol":1, + "insertcolnext":1, + "deletecol":1, + "splittocells":1, + "splittorows":1, + "splittocols":1, + "adaptbytext":1, + "adaptbywindow":1, + "adaptbycustomer":1, + "insertparagraph":1, + "insertparagraphbeforetable":1, + "averagedistributecol":1, + "averagedistributerow":1 + }; + me.ready(function () { + utils.cssRule('table', + //选中的td上的样式 + '.selectTdClass{background-color:#edf5fa !important}' + + 'table.noBorderTable td,table.noBorderTable th,table.noBorderTable caption{border:1px dashed #ddd !important}' + + //插入的表格的默认样式 + 'table{margin-bottom:10px;border-collapse:collapse;display:table;}' + + 'td,th{padding: 5px 10px;border: 1px solid #DDD;}' + + 'caption{border:1px dashed #DDD;border-bottom:0;padding:3px;text-align:center;}' + + 'th{border-top:1px solid #BBB;background-color:#F7F7F7;}' + + 'table tr.firstRow th{border-top-width:2px;}' + + '.ue-table-interlace-color-single{ background-color: #fcfcfc; } .ue-table-interlace-color-double{ background-color: #f7faff; }' + + 'td p{margin:0;padding:0;}', me.document); + + var tableCopyList, isFullCol, isFullRow; + //注册del/backspace事件 + me.addListener('keydown', function (cmd, evt) { + var me = this; + var keyCode = evt.keyCode || evt.which; + + if (keyCode == 8) { + + var ut = getUETableBySelected(me); + if (ut && ut.selectedTds.length) { + + if (ut.isFullCol()) { + me.execCommand('deletecol') + } else if (ut.isFullRow()) { + me.execCommand('deleterow') + } else { + me.fireEvent('delcells'); + } + domUtils.preventDefault(evt); + } + + var caption = domUtils.findParentByTagName(me.selection.getStart(), 'caption', true), + range = me.selection.getRange(); + if (range.collapsed && caption && isEmptyBlock(caption)) { + me.fireEvent('saveScene'); + var table = caption.parentNode; + domUtils.remove(caption); + if (table) { + range.setStart(table.rows[0].cells[0], 0).setCursor(false, true); + } + me.fireEvent('saveScene'); + } + + } + + if (keyCode == 46) { + + ut = getUETableBySelected(me); + if (ut) { + me.fireEvent('saveScene'); + for (var i = 0, ci; ci = ut.selectedTds[i++];) { + domUtils.fillNode(me.document, ci) + } + me.fireEvent('saveScene'); + domUtils.preventDefault(evt); + + } + + } + if (keyCode == 13) { + + var rng = me.selection.getRange(), + caption = domUtils.findParentByTagName(rng.startContainer, 'caption', true); + if (caption) { + var table = domUtils.findParentByTagName(caption, 'table'); + if (!rng.collapsed) { + + rng.deleteContents(); + me.fireEvent('saveScene'); + } else { + if (caption) { + rng.setStart(table.rows[0].cells[0], 0).setCursor(false, true); + } + } + domUtils.preventDefault(evt); + return; + } + if (rng.collapsed) { + var table = domUtils.findParentByTagName(rng.startContainer, 'table'); + if (table) { + var cell = table.rows[0].cells[0], + start = domUtils.findParentByTagName(me.selection.getStart(), ['td', 'th'], true), + preNode = table.previousSibling; + if (cell === start && (!preNode || preNode.nodeType == 1 && preNode.tagName == 'TABLE' ) && domUtils.isStartInblock(rng)) { + var first = domUtils.findParent(me.selection.getStart(), function(n){return domUtils.isBlockElm(n)}, true); + if(first && ( /t(h|d)/i.test(first.tagName) || first === start.firstChild )){ + me.execCommand('insertparagraphbeforetable'); + domUtils.preventDefault(evt); + } + + } + } + } + } + + if ((evt.ctrlKey || evt.metaKey) && evt.keyCode == '67') { + tableCopyList = null; + var ut = getUETableBySelected(me); + if (ut) { + var tds = ut.selectedTds; + isFullCol = ut.isFullCol(); + isFullRow = ut.isFullRow(); + tableCopyList = [ + [ut.cloneCell(tds[0],null,true)] + ]; + for (var i = 1, ci; ci = tds[i]; i++) { + if (ci.parentNode !== tds[i - 1].parentNode) { + tableCopyList.push([ut.cloneCell(ci,null,true)]); + } else { + tableCopyList[tableCopyList.length - 1].push(ut.cloneCell(ci,null,true)); + } + + } + } + } + }); + me.addListener("tablehasdeleted",function(){ + toggleDraggableState(this, false, "", null); + if (dragButton)domUtils.remove(dragButton); + }); + + me.addListener('beforepaste', function (cmd, html) { + var me = this; + var rng = me.selection.getRange(); + if (domUtils.findParentByTagName(rng.startContainer, 'caption', true)) { + var div = me.document.createElement("div"); + div.innerHTML = html.html; + //trace:3729 + html.html = div[browser.ie9below ? 'innerText' : 'textContent']; + return; + } + var table = getUETableBySelected(me); + if (tableCopyList) { + me.fireEvent('saveScene'); + var rng = me.selection.getRange(); + var td = domUtils.findParentByTagName(rng.startContainer, ['td', 'th'], true), tmpNode, preNode; + if (td) { + var ut = getUETable(td); + if (isFullRow) { + var rowIndex = ut.getCellInfo(td).rowIndex; + if (td.tagName == 'TH') { + rowIndex++; + } + for (var i = 0, ci; ci = tableCopyList[i++];) { + var tr = ut.insertRow(rowIndex++, "td"); + for (var j = 0, cj; cj = ci[j]; j++) { + var cell = tr.cells[j]; + if (!cell) { + cell = tr.insertCell(j) + } + cell.innerHTML = cj.innerHTML; + cj.getAttribute('width') && cell.setAttribute('width', cj.getAttribute('width')); + cj.getAttribute('vAlign') && cell.setAttribute('vAlign', cj.getAttribute('vAlign')); + cj.getAttribute('align') && cell.setAttribute('align', cj.getAttribute('align')); + cj.style.cssText && (cell.style.cssText = cj.style.cssText) + } + for (var j = 0, cj; cj = tr.cells[j]; j++) { + if (!ci[j]) + break; + cj.innerHTML = ci[j].innerHTML; + ci[j].getAttribute('width') && cj.setAttribute('width', ci[j].getAttribute('width')); + ci[j].getAttribute('vAlign') && cj.setAttribute('vAlign', ci[j].getAttribute('vAlign')); + ci[j].getAttribute('align') && cj.setAttribute('align', ci[j].getAttribute('align')); + ci[j].style.cssText && (cj.style.cssText = ci[j].style.cssText) + } + } + } else { + if (isFullCol) { + cellInfo = ut.getCellInfo(td); + var maxColNum = 0; + for (var j = 0, ci = tableCopyList[0], cj; cj = ci[j++];) { + maxColNum += cj.colSpan || 1; + } + me.__hasEnterExecCommand = true; + for (i = 0; i < maxColNum; i++) { + me.execCommand('insertcol'); + } + me.__hasEnterExecCommand = false; + td = ut.table.rows[0].cells[cellInfo.cellIndex]; + if (td.tagName == 'TH') { + td = ut.table.rows[1].cells[cellInfo.cellIndex]; + } + } + for (var i = 0, ci; ci = tableCopyList[i++];) { + tmpNode = td; + for (var j = 0, cj; cj = ci[j++];) { + if (td) { + td.innerHTML = cj.innerHTML; + //todo 定制处理 + cj.getAttribute('width') && td.setAttribute('width', cj.getAttribute('width')); + cj.getAttribute('vAlign') && td.setAttribute('vAlign', cj.getAttribute('vAlign')); + cj.getAttribute('align') && td.setAttribute('align', cj.getAttribute('align')); + cj.style.cssText && (td.style.cssText = cj.style.cssText); + preNode = td; + td = td.nextSibling; + } else { + var cloneTd = cj.cloneNode(true); + domUtils.removeAttributes(cloneTd, ['class', 'rowSpan', 'colSpan']); + + preNode.parentNode.appendChild(cloneTd) + } + } + td = ut.getNextCell(tmpNode, true, true); + if (!tableCopyList[i]) + break; + if (!td) { + var cellInfo = ut.getCellInfo(tmpNode); + ut.table.insertRow(ut.table.rows.length); + ut.update(); + td = ut.getVSideCell(tmpNode, true); + } + } + } + ut.update(); + } else { + table = me.document.createElement('table'); + for (var i = 0, ci; ci = tableCopyList[i++];) { + var tr = table.insertRow(table.rows.length); + for (var j = 0, cj; cj = ci[j++];) { + cloneTd = UT.cloneCell(cj,null,true); + domUtils.removeAttributes(cloneTd, ['class']); + tr.appendChild(cloneTd) + } + if (j == 2 && cloneTd.rowSpan > 1) { + cloneTd.rowSpan = 1; + } + } + + var defaultValue = getDefaultValue(me), + width = me.body.offsetWidth - + (needIEHack ? parseInt(domUtils.getComputedStyle(me.body, 'margin-left'), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (me.options.offsetWidth || 0); + me.execCommand('insertHTML', '' + table.innerHTML.replace(/>\s*<').replace(/\bth\b/gi, "td") + '
    ') + } + me.fireEvent('contentchange'); + me.fireEvent('saveScene'); + html.html = ''; + return true; + } else { + var div = me.document.createElement("div"), tables; + div.innerHTML = html.html; + tables = div.getElementsByTagName("table"); + if (domUtils.findParentByTagName(me.selection.getStart(), 'table')) { + utils.each(tables, function (t) { + domUtils.remove(t) + }); + if (domUtils.findParentByTagName(me.selection.getStart(), 'caption', true)) { + div.innerHTML = div[browser.ie ? 'innerText' : 'textContent']; + } + } else { + utils.each(tables, function (table) { + removeStyleSize(table, true); + domUtils.removeAttributes(table, ['style', 'border']); + utils.each(domUtils.getElementsByTagName(table, "td"), function (td) { + if (isEmptyBlock(td)) { + domUtils.fillNode(me.document, td); + } + removeStyleSize(td, true); +// domUtils.removeAttributes(td, ['style']) + }); + }); + } + html.html = div.innerHTML; + } + }); + + me.addListener('afterpaste', function () { + utils.each(domUtils.getElementsByTagName(me.body, "table"), function (table) { + if (table.offsetWidth > me.body.offsetWidth) { + var defaultValue = getDefaultValue(me, table); + table.style.width = me.body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(me.body, 'margin-left'), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (me.options.offsetWidth || 0) + 'px' + } + }) + }); + me.addListener('blur', function () { + tableCopyList = null; + }); + var timer; + me.addListener('keydown', function () { + clearTimeout(timer); + timer = setTimeout(function () { + var rng = me.selection.getRange(), + cell = domUtils.findParentByTagName(rng.startContainer, ['th', 'td'], true); + if (cell) { + var table = cell.parentNode.parentNode.parentNode; + if (table.offsetWidth > table.getAttribute("width")) { + cell.style.wordBreak = "break-all"; + } + } + + }, 100); + }); + me.addListener("selectionchange", function () { + toggleDraggableState(me, false, "", null); + }); + + + //内容变化时触发索引更新 + //todo 可否考虑标记检测,如果不涉及表格的变化就不进行索引重建和更新 + me.addListener("contentchange", function () { + var me = this; + //尽可能排除一些不需要更新的状况 + hideDragLine(me); + if (getUETableBySelected(me))return; + var rng = me.selection.getRange(); + var start = rng.startContainer; + start = domUtils.findParentByTagName(start, ['td', 'th'], true); + utils.each(domUtils.getElementsByTagName(me.document, 'table'), function (table) { + if (me.fireEvent("excludetable", table) === true) return; + table.ueTable = new UT(table); + //trace:3742 +// utils.each(domUtils.getElementsByTagName(me.document, 'td'), function (td) { +// +// if (domUtils.isEmptyBlock(td) && td !== start) { +// domUtils.fillNode(me.document, td); +// if (browser.ie && browser.version == 6) { +// td.innerHTML = ' ' +// } +// } +// }); +// utils.each(domUtils.getElementsByTagName(me.document, 'th'), function (th) { +// if (domUtils.isEmptyBlock(th) && th !== start) { +// domUtils.fillNode(me.document, th); +// if (browser.ie && browser.version == 6) { +// th.innerHTML = ' ' +// } +// } +// }); + table.onmouseover = function () { + me.fireEvent('tablemouseover', table); + }; + table.onmousemove = function () { + me.fireEvent('tablemousemove', table); + me.options.tableDragable && toggleDragButton(true, this, me); + utils.defer(function(){ + me.fireEvent('contentchange',50) + },true) + }; + table.onmouseout = function () { + me.fireEvent('tablemouseout', table); + toggleDraggableState(me, false, "", null); + hideDragLine(me); + }; + table.onclick = function (evt) { + evt = me.window.event || evt; + var target = getParentTdOrTh(evt.target || evt.srcElement); + if (!target)return; + var ut = getUETable(target), + table = ut.table, + cellInfo = ut.getCellInfo(target), + cellsRange, + rng = me.selection.getRange(); +// if ("topLeft" == inPosition(table, mouseCoords(evt))) { +// cellsRange = ut.getCellsRange(ut.table.rows[0].cells[0], ut.getLastCell()); +// ut.setSelected(cellsRange); +// return; +// } +// if ("bottomRight" == inPosition(table, mouseCoords(evt))) { +// +// return; +// } + if (inTableSide(table, target, evt, true)) { + var endTdCol = ut.getCell(ut.indexTable[ut.rowsNum - 1][cellInfo.colIndex].rowIndex, ut.indexTable[ut.rowsNum - 1][cellInfo.colIndex].cellIndex); + if (evt.shiftKey && ut.selectedTds.length) { + if (ut.selectedTds[0] !== endTdCol) { + cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdCol); + ut.setSelected(cellsRange); + } else { + rng && rng.selectNodeContents(endTdCol).select(); + } + } else { + if (target !== endTdCol) { + cellsRange = ut.getCellsRange(target, endTdCol); + ut.setSelected(cellsRange); + } else { + rng && rng.selectNodeContents(endTdCol).select(); + } + } + return; + } + if (inTableSide(table, target, evt)) { + var endTdRow = ut.getCell(ut.indexTable[cellInfo.rowIndex][ut.colsNum - 1].rowIndex, ut.indexTable[cellInfo.rowIndex][ut.colsNum - 1].cellIndex); + if (evt.shiftKey && ut.selectedTds.length) { + if (ut.selectedTds[0] !== endTdRow) { + cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdRow); + ut.setSelected(cellsRange); + } else { + rng && rng.selectNodeContents(endTdRow).select(); + } + } else { + if (target !== endTdRow) { + cellsRange = ut.getCellsRange(target, endTdRow); + ut.setSelected(cellsRange); + } else { + rng && rng.selectNodeContents(endTdRow).select(); + } + } + } + }; + }); + + switchBorderColor(me, true); + }); + + domUtils.on(me.document, "mousemove", mouseMoveEvent); + + domUtils.on(me.document, "mouseout", function (evt) { + var target = evt.target || evt.srcElement; + if (target.tagName == "TABLE") { + toggleDraggableState(me, false, "", null); + } + }); + /** + * 表格隔行变色 + */ + me.addListener("interlacetable",function(type,table,classList){ + if(!table) return; + var me = this, + rows = table.rows, + len = rows.length, + getClass = function(list,index,repeat){ + return list[index] ? list[index] : repeat ? list[index % list.length]: ""; + }; + for(var i = 0;i 1 ? currentRowIndex : ua.getCellInfo(cell).rowIndex; + var nextCell = ua.getTabNextCell(cell, currentRowIndex); + if (nextCell) { + if (isEmptyBlock(nextCell)) { + range.setStart(nextCell, 0).setCursor(false, true) + } else { + range.selectNodeContents(nextCell).select() + } + } else { + me.fireEvent('saveScene'); + me.__hasEnterExecCommand = true; + this.execCommand('insertrownext'); + me.__hasEnterExecCommand = false; + range = this.selection.getRange(); + range.setStart(table.rows[table.rows.length - 1].cells[0], 0).setCursor(); + me.fireEvent('saveScene'); + } + } + return true; + } + + }); + browser.ie && me.addListener('selectionchange', function () { + toggleDraggableState(this, false, "", null); + }); + me.addListener("keydown", function (type, evt) { + var me = this; + //处理在表格的最后一个输入tab产生新的表格 + var keyCode = evt.keyCode || evt.which; + if (keyCode == 8 || keyCode == 46) { + return; + } + var notCtrlKey = !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey; + notCtrlKey && removeSelectedClass(domUtils.getElementsByTagName(me.body, "td")); + var ut = getUETableBySelected(me); + if (!ut) return; + notCtrlKey && ut.clearSelected(); + }); + + me.addListener("beforegetcontent", function () { + switchBorderColor(this, false); + browser.ie && utils.each(this.document.getElementsByTagName('caption'), function (ci) { + if (domUtils.isEmptyNode(ci)) { + ci.innerHTML = ' ' + } + }); + }); + me.addListener("aftergetcontent", function () { + switchBorderColor(this, true); + }); + me.addListener("getAllHtml", function () { + removeSelectedClass(me.document.getElementsByTagName("td")); + }); + //修正全屏状态下插入的表格宽度在非全屏状态下撑开编辑器的情况 + me.addListener("fullscreenchanged", function (type, fullscreen) { + if (!fullscreen) { + var ratio = this.body.offsetWidth / document.body.offsetWidth, + tables = domUtils.getElementsByTagName(this.body, "table"); + utils.each(tables, function (table) { + if (table.offsetWidth < me.body.offsetWidth) return false; + var tds = domUtils.getElementsByTagName(table, "td"), + backWidths = []; + utils.each(tds, function (td) { + backWidths.push(td.offsetWidth); + }); + for (var i = 0, td; td = tds[i]; i++) { + td.setAttribute("width", Math.floor(backWidths[i] * ratio)); + } + table.setAttribute("width", Math.floor(getTableWidth(me, needIEHack, getDefaultValue(me)))) + }); + } + }); + + //重写execCommand命令,用于处理框选时的处理 + var oldExecCommand = me.execCommand; + me.execCommand = function (cmd, datatat) { + + var me = this, + args = arguments; + + cmd = cmd.toLowerCase(); + var ut = getUETableBySelected(me), tds, + range = new dom.Range(me.document), + cmdFun = me.commands[cmd] || UE.commands[cmd], + result; + if (!cmdFun) return; + if (ut && !commands[cmd] && !cmdFun.notNeedUndo && !me.__hasEnterExecCommand) { + me.__hasEnterExecCommand = true; + me.fireEvent("beforeexeccommand", cmd); + tds = ut.selectedTds; + var lastState = -2, lastValue = -2, value, state; + for (var i = 0, td; td = tds[i]; i++) { + if (isEmptyBlock(td)) { + range.setStart(td, 0).setCursor(false, true) + } else { + range.selectNode(td).select(true); + } + state = me.queryCommandState(cmd); + value = me.queryCommandValue(cmd); + if (state != -1) { + if (lastState !== state || lastValue !== value) { + me._ignoreContentChange = true; + result = oldExecCommand.apply(me, arguments); + me._ignoreContentChange = false; + + } + lastState = me.queryCommandState(cmd); + lastValue = me.queryCommandValue(cmd); + if (domUtils.isEmptyBlock(td)) { + domUtils.fillNode(me.document, td) + } + } + } + range.setStart(tds[0], 0).shrinkBoundary(true).setCursor(false, true); + me.fireEvent('contentchange'); + me.fireEvent("afterexeccommand", cmd); + me.__hasEnterExecCommand = false; + me._selectionChange(); + } else { + result = oldExecCommand.apply(me, arguments); + } + return result; + }; + + + }); + /** + * 删除obj的宽高style,改成属性宽高 + * @param obj + * @param replaceToProperty + */ + function removeStyleSize(obj, replaceToProperty) { + removeStyle(obj, "width", true); + removeStyle(obj, "height", true); + } + + function removeStyle(obj, styleName, replaceToProperty) { + if (obj.style[styleName]) { + replaceToProperty && obj.setAttribute(styleName, parseInt(obj.style[styleName], 10)); + obj.style[styleName] = ""; + } + } + + function getParentTdOrTh(ele) { + if (ele.tagName == "TD" || ele.tagName == "TH") return ele; + var td; + if (td = domUtils.findParentByTagName(ele, "td", true) || domUtils.findParentByTagName(ele, "th", true)) return td; + return null; + } + + function isEmptyBlock(node) { + var reg = new RegExp(domUtils.fillChar, 'g'); + if (node[browser.ie ? 'innerText' : 'textContent'].replace(/^\s*$/, '').replace(reg, '').length > 0) { + return 0; + } + for (var n in dtd.$isNotEmpty) { + if (node.getElementsByTagName(n).length) { + return 0; + } + } + return 1; + } + + + function mouseCoords(evt) { + if (evt.pageX || evt.pageY) { + return { x:evt.pageX, y:evt.pageY }; + } + return { + x:evt.clientX + me.document.body.scrollLeft - me.document.body.clientLeft, + y:evt.clientY + me.document.body.scrollTop - me.document.body.clientTop + }; + } + + function mouseMoveEvent(evt) { + + if( isEditorDisabled() ) { + return; + } + + try { + + //普通状态下鼠标移动 + var target = getParentTdOrTh(evt.target || evt.srcElement), + pos; + + //区分用户的行为是拖动还是双击 + if( isInResizeBuffer ) { + + me.body.style.webkitUserSelect = 'none'; + + if( Math.abs( userActionStatus.x - evt.clientX ) > offsetOfTableCell || Math.abs( userActionStatus.y - evt.clientY ) > offsetOfTableCell ) { + clearTableDragTimer(); + isInResizeBuffer = false; + singleClickState = 0; + //drag action + tableBorderDrag(evt); + } + } + + //修改单元格大小时的鼠标移动 + if (onDrag && dragTd) { + singleClickState = 0; + me.body.style.webkitUserSelect = 'none'; + me.selection.getNative()[browser.ie9below ? 'empty' : 'removeAllRanges'](); + pos = mouseCoords(evt); + toggleDraggableState(me, true, onDrag, pos, target); + if (onDrag == "h") { + dragLine.style.left = getPermissionX(dragTd, evt) + "px"; + } else if (onDrag == "v") { + dragLine.style.top = getPermissionY(dragTd, evt) + "px"; + } + return; + } + //当鼠标处于table上时,修改移动过程中的光标状态 + if (target) { + //针对使用table作为容器的组件不触发拖拽效果 + if (me.fireEvent('excludetable', target) === true) + return; + pos = mouseCoords(evt); + var state = getRelation(target, pos), + table = domUtils.findParentByTagName(target, "table", true); + + if (inTableSide(table, target, evt, true)) { + if (me.fireEvent("excludetable", table) === true) return; + me.body.style.cursor = "url(" + me.options.cursorpath + "h.png),pointer"; + } else if (inTableSide(table, target, evt)) { + if (me.fireEvent("excludetable", table) === true) return; + me.body.style.cursor = "url(" + me.options.cursorpath + "v.png),pointer"; + } else { + me.body.style.cursor = "text"; + var curCell = target; + if (/\d/.test(state)) { + state = state.replace(/\d/, ''); + target = getUETable(target).getPreviewCell(target, state == "v"); + } + //位于第一行的顶部或者第一列的左边时不可拖动 + toggleDraggableState(me, target ? !!state : false, target ? state : '', pos, target); + + } + } else { + toggleDragButton(false, table, me); + } + + } catch (e) { + showError(e); + } + } + + var dragButtonTimer; + + function toggleDragButton(show, table, editor) { + if (!show) { + if (dragOver)return; + dragButtonTimer = setTimeout(function () { + !dragOver && dragButton && dragButton.parentNode && dragButton.parentNode.removeChild(dragButton); + }, 2000); + } else { + createDragButton(table, editor); + } + } + + function createDragButton(table, editor) { + var pos = domUtils.getXY(table), + doc = table.ownerDocument; + if (dragButton && dragButton.parentNode)return dragButton; + dragButton = doc.createElement("div"); + dragButton.contentEditable = false; + dragButton.innerHTML = ""; + dragButton.style.cssText = "width:15px;height:15px;background-image:url(" + editor.options.UEDITOR_HOME_URL + "dialogs/table/dragicon.png);position: absolute;cursor:move;top:" + (pos.y - 15) + "px;left:" + (pos.x) + "px;"; + domUtils.unSelectable(dragButton); + dragButton.onmouseover = function (evt) { + dragOver = true; + }; + dragButton.onmouseout = function (evt) { + dragOver = false; + }; + domUtils.on(dragButton, 'click', function (type, evt) { + doClick(evt, this); + }); + domUtils.on(dragButton, 'dblclick', function (type, evt) { + doDblClick(evt); + }); + domUtils.on(dragButton, 'dragstart', function (type, evt) { + domUtils.preventDefault(evt); + }); + var timer; + + function doClick(evt, button) { + // 部分浏览器下需要清理 + clearTimeout(timer); + timer = setTimeout(function () { + editor.fireEvent("tableClicked", table, button); + }, 300); + } + + function doDblClick(evt) { + clearTimeout(timer); + var ut = getUETable(table), + start = table.rows[0].cells[0], + end = ut.getLastCell(), + range = ut.getCellsRange(start, end); + editor.selection.getRange().setStart(start, 0).setCursor(false, true); + ut.setSelected(range); + } + + doc.body.appendChild(dragButton); + } + + +// function inPosition(table, pos) { +// var tablePos = domUtils.getXY(table), +// width = table.offsetWidth, +// height = table.offsetHeight; +// if (pos.x - tablePos.x < 5 && pos.y - tablePos.y < 5) { +// return "topLeft"; +// } else if (tablePos.x + width - pos.x < 5 && tablePos.y + height - pos.y < 5) { +// return "bottomRight"; +// } +// } + + function inTableSide(table, cell, evt, top) { + var pos = mouseCoords(evt), + state = getRelation(cell, pos); + + if (top) { + var caption = table.getElementsByTagName("caption")[0], + capHeight = caption ? caption.offsetHeight : 0; + return (state == "v1") && ((pos.y - domUtils.getXY(table).y - capHeight) < 8); + } else { + return (state == "h1") && ((pos.x - domUtils.getXY(table).x) < 8); + } + } + + /** + * 获取拖动时允许的X轴坐标 + * @param dragTd + * @param evt + */ + function getPermissionX(dragTd, evt) { + var ut = getUETable(dragTd); + if (ut) { + var preTd = ut.getSameEndPosCells(dragTd, "x")[0], + nextTd = ut.getSameStartPosXCells(dragTd)[0], + mouseX = mouseCoords(evt).x, + left = (preTd ? domUtils.getXY(preTd).x : domUtils.getXY(ut.table).x) + 20 , + right = nextTd ? domUtils.getXY(nextTd).x + nextTd.offsetWidth - 20 : (me.body.offsetWidth + 5 || parseInt(domUtils.getComputedStyle(me.body, "width"), 10)); + + left += cellMinWidth; + right -= cellMinWidth; + + return mouseX < left ? left : mouseX > right ? right : mouseX; + } + } + + /** + * 获取拖动时允许的Y轴坐标 + */ + function getPermissionY(dragTd, evt) { + try { + var top = domUtils.getXY(dragTd).y, + mousePosY = mouseCoords(evt).y; + return mousePosY < top ? top : mousePosY; + } catch (e) { + showError(e); + } + } + + /** + * 移动状态切换 + */ + function toggleDraggableState(editor, draggable, dir, mousePos, cell) { + try { + editor.body.style.cursor = dir == "h" ? "col-resize" : dir == "v" ? "row-resize" : "text"; + if (browser.ie) { + if (dir && !mousedown && !getUETableBySelected(editor)) { + getDragLine(editor, editor.document); + showDragLineAt(dir, cell); + } else { + hideDragLine(editor) + } + } + onBorder = draggable; + } catch (e) { + showError(e); + } + } + + /** + * 获取与UETable相关的resize line + * @param uetable UETable对象 + */ + function getResizeLineByUETable() { + + var lineId = '_UETableResizeLine', + line = this.document.getElementById( lineId ); + + if( !line ) { + line = this.document.createElement("div"); + line.id = lineId; + line.contnetEditable = false; + line.setAttribute("unselectable", "on"); + + var styles = { + width: 2*cellBorderWidth + 1 + 'px', + position: 'absolute', + 'z-index': 100000, + cursor: 'col-resize', + background: 'red', + display: 'none' + }; + + //切换状态 + line.onmouseout = function(){ + this.style.display = 'none'; + }; + + utils.extend( line.style, styles ); + + this.document.body.appendChild( line ); + + } + + return line; + + } + + /** + * 更新resize-line + */ + function updateResizeLine( cell, uetable ) { + + var line = getResizeLineByUETable.call( this ), + table = uetable.table, + styles = { + top: domUtils.getXY( table ).y + 'px', + left: domUtils.getXY( cell).x + cell.offsetWidth - cellBorderWidth + 'px', + display: 'block', + height: table.offsetHeight + 'px' + }; + + utils.extend( line.style, styles ); + + } + + /** + * 显示resize-line + */ + function showResizeLine( cell ) { + + var uetable = getUETable( cell ); + + updateResizeLine.call( this, cell, uetable ); + + } + + /** + * 获取鼠标与当前单元格的相对位置 + * @param ele + * @param mousePos + */ + function getRelation(ele, mousePos) { + var elePos = domUtils.getXY(ele); + + if( !elePos ) { + return ''; + } + + if (elePos.x + ele.offsetWidth - mousePos.x < cellBorderWidth) { + return "h"; + } + if (mousePos.x - elePos.x < cellBorderWidth) { + return 'h1' + } + if (elePos.y + ele.offsetHeight - mousePos.y < cellBorderWidth) { + return "v"; + } + if (mousePos.y - elePos.y < cellBorderWidth) { + return 'v1' + } + return ''; + } + + function mouseDownEvent(type, evt) { + + if( isEditorDisabled() ) { + return ; + } + + userActionStatus = { + x: evt.clientX, + y: evt.clientY + }; + + //右键菜单单独处理 + if (evt.button == 2) { + var ut = getUETableBySelected(me), + flag = false; + + if (ut) { + var td = getTargetTd(me, evt); + utils.each(ut.selectedTds, function (ti) { + if (ti === td) { + flag = true; + } + }); + if (!flag) { + removeSelectedClass(domUtils.getElementsByTagName(me.body, "th td")); + ut.clearSelected() + } else { + td = ut.selectedTds[0]; + setTimeout(function () { + me.selection.getRange().setStart(td, 0).setCursor(false, true); + }, 0); + + } + } + } else { + tableClickHander( evt ); + } + + } + + //清除表格的计时器 + function clearTableTimer() { + tabTimer && clearTimeout( tabTimer ); + tabTimer = null; + } + + //双击收缩 + function tableDbclickHandler(evt) { + singleClickState = 0; + evt = evt || me.window.event; + var target = getParentTdOrTh(evt.target || evt.srcElement); + if (target) { + var h; + if (h = getRelation(target, mouseCoords(evt))) { + + hideDragLine( me ); + + if (h == 'h1') { + h = 'h'; + if (inTableSide(domUtils.findParentByTagName(target, "table"), target, evt)) { + me.execCommand('adaptbywindow'); + } else { + target = getUETable(target).getPreviewCell(target); + if (target) { + var rng = me.selection.getRange(); + rng.selectNodeContents(target).setCursor(true, true) + } + } + } + if (h == 'h') { + var ut = getUETable(target), + table = ut.table, + cells = getCellsByMoveBorder( target, table, true ); + + cells = extractArray( cells, 'left' ); + + ut.width = ut.offsetWidth; + + var oldWidth = [], + newWidth = []; + + utils.each( cells, function( cell ){ + + oldWidth.push( cell.offsetWidth ); + + } ); + + utils.each( cells, function( cell ){ + + cell.removeAttribute("width"); + + } ); + + window.setTimeout( function(){ + + //是否允许改变 + var changeable = true; + + utils.each( cells, function( cell, index ){ + + var width = cell.offsetWidth; + + if( width > oldWidth[index] ) { + changeable = false; + return false; + } + + newWidth.push( width ); + + } ); + + var change = changeable ? newWidth : oldWidth; + + utils.each( cells, function( cell, index ){ + + cell.width = change[index] - getTabcellSpace(); + + } ); + + + }, 0 ); + +// minWidth -= cellMinWidth; +// +// table.removeAttribute("width"); +// utils.each(cells, function (cell) { +// cell.style.width = ""; +// cell.width -= minWidth; +// }); + + } + } + } + } + + function tableClickHander( evt ) { + + removeSelectedClass(domUtils.getElementsByTagName(me.body, "td th")); + //trace:3113 + //选中单元格,点击table外部,不会清掉table上挂的ueTable,会引起getUETableBySelected方法返回值 + utils.each(me.document.getElementsByTagName('table'), function (t) { + t.ueTable = null; + }); + startTd = getTargetTd(me, evt); + if( !startTd ) return; + var table = domUtils.findParentByTagName(startTd, "table", true); + ut = getUETable(table); + ut && ut.clearSelected(); + + //判断当前鼠标状态 + if (!onBorder) { + me.document.body.style.webkitUserSelect = ''; + mousedown = true; + me.addListener('mouseover', mouseOverEvent); + } else { + //边框上的动作处理 + borderActionHandler( evt ); + } + + + } + + //处理表格边框上的动作, 这里做延时处理,避免两种动作互相影响 + function borderActionHandler( evt ) { + + if ( browser.ie ) { + evt = reconstruct(evt ); + } + + clearTableDragTimer(); + + //是否正在等待resize的缓冲中 + isInResizeBuffer = true; + + tableDragTimer = setTimeout(function(){ + tableBorderDrag( evt ); + }, dblclickTime); + + } + + function extractArray( originArr, key ) { + + var result = [], + tmp = null; + + for( var i = 0, len = originArr.length; i 0 && singleClickState--; + }, dblclickTime ); + + if( singleClickState === 2 ) { + + singleClickState = 0; + tableDbclickHandler(evt); + return; + + } + + } + + if (evt.button == 2)return; + var me = this; + //清除表格上原生跨选问题 + var range = me.selection.getRange(), + start = domUtils.findParentByTagName(range.startContainer, 'table', true), + end = domUtils.findParentByTagName(range.endContainer, 'table', true); + + if (start || end) { + if (start === end) { + start = domUtils.findParentByTagName(range.startContainer, ['td', 'th', 'caption'], true); + end = domUtils.findParentByTagName(range.endContainer, ['td', 'th', 'caption'], true); + if (start !== end) { + me.selection.clearRange() + } + } else { + me.selection.clearRange() + } + } + mousedown = false; + me.document.body.style.webkitUserSelect = ''; + //拖拽状态下的mouseUP + if ( onDrag && dragTd ) { + + me.selection.getNative()[browser.ie9below ? 'empty' : 'removeAllRanges'](); + + singleClickState = 0; + dragLine = me.document.getElementById('ue_tableDragLine'); + + // trace 3973 + if (dragLine) { + var dragTdPos = domUtils.getXY(dragTd), + dragLinePos = domUtils.getXY(dragLine); + + switch (onDrag) { + case "h": + changeColWidth(dragTd, dragLinePos.x - dragTdPos.x); + break; + case "v": + changeRowHeight(dragTd, dragLinePos.y - dragTdPos.y - dragTd.offsetHeight); + break; + default: + } + onDrag = ""; + dragTd = null; + + hideDragLine(me); + me.fireEvent('saveScene'); + return; + } + } + //正常状态下的mouseup + if (!startTd) { + var target = domUtils.findParentByTagName(evt.target || evt.srcElement, "td", true); + if (!target) target = domUtils.findParentByTagName(evt.target || evt.srcElement, "th", true); + if (target && (target.tagName == "TD" || target.tagName == "TH")) { + if (me.fireEvent("excludetable", target) === true) return; + range = new dom.Range(me.document); + range.setStart(target, 0).setCursor(false, true); + } + } else { + var ut = getUETable(startTd), + cell = ut ? ut.selectedTds[0] : null; + if (cell) { + range = new dom.Range(me.document); + if (domUtils.isEmptyBlock(cell)) { + range.setStart(cell, 0).setCursor(false, true); + } else { + range.selectNodeContents(cell).shrinkBoundary().setCursor(false, true); + } + } else { + range = me.selection.getRange().shrinkBoundary(); + if (!range.collapsed) { + var start = domUtils.findParentByTagName(range.startContainer, ['td', 'th'], true), + end = domUtils.findParentByTagName(range.endContainer, ['td', 'th'], true); + //在table里边的不能清除 + if (start && !end || !start && end || start && end && start !== end) { + range.setCursor(false, true); + } + } + } + startTd = null; + me.removeListener('mouseover', mouseOverEvent); + } + me._selectionChange(250, evt); + } + + function mouseOverEvent(type, evt) { + + if( isEditorDisabled() ) { + return; + } + + var me = this, + tar = evt.target || evt.srcElement; + currentTd = domUtils.findParentByTagName(tar, "td", true) || domUtils.findParentByTagName(tar, "th", true); + //需要判断两个TD是否位于同一个表格内 + if (startTd && currentTd && + ((startTd.tagName == "TD" && currentTd.tagName == "TD") || (startTd.tagName == "TH" && currentTd.tagName == "TH")) && + domUtils.findParentByTagName(startTd, 'table') == domUtils.findParentByTagName(currentTd, 'table')) { + var ut = getUETable(currentTd); + if (startTd != currentTd) { + me.document.body.style.webkitUserSelect = 'none'; + me.selection.getNative()[browser.ie9below ? 'empty' : 'removeAllRanges'](); + var range = ut.getCellsRange(startTd, currentTd); + ut.setSelected(range); + } else { + me.document.body.style.webkitUserSelect = ''; + ut.clearSelected(); + } + + } + evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); + } + + function setCellHeight(cell, height, backHeight) { + var lineHight = parseInt(domUtils.getComputedStyle(cell, "line-height"), 10), + tmpHeight = backHeight + height; + height = tmpHeight < lineHight ? lineHight : tmpHeight; + if (cell.style.height) cell.style.height = ""; + cell.rowSpan == 1 ? cell.setAttribute("height", height) : (cell.removeAttribute && cell.removeAttribute("height")); + } + + function getWidth(cell) { + if (!cell)return 0; + return parseInt(domUtils.getComputedStyle(cell, "width"), 10); + } + + function changeColWidth(cell, changeValue) { + + var ut = getUETable(cell); + if (ut) { + + //根据当前移动的边框获取相关的单元格 + var table = ut.table, + cells = getCellsByMoveBorder( cell, table ); + + table.style.width = ""; + table.removeAttribute("width"); + + //修正改变量 + changeValue = correctChangeValue( changeValue, cell, cells ); + + if (cell.nextSibling) { + + var i=0; + + utils.each( cells, function( cellGroup ){ + + cellGroup.left.width = (+cellGroup.left.width)+changeValue; + cellGroup.right && ( cellGroup.right.width = (+cellGroup.right.width)-changeValue ); + + } ); + + } else { + + utils.each( cells, function( cellGroup ){ + cellGroup.left.width -= -changeValue; + } ); + + } + } + + } + + function isEditorDisabled() { + return me.body.contentEditable === "false"; + } + + function changeRowHeight(td, changeValue) { + if (Math.abs(changeValue) < 10) return; + var ut = getUETable(td); + if (ut) { + var cells = ut.getSameEndPosCells(td, "y"), + //备份需要连带变化的td的原始高度,否则后期无法获取正确的值 + backHeight = cells[0] ? cells[0].offsetHeight : 0; + for (var i = 0, cell; cell = cells[i++];) { + setCellHeight(cell, changeValue, backHeight); + } + } + + } + + /** + * 获取调整单元格大小的相关单元格 + * @isContainMergeCell 返回的结果中是否包含发生合并后的单元格 + */ + function getCellsByMoveBorder( cell, table, isContainMergeCell ) { + + if( !table ) { + table = domUtils.findParentByTagName( cell, 'table' ); + } + + if( !table ) { + return null; + } + + //获取到该单元格所在行的序列号 + var index = domUtils.getNodeIndex( cell ), + temp = cell, + rows = table.rows, + colIndex = 0; + + while( temp ) { + //获取到当前单元格在未发生单元格合并时的序列 + if( temp.nodeType === 1 ) { + colIndex += (temp.colSpan || 1); + } + temp = temp.previousSibling; + } + + temp = null; + + //记录想关的单元格 + var borderCells = []; + + utils.each(rows, function( tabRow ){ + + var cells = tabRow.cells, + currIndex = 0; + + utils.each( cells, function( tabCell ){ + + currIndex += (tabCell.colSpan || 1); + + if( currIndex === colIndex ) { + + borderCells.push({ + left: tabCell, + right: tabCell.nextSibling || null + }); + + return false; + + } else if( currIndex > colIndex ) { + + if( isContainMergeCell ) { + borderCells.push({ + left: tabCell + }); + } + + return false; + } + + + } ); + + }); + + return borderCells; + + } + + + /** + * 通过给定的单元格集合获取最小的单元格width + */ + function getMinWidthByTableCells( cells ) { + + var minWidth = Number.MAX_VALUE; + + for( var i = 0, curCell; curCell = cells[ i ] ; i++ ) { + + minWidth = Math.min( minWidth, curCell.width || getTableCellWidth( curCell ) ); + + } + + return minWidth; + + } + + function correctChangeValue( changeValue, relatedCell, cells ) { + + //为单元格的paading预留空间 + changeValue -= getTabcellSpace(); + + if( changeValue < 0 ) { + return 0; + } + + changeValue -= getTableCellWidth( relatedCell ); + + //确定方向 + var direction = changeValue < 0 ? 'left':'right'; + + changeValue = Math.abs(changeValue); + + //只关心非最后一个单元格就可以 + utils.each( cells, function( cellGroup ){ + + var curCell = cellGroup[direction]; + + //为单元格保留最小空间 + if( curCell ) { + changeValue = Math.min( changeValue, getTableCellWidth( curCell )-cellMinWidth ); + } + + + } ); + + + //修正越界 + changeValue = changeValue < 0 ? 0 : changeValue; + + return direction === 'left' ? -changeValue : changeValue; + + } + + function getTableCellWidth( cell ) { + + var width = 0, + //偏移纠正量 + offset = 0, + width = cell.offsetWidth - getTabcellSpace(); + + //最后一个节点纠正一下 + if( !cell.nextSibling ) { + + width -= getTableCellOffset( cell ); + + } + + width = width < 0 ? 0 : width; + + try { + cell.width = width; + } catch(e) { + } + + return width; + + } + + /** + * 获取单元格所在表格的最末单元格的偏移量 + */ + function getTableCellOffset( cell ) { + + tab = domUtils.findParentByTagName( cell, "table", false); + + if( tab.offsetVal === undefined ) { + + var prev = cell.previousSibling; + + if( prev ) { + + //最后一个单元格和前一个单元格的width diff结果 如果恰好为一个border width, 则条件成立 + tab.offsetVal = cell.offsetWidth - prev.offsetWidth === UT.borderWidth ? UT.borderWidth : 0; + + } else { + tab.offsetVal = 0; + } + + } + + return tab.offsetVal; + + } + + function getTabcellSpace() { + + if( UT.tabcellSpace === undefined ) { + + var cell = null, + tab = me.document.createElement("table"), + tbody = me.document.createElement("tbody"), + trow = me.document.createElement("tr"), + tabcell = me.document.createElement("td"), + mirror = null; + + tabcell.style.cssText = 'border: 0;'; + tabcell.width = 1; + + trow.appendChild( tabcell ); + trow.appendChild( mirror = tabcell.cloneNode( false ) ); + + tbody.appendChild( trow ); + + tab.appendChild( tbody ); + + tab.style.cssText = "visibility: hidden;"; + + me.body.appendChild( tab ); + + UT.paddingSpace = tabcell.offsetWidth - 1; + + var tmpTabWidth = tab.offsetWidth; + + tabcell.style.cssText = ''; + mirror.style.cssText = ''; + + UT.borderWidth = ( tab.offsetWidth - tmpTabWidth ) / 3; + + UT.tabcellSpace = UT.paddingSpace + UT.borderWidth; + + me.body.removeChild( tab ); + + } + + getTabcellSpace = function(){ return UT.tabcellSpace; }; + + return UT.tabcellSpace; + + } + + function getDragLine(editor, doc) { + if (mousedown)return; + dragLine = editor.document.createElement("div"); + domUtils.setAttributes(dragLine, { + id:"ue_tableDragLine", + unselectable:'on', + contenteditable:false, + 'onresizestart':'return false', + 'ondragstart':'return false', + 'onselectstart':'return false', + style:"background-color:blue;position:absolute;padding:0;margin:0;background-image:none;border:0px none;opacity:0;filter:alpha(opacity=0)" + }); + editor.body.appendChild(dragLine); + } + + function hideDragLine(editor) { + if (mousedown)return; + var line; + while (line = editor.document.getElementById('ue_tableDragLine')) { + domUtils.remove(line) + } + } + + /** + * 依据state(v|h)在cell位置显示横线 + * @param state + * @param cell + */ + function showDragLineAt(state, cell) { + if (!cell) return; + var table = domUtils.findParentByTagName(cell, "table"), + caption = table.getElementsByTagName('caption'), + width = table.offsetWidth, + height = table.offsetHeight - (caption.length > 0 ? caption[0].offsetHeight : 0), + tablePos = domUtils.getXY(table), + cellPos = domUtils.getXY(cell), css; + switch (state) { + case "h": + css = 'height:' + height + 'px;top:' + (tablePos.y + (caption.length > 0 ? caption[0].offsetHeight : 0)) + 'px;left:' + (cellPos.x + cell.offsetWidth); + dragLine.style.cssText = css + 'px;position: absolute;display:block;background-color:blue;width:1px;border:0; color:blue;opacity:.3;filter:alpha(opacity=30)'; + break; + case "v": + css = 'width:' + width + 'px;left:' + tablePos.x + 'px;top:' + (cellPos.y + cell.offsetHeight ); + //必须加上border:0和color:blue,否则低版ie不支持背景色显示 + dragLine.style.cssText = css + 'px;overflow:hidden;position: absolute;display:block;background-color:blue;height:1px;border:0;color:blue;opacity:.2;filter:alpha(opacity=20)'; + break; + default: + } + } + + /** + * 当表格边框颜色为白色时设置为虚线,true为添加虚线 + * @param editor + * @param flag + */ + function switchBorderColor(editor, flag) { + var tableArr = domUtils.getElementsByTagName(editor.body, "table"), color; + for (var i = 0, node; node = tableArr[i++];) { + var td = domUtils.getElementsByTagName(node, "td"); + if (td[0]) { + if (flag) { + color = (td[0].style.borderColor).replace(/\s/g, ""); + if (/(#ffffff)|(rgb\(255,255,255\))/ig.test(color)) + domUtils.addClass(node, "noBorderTable") + } else { + domUtils.removeClasses(node, "noBorderTable") + } + } + + } + } + + function getTableWidth(editor, needIEHack, defaultValue) { + var body = editor.body; + return body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(body, 'margin-left'), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (editor.options.offsetWidth || 0); + } + + /** + * 获取当前拖动的单元格 + */ + function getTargetTd(editor, evt) { + + var target = domUtils.findParentByTagName(evt.target || evt.srcElement, ["td", "th"], true), + dir = null; + + if( !target ) { + return null; + } + + dir = getRelation( target, mouseCoords( evt ) ); + + //如果有前一个节点, 需要做一个修正, 否则可能会得到一个错误的td + + if( !target ) { + return null; + } + + if( dir === 'h1' && target.previousSibling ) { + + var position = domUtils.getXY( target), + cellWidth = target.offsetWidth; + + if( Math.abs( position.x + cellWidth - evt.clientX ) > cellWidth / 3 ) { + target = target.previousSibling; + } + + } else if( dir === 'v1' && target.parentNode.previousSibling ) { + + var position = domUtils.getXY( target), + cellHeight = target.offsetHeight; + + if( Math.abs( position.y + cellHeight - evt.clientY ) > cellHeight / 3 ) { + target = target.parentNode.previousSibling.firstChild; + } + + } + + + //排除了非td内部以及用于代码高亮部分的td + return target && !(editor.fireEvent("excludetable", target) === true) ? target : null; + } + +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/table.cmds.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/table.cmds.js new file mode 100644 index 000000000..c9f12fab5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/table.cmds.js @@ -0,0 +1,936 @@ +/** + * Created with JetBrains PhpStorm. + * User: taoqili + * Date: 13-2-20 + * Time: 下午6:25 + * To change this template use File | Settings | File Templates. + */ +; +(function () { + var UT = UE.UETable, + getTableItemsByRange = function (editor) { + return UT.getTableItemsByRange(editor); + }, + getUETableBySelected = function (editor) { + return UT.getUETableBySelected(editor) + }, + getDefaultValue = function (editor, table) { + return UT.getDefaultValue(editor, table); + }, + getUETable = function (tdOrTable) { + return UT.getUETable(tdOrTable); + }; + + + UE.commands['inserttable'] = { + queryCommandState: function () { + return getTableItemsByRange(this).table ? -1 : 0; + }, + execCommand: function (cmd, opt) { + function createTable(opt, tdWidth) { + var html = [], + rowsNum = opt.numRows, + colsNum = opt.numCols; + for (var r = 0; r < rowsNum; r++) { + html.push(''); + for (var c = 0; c < colsNum; c++) { + html.push('
  • ' + (browser.ie && browser.version < 11 ? domUtils.fillChar : '
    ') + '
    ' + html.join('') + '
    ' + } + + if (!opt) { + opt = utils.extend({}, { + numCols: this.options.defaultCols, + numRows: this.options.defaultRows, + tdvalign: this.options.tdvalign + }) + } + var me = this; + var range = this.selection.getRange(), + start = range.startContainer, + firstParentBlock = domUtils.findParent(start, function (node) { + return domUtils.isBlockElm(node); + }, true) || me.body; + + var defaultValue = getDefaultValue(me), + tableWidth = firstParentBlock.offsetWidth, + tdWidth = Math.floor(tableWidth / opt.numCols - defaultValue.tdPadding * 2 - defaultValue.tdBorder); + + //todo其他属性 + !opt.tdvalign && (opt.tdvalign = me.options.tdvalign); + me.execCommand("inserthtml", createTable(opt, tdWidth)); + } + }; + + UE.commands['insertparagraphbeforetable'] = { + queryCommandState: function () { + return getTableItemsByRange(this).cell ? 0 : -1; + }, + execCommand: function () { + var table = getTableItemsByRange(this).table; + if (table) { + var p = this.document.createElement("p"); + p.innerHTML = browser.ie ? ' ' : '
    '; + table.parentNode.insertBefore(p, table); + this.selection.getRange().setStart(p, 0).setCursor(); + } + } + }; + + UE.commands['deletetable'] = { + queryCommandState: function () { + var rng = this.selection.getRange(); + return domUtils.findParentByTagName(rng.startContainer, 'table', true) ? 0 : -1; + }, + execCommand: function (cmd, table) { + var rng = this.selection.getRange(); + table = table || domUtils.findParentByTagName(rng.startContainer, 'table', true); + if (table) { + var next = table.nextSibling; + if (!next) { + next = domUtils.createElement(this.document, 'p', { + 'innerHTML': browser.ie ? domUtils.fillChar : '
    ' + }); + table.parentNode.insertBefore(next, table); + } + domUtils.remove(table); + rng = this.selection.getRange(); + if (next.nodeType == 3) { + rng.setStartBefore(next) + } else { + rng.setStart(next, 0) + } + rng.setCursor(false, true) + this.fireEvent("tablehasdeleted") + + } + + } + }; + UE.commands['cellalign'] = { + queryCommandState: function () { + return getSelectedArr(this).length ? 0 : -1 + }, + execCommand: function (cmd, align) { + var selectedTds = getSelectedArr(this); + if (selectedTds.length) { + for (var i = 0, ci; ci = selectedTds[i++];) { + ci.setAttribute('align', align); + } + } + } + }; + UE.commands['cellvalign'] = { + queryCommandState: function () { + return getSelectedArr(this).length ? 0 : -1; + }, + execCommand: function (cmd, valign) { + var selectedTds = getSelectedArr(this); + if (selectedTds.length) { + for (var i = 0, ci; ci = selectedTds[i++];) { + ci.setAttribute('vAlign', valign); + } + } + } + }; + UE.commands['insertcaption'] = { + queryCommandState: function () { + var table = getTableItemsByRange(this).table; + if (table) { + return table.getElementsByTagName('caption').length == 0 ? 1 : -1; + } + return -1; + }, + execCommand: function () { + var table = getTableItemsByRange(this).table; + if (table) { + var caption = this.document.createElement('caption'); + caption.innerHTML = browser.ie ? domUtils.fillChar : '
    '; + table.insertBefore(caption, table.firstChild); + var range = this.selection.getRange(); + range.setStart(caption, 0).setCursor(); + } + + } + }; + UE.commands['deletecaption'] = { + queryCommandState: function () { + var rng = this.selection.getRange(), + table = domUtils.findParentByTagName(rng.startContainer, 'table'); + if (table) { + return table.getElementsByTagName('caption').length == 0 ? -1 : 1; + } + return -1; + }, + execCommand: function () { + var rng = this.selection.getRange(), + table = domUtils.findParentByTagName(rng.startContainer, 'table'); + if (table) { + domUtils.remove(table.getElementsByTagName('caption')[0]); + var range = this.selection.getRange(); + range.setStart(table.rows[0].cells[0], 0).setCursor(); + } + + } + }; + UE.commands['inserttitle'] = { + queryCommandState: function () { + var table = getTableItemsByRange(this).table; + if (table) { + var firstRow = table.rows[0]; + return firstRow.cells[firstRow.cells.length-1].tagName.toLowerCase() != 'th' ? 0 : -1 + } + return -1; + }, + execCommand: function () { + var table = getTableItemsByRange(this).table; + if (table) { + getUETable(table).insertRow(0, 'th'); + } + var th = table.getElementsByTagName('th')[0]; + this.selection.getRange().setStart(th, 0).setCursor(false, true); + } + }; + UE.commands['deletetitle'] = { + queryCommandState: function () { + var table = getTableItemsByRange(this).table; + if (table) { + var firstRow = table.rows[0]; + return firstRow.cells[firstRow.cells.length-1].tagName.toLowerCase() == 'th' ? 0 : -1 + } + return -1; + }, + execCommand: function () { + var table = getTableItemsByRange(this).table; + if (table) { + domUtils.remove(table.rows[0]) + } + var td = table.getElementsByTagName('td')[0]; + this.selection.getRange().setStart(td, 0).setCursor(false, true); + } + }; + UE.commands['inserttitlecol'] = { + queryCommandState: function () { + var table = getTableItemsByRange(this).table; + if (table) { + var lastRow = table.rows[table.rows.length-1]; + return lastRow.getElementsByTagName('th').length ? -1 : 0; + } + return -1; + }, + execCommand: function (cmd) { + var table = getTableItemsByRange(this).table; + if (table) { + getUETable(table).insertCol(0, 'th'); + } + resetTdWidth(table, this); + var th = table.getElementsByTagName('th')[0]; + this.selection.getRange().setStart(th, 0).setCursor(false, true); + } + }; + UE.commands['deletetitlecol'] = { + queryCommandState: function () { + var table = getTableItemsByRange(this).table; + if (table) { + var lastRow = table.rows[table.rows.length-1]; + return lastRow.getElementsByTagName('th').length ? 0 : -1; + } + return -1; + }, + execCommand: function () { + var table = getTableItemsByRange(this).table; + if (table) { + for(var i = 0; i< table.rows.length; i++ ){ + domUtils.remove(table.rows[i].children[0]) + } + } + resetTdWidth(table, this); + var td = table.getElementsByTagName('td')[0]; + this.selection.getRange().setStart(td, 0).setCursor(false, true); + } + }; + + UE.commands["mergeright"] = { + queryCommandState: function (cmd) { + var tableItems = getTableItemsByRange(this), + table = tableItems.table, + cell = tableItems.cell; + + if (!table || !cell) return -1; + var ut = getUETable(table); + if (ut.selectedTds.length) return -1; + + var cellInfo = ut.getCellInfo(cell), + rightColIndex = cellInfo.colIndex + cellInfo.colSpan; + if (rightColIndex >= ut.colsNum) return -1; // 如果处于最右边则不能向右合并 + + var rightCellInfo = ut.indexTable[cellInfo.rowIndex][rightColIndex], + rightCell = table.rows[rightCellInfo.rowIndex].cells[rightCellInfo.cellIndex]; + if (!rightCell || cell.tagName != rightCell.tagName) return -1; // TH和TD不能相互合并 + + // 当且仅当两个Cell的开始列号和结束列号一致时能进行合并 + return (rightCellInfo.rowIndex == cellInfo.rowIndex && rightCellInfo.rowSpan == cellInfo.rowSpan) ? 0 : -1; + }, + execCommand: function (cmd) { + var rng = this.selection.getRange(), + bk = rng.createBookmark(true); + var cell = getTableItemsByRange(this).cell, + ut = getUETable(cell); + ut.mergeRight(cell); + rng.moveToBookmark(bk).select(); + } + }; + UE.commands["mergedown"] = { + queryCommandState: function (cmd) { + var tableItems = getTableItemsByRange(this), + table = tableItems.table, + cell = tableItems.cell; + + if (!table || !cell) return -1; + var ut = getUETable(table); + if (ut.selectedTds.length)return -1; + + var cellInfo = ut.getCellInfo(cell), + downRowIndex = cellInfo.rowIndex + cellInfo.rowSpan; + if (downRowIndex >= ut.rowsNum) return -1; // 如果处于最下边则不能向下合并 + + var downCellInfo = ut.indexTable[downRowIndex][cellInfo.colIndex], + downCell = table.rows[downCellInfo.rowIndex].cells[downCellInfo.cellIndex]; + if (!downCell || cell.tagName != downCell.tagName) return -1; // TH和TD不能相互合并 + + // 当且仅当两个Cell的开始列号和结束列号一致时能进行合并 + return (downCellInfo.colIndex == cellInfo.colIndex && downCellInfo.colSpan == cellInfo.colSpan) ? 0 : -1; + }, + execCommand: function () { + var rng = this.selection.getRange(), + bk = rng.createBookmark(true); + var cell = getTableItemsByRange(this).cell, + ut = getUETable(cell); + ut.mergeDown(cell); + rng.moveToBookmark(bk).select(); + } + }; + UE.commands["mergecells"] = { + queryCommandState: function () { + return getUETableBySelected(this) ? 0 : -1; + }, + execCommand: function () { + var ut = getUETableBySelected(this); + if (ut && ut.selectedTds.length) { + var cell = ut.selectedTds[0]; + ut.mergeRange(); + var rng = this.selection.getRange(); + if (domUtils.isEmptyBlock(cell)) { + rng.setStart(cell, 0).collapse(true) + } else { + rng.selectNodeContents(cell) + } + rng.select(); + } + + + } + }; + UE.commands["insertrow"] = { + queryCommandState: function () { + var tableItems = getTableItemsByRange(this), + cell = tableItems.cell; + return cell && (cell.tagName == "TD" || (cell.tagName == 'TH' && tableItems.tr !== tableItems.table.rows[0])) && + getUETable(tableItems.table).rowsNum < this.options.maxRowNum ? 0 : -1; + }, + execCommand: function () { + var rng = this.selection.getRange(), + bk = rng.createBookmark(true); + var tableItems = getTableItemsByRange(this), + cell = tableItems.cell, + table = tableItems.table, + ut = getUETable(table), + cellInfo = ut.getCellInfo(cell); + //ut.insertRow(!ut.selectedTds.length ? cellInfo.rowIndex:ut.cellsRange.beginRowIndex,''); + if (!ut.selectedTds.length) { + ut.insertRow(cellInfo.rowIndex, cell); + } else { + var range = ut.cellsRange; + for (var i = 0, len = range.endRowIndex - range.beginRowIndex + 1; i < len; i++) { + ut.insertRow(range.beginRowIndex, cell); + } + } + rng.moveToBookmark(bk).select(); + if (table.getAttribute("interlaced") === "enabled")this.fireEvent("interlacetable", table); + } + }; + //后插入行 + UE.commands["insertrownext"] = { + queryCommandState: function () { + var tableItems = getTableItemsByRange(this), + cell = tableItems.cell; + return cell && (cell.tagName == "TD") && getUETable(tableItems.table).rowsNum < this.options.maxRowNum ? 0 : -1; + }, + execCommand: function () { + var rng = this.selection.getRange(), + bk = rng.createBookmark(true); + var tableItems = getTableItemsByRange(this), + cell = tableItems.cell, + table = tableItems.table, + ut = getUETable(table), + cellInfo = ut.getCellInfo(cell); + //ut.insertRow(!ut.selectedTds.length? cellInfo.rowIndex + cellInfo.rowSpan : ut.cellsRange.endRowIndex + 1,''); + if (!ut.selectedTds.length) { + ut.insertRow(cellInfo.rowIndex + cellInfo.rowSpan, cell); + } else { + var range = ut.cellsRange; + for (var i = 0, len = range.endRowIndex - range.beginRowIndex + 1; i < len; i++) { + ut.insertRow(range.endRowIndex + 1, cell); + } + } + rng.moveToBookmark(bk).select(); + if (table.getAttribute("interlaced") === "enabled")this.fireEvent("interlacetable", table); + } + }; + UE.commands["deleterow"] = { + queryCommandState: function () { + var tableItems = getTableItemsByRange(this); + return tableItems.cell ? 0 : -1; + }, + execCommand: function () { + var cell = getTableItemsByRange(this).cell, + ut = getUETable(cell), + cellsRange = ut.cellsRange, + cellInfo = ut.getCellInfo(cell), + preCell = ut.getVSideCell(cell), + nextCell = ut.getVSideCell(cell, true), + rng = this.selection.getRange(); + if (utils.isEmptyObject(cellsRange)) { + ut.deleteRow(cellInfo.rowIndex); + } else { + for (var i = cellsRange.beginRowIndex; i < cellsRange.endRowIndex + 1; i++) { + ut.deleteRow(cellsRange.beginRowIndex); + } + } + var table = ut.table; + if (!table.getElementsByTagName('td').length) { + var nextSibling = table.nextSibling; + domUtils.remove(table); + if (nextSibling) { + rng.setStart(nextSibling, 0).setCursor(false, true); + } + } else { + if (cellInfo.rowSpan == 1 || cellInfo.rowSpan == cellsRange.endRowIndex - cellsRange.beginRowIndex + 1) { + if (nextCell || preCell) rng.selectNodeContents(nextCell || preCell).setCursor(false, true); + } else { + var newCell = ut.getCell(cellInfo.rowIndex, ut.indexTable[cellInfo.rowIndex][cellInfo.colIndex].cellIndex); + if (newCell) rng.selectNodeContents(newCell).setCursor(false, true); + } + } + if (table.getAttribute("interlaced") === "enabled")this.fireEvent("interlacetable", table); + } + }; + UE.commands["insertcol"] = { + queryCommandState: function (cmd) { + var tableItems = getTableItemsByRange(this), + cell = tableItems.cell; + return cell && (cell.tagName == "TD" || (cell.tagName == 'TH' && cell !== tableItems.tr.cells[0])) && + getUETable(tableItems.table).colsNum < this.options.maxColNum ? 0 : -1; + }, + execCommand: function (cmd) { + var rng = this.selection.getRange(), + bk = rng.createBookmark(true); + if (this.queryCommandState(cmd) == -1)return; + var cell = getTableItemsByRange(this).cell, + ut = getUETable(cell), + cellInfo = ut.getCellInfo(cell); + + //ut.insertCol(!ut.selectedTds.length ? cellInfo.colIndex:ut.cellsRange.beginColIndex); + if (!ut.selectedTds.length) { + ut.insertCol(cellInfo.colIndex, cell); + } else { + var range = ut.cellsRange; + for (var i = 0, len = range.endColIndex - range.beginColIndex + 1; i < len; i++) { + ut.insertCol(range.beginColIndex, cell); + } + } + rng.moveToBookmark(bk).select(true); + } + }; + UE.commands["insertcolnext"] = { + queryCommandState: function () { + var tableItems = getTableItemsByRange(this), + cell = tableItems.cell; + return cell && getUETable(tableItems.table).colsNum < this.options.maxColNum ? 0 : -1; + }, + execCommand: function () { + var rng = this.selection.getRange(), + bk = rng.createBookmark(true); + var cell = getTableItemsByRange(this).cell, + ut = getUETable(cell), + cellInfo = ut.getCellInfo(cell); + //ut.insertCol(!ut.selectedTds.length ? cellInfo.colIndex + cellInfo.colSpan:ut.cellsRange.endColIndex +1); + if (!ut.selectedTds.length) { + ut.insertCol(cellInfo.colIndex + cellInfo.colSpan, cell); + } else { + var range = ut.cellsRange; + for (var i = 0, len = range.endColIndex - range.beginColIndex + 1; i < len; i++) { + ut.insertCol(range.endColIndex + 1, cell); + } + } + rng.moveToBookmark(bk).select(); + } + }; + + UE.commands["deletecol"] = { + queryCommandState: function () { + var tableItems = getTableItemsByRange(this); + return tableItems.cell ? 0 : -1; + }, + execCommand: function () { + var cell = getTableItemsByRange(this).cell, + ut = getUETable(cell), + range = ut.cellsRange, + cellInfo = ut.getCellInfo(cell), + preCell = ut.getHSideCell(cell), + nextCell = ut.getHSideCell(cell, true); + if (utils.isEmptyObject(range)) { + ut.deleteCol(cellInfo.colIndex); + } else { + for (var i = range.beginColIndex; i < range.endColIndex + 1; i++) { + ut.deleteCol(range.beginColIndex); + } + } + var table = ut.table, + rng = this.selection.getRange(); + + if (!table.getElementsByTagName('td').length) { + var nextSibling = table.nextSibling; + domUtils.remove(table); + if (nextSibling) { + rng.setStart(nextSibling, 0).setCursor(false, true); + } + } else { + if (domUtils.inDoc(cell, this.document)) { + rng.setStart(cell, 0).setCursor(false, true); + } else { + if (nextCell && domUtils.inDoc(nextCell, this.document)) { + rng.selectNodeContents(nextCell).setCursor(false, true); + } else { + if (preCell && domUtils.inDoc(preCell, this.document)) { + rng.selectNodeContents(preCell).setCursor(true, true); + } + } + } + } + } + }; + UE.commands["splittocells"] = { + queryCommandState: function () { + var tableItems = getTableItemsByRange(this), + cell = tableItems.cell; + if (!cell) return -1; + var ut = getUETable(tableItems.table); + if (ut.selectedTds.length > 0) return -1; + return cell && (cell.colSpan > 1 || cell.rowSpan > 1) ? 0 : -1; + }, + execCommand: function () { + var rng = this.selection.getRange(), + bk = rng.createBookmark(true); + var cell = getTableItemsByRange(this).cell, + ut = getUETable(cell); + ut.splitToCells(cell); + rng.moveToBookmark(bk).select(); + } + }; + UE.commands["splittorows"] = { + queryCommandState: function () { + var tableItems = getTableItemsByRange(this), + cell = tableItems.cell; + if (!cell) return -1; + var ut = getUETable(tableItems.table); + if (ut.selectedTds.length > 0) return -1; + return cell && cell.rowSpan > 1 ? 0 : -1; + }, + execCommand: function () { + var rng = this.selection.getRange(), + bk = rng.createBookmark(true); + var cell = getTableItemsByRange(this).cell, + ut = getUETable(cell); + ut.splitToRows(cell); + rng.moveToBookmark(bk).select(); + } + }; + UE.commands["splittocols"] = { + queryCommandState: function () { + var tableItems = getTableItemsByRange(this), + cell = tableItems.cell; + if (!cell) return -1; + var ut = getUETable(tableItems.table); + if (ut.selectedTds.length > 0) return -1; + return cell && cell.colSpan > 1 ? 0 : -1; + }, + execCommand: function () { + var rng = this.selection.getRange(), + bk = rng.createBookmark(true); + var cell = getTableItemsByRange(this).cell, + ut = getUETable(cell); + ut.splitToCols(cell); + rng.moveToBookmark(bk).select(); + + } + }; + + UE.commands["adaptbytext"] = + UE.commands["adaptbywindow"] = { + queryCommandState: function () { + return getTableItemsByRange(this).table ? 0 : -1 + }, + execCommand: function (cmd) { + var tableItems = getTableItemsByRange(this), + table = tableItems.table; + if (table) { + if (cmd == 'adaptbywindow') { + resetTdWidth(table, this); + } else { + var cells = domUtils.getElementsByTagName(table, "td th"); + utils.each(cells, function (cell) { + cell.removeAttribute("width"); + }); + table.removeAttribute("width"); + } + } + } + }; + + //平均分配各列 + UE.commands['averagedistributecol'] = { + queryCommandState: function () { + var ut = getUETableBySelected(this); + if (!ut) return -1; + return ut.isFullRow() || ut.isFullCol() ? 0 : -1; + }, + execCommand: function (cmd) { + var me = this, + ut = getUETableBySelected(me); + + function getAverageWidth() { + var tb = ut.table, + averageWidth, sumWidth = 0, colsNum = 0, + tbAttr = getDefaultValue(me, tb); + + if (ut.isFullRow()) { + sumWidth = tb.offsetWidth; + colsNum = ut.colsNum; + } else { + var begin = ut.cellsRange.beginColIndex, + end = ut.cellsRange.endColIndex, + node; + for (var i = begin; i <= end;) { + node = ut.selectedTds[i]; + sumWidth += node.offsetWidth; + i += node.colSpan; + colsNum += 1; + } + } + averageWidth = Math.ceil(sumWidth / colsNum) - tbAttr.tdBorder * 2 - tbAttr.tdPadding * 2; + return averageWidth; + } + + function setAverageWidth(averageWidth) { + utils.each(domUtils.getElementsByTagName(ut.table, "th"), function (node) { + node.setAttribute("width", ""); + }); + var cells = ut.isFullRow() ? domUtils.getElementsByTagName(ut.table, "td") : ut.selectedTds; + + utils.each(cells, function (node) { + if (node.colSpan == 1) { + node.setAttribute("width", averageWidth); + } + }); + } + + if (ut && ut.selectedTds.length) { + setAverageWidth(getAverageWidth()); + } + } + }; + //平均分配各行 + UE.commands['averagedistributerow'] = { + queryCommandState: function () { + var ut = getUETableBySelected(this); + if (!ut) return -1; + if (ut.selectedTds && /th/ig.test(ut.selectedTds[0].tagName)) return -1; + return ut.isFullRow() || ut.isFullCol() ? 0 : -1; + }, + execCommand: function (cmd) { + var me = this, + ut = getUETableBySelected(me); + + function getAverageHeight() { + var averageHeight, rowNum, sumHeight = 0, + tb = ut.table, + tbAttr = getDefaultValue(me, tb), + tdpadding = parseInt(domUtils.getComputedStyle(tb.getElementsByTagName('td')[0], "padding-top")); + + if (ut.isFullCol()) { + var captionArr = domUtils.getElementsByTagName(tb, "caption"), + thArr = domUtils.getElementsByTagName(tb, "th"), + captionHeight, thHeight; + + if (captionArr.length > 0) { + captionHeight = captionArr[0].offsetHeight; + } + if (thArr.length > 0) { + thHeight = thArr[0].offsetHeight; + } + + sumHeight = tb.offsetHeight - (captionHeight || 0) - (thHeight || 0); + rowNum = thArr.length == 0 ? ut.rowsNum : (ut.rowsNum - 1); + } else { + var begin = ut.cellsRange.beginRowIndex, + end = ut.cellsRange.endRowIndex, + count = 0, + trs = domUtils.getElementsByTagName(tb, "tr"); + for (var i = begin; i <= end; i++) { + sumHeight += trs[i].offsetHeight; + count += 1; + } + rowNum = count; + } + //ie8下是混杂模式 + if (browser.ie && browser.version < 9) { + averageHeight = Math.ceil(sumHeight / rowNum); + } else { + averageHeight = Math.ceil(sumHeight / rowNum) - tbAttr.tdBorder * 2 - tdpadding * 2; + } + return averageHeight; + } + + function setAverageHeight(averageHeight) { + var cells = ut.isFullCol() ? domUtils.getElementsByTagName(ut.table, "td") : ut.selectedTds; + utils.each(cells, function (node) { + if (node.rowSpan == 1) { + node.setAttribute("height", averageHeight); + } + }); + } + + if (ut && ut.selectedTds.length) { + setAverageHeight(getAverageHeight()); + } + } + }; + + //单元格对齐方式 + UE.commands['cellalignment'] = { + queryCommandState: function () { + return getTableItemsByRange(this).table ? 0 : -1 + }, + execCommand: function (cmd, data) { + var me = this, + ut = getUETableBySelected(me); + + if (!ut) { + var start = me.selection.getStart(), + cell = start && domUtils.findParentByTagName(start, ["td", "th", "caption"], true); + if (!/caption/ig.test(cell.tagName)) { + domUtils.setAttributes(cell, data); + } else { + cell.style.textAlign = data.align; + cell.style.verticalAlign = data.vAlign; + } + me.selection.getRange().setCursor(true); + } else { + utils.each(ut.selectedTds, function (cell) { + domUtils.setAttributes(cell, data); + }); + } + }, + /** + * 查询当前点击的单元格的对齐状态, 如果当前已经选择了多个单元格, 则会返回所有单元格经过统一协调过后的状态 + * @see UE.UETable.getTableCellAlignState + */ + queryCommandValue: function (cmd) { + + var activeMenuCell = getTableItemsByRange( this).cell; + + if( !activeMenuCell ) { + activeMenuCell = getSelectedArr(this)[0]; + } + + if (!activeMenuCell) { + + return null; + + } else { + + //获取同时选中的其他单元格 + var cells = UE.UETable.getUETable(activeMenuCell).selectedTds; + + !cells.length && ( cells = activeMenuCell ); + + return UE.UETable.getTableCellAlignState(cells); + + } + + } + }; + //表格对齐方式 + UE.commands['tablealignment'] = { + queryCommandState: function () { + if (browser.ie && browser.version < 8) { + return -1; + } + return getTableItemsByRange(this).table ? 0 : -1 + }, + execCommand: function (cmd, value) { + var me = this, + start = me.selection.getStart(), + table = start && domUtils.findParentByTagName(start, ["table"], true); + + if (table) { + table.setAttribute("align",value); + } + } + }; + + //表格属性 + UE.commands['edittable'] = { + queryCommandState: function () { + return getTableItemsByRange(this).table ? 0 : -1 + }, + execCommand: function (cmd, color) { + var rng = this.selection.getRange(), + table = domUtils.findParentByTagName(rng.startContainer, 'table'); + if (table) { + var arr = domUtils.getElementsByTagName(table, "td").concat( + domUtils.getElementsByTagName(table, "th"), + domUtils.getElementsByTagName(table, "caption") + ); + utils.each(arr, function (node) { + node.style.borderColor = color; + }); + } + } + }; + //单元格属性 + UE.commands['edittd'] = { + queryCommandState: function () { + return getTableItemsByRange(this).table ? 0 : -1 + }, + execCommand: function (cmd, bkColor) { + var me = this, + ut = getUETableBySelected(me); + + if (!ut) { + var start = me.selection.getStart(), + cell = start && domUtils.findParentByTagName(start, ["td", "th", "caption"], true); + if (cell) { + cell.style.backgroundColor = bkColor; + } + } else { + utils.each(ut.selectedTds, function (cell) { + cell.style.backgroundColor = bkColor; + }); + } + } + }; + + UE.commands["settablebackground"] = { + queryCommandState: function () { + return getSelectedArr(this).length > 1 ? 0 : -1; + }, + execCommand: function (cmd, value) { + var cells, ut; + cells = getSelectedArr(this); + ut = getUETable(cells[0]); + ut.setBackground(cells, value); + } + }; + + UE.commands["cleartablebackground"] = { + queryCommandState: function () { + var cells = getSelectedArr(this); + if (!cells.length)return -1; + for (var i = 0, cell; cell = cells[i++];) { + if (cell.style.backgroundColor !== "") return 0; + } + return -1; + }, + execCommand: function () { + var cells = getSelectedArr(this), + ut = getUETable(cells[0]); + ut.removeBackground(cells); + } + }; + + UE.commands["interlacetable"] = UE.commands["uninterlacetable"] = { + queryCommandState: function (cmd) { + var table = getTableItemsByRange(this).table; + if (!table) return -1; + var interlaced = table.getAttribute("interlaced"); + if (cmd == "interlacetable") { + //TODO 待定 + //是否需要待定,如果设置,则命令只能单次执行成功,但反射具备toggle效果;否则可以覆盖前次命令,但反射将不存在toggle效果 + return (interlaced === "enabled") ? -1 : 0; + } else { + return (!interlaced || interlaced === "disabled") ? -1 : 0; + } + }, + execCommand: function (cmd, classList) { + var table = getTableItemsByRange(this).table; + if (cmd == "interlacetable") { + table.setAttribute("interlaced", "enabled"); + this.fireEvent("interlacetable", table, classList); + } else { + table.setAttribute("interlaced", "disabled"); + this.fireEvent("uninterlacetable", table); + } + } + }; + UE.commands["setbordervisible"] = { + queryCommandState: function (cmd) { + var table = getTableItemsByRange(this).table; + if (!table) return -1; + return 0; + }, + execCommand: function () { + var table = getTableItemsByRange(this).table; + utils.each(domUtils.getElementsByTagName(table,'td'),function(td){ + td.style.borderWidth = '1px'; + td.style.borderStyle = 'solid'; + }) + } + }; + function resetTdWidth(table, editor) { + var tds = domUtils.getElementsByTagName(table,'td th'); + utils.each(tds, function (td) { + td.removeAttribute("width"); + }); + table.setAttribute('width', getTableWidth(editor, true, getDefaultValue(editor, table))); + var tdsWidths = []; + setTimeout(function () { + utils.each(tds, function (td) { + (td.colSpan == 1) && tdsWidths.push(td.offsetWidth) + }) + utils.each(tds, function (td,i) { + (td.colSpan == 1) && td.setAttribute("width", tdsWidths[i] + ""); + }) + }, 0); + } + + function getTableWidth(editor, needIEHack, defaultValue) { + var body = editor.body; + return body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(body, 'margin-left'), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (editor.options.offsetWidth || 0); + } + + function getSelectedArr(editor) { + var cell = getTableItemsByRange(editor).cell; + if (cell) { + var ut = getUETable(cell); + return ut.selectedTds.length ? ut.selectedTds : [cell]; + } else { + return []; + } + } +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/table.core.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/table.core.js new file mode 100644 index 000000000..ecfa51976 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/table.core.js @@ -0,0 +1,1140 @@ +/** + * Created with JetBrains WebStorm. + * User: taoqili + * Date: 13-1-18 + * Time: 上午11:09 + * To change this template use File | Settings | File Templates. + */ +/** + * UE表格操作类 + * @param table + * @constructor + */ +(function () { + var UETable = UE.UETable = function (table) { + this.table = table; + this.indexTable = []; + this.selectedTds = []; + this.cellsRange = {}; + this.update(table); + }; + + //===以下为静态工具方法=== + UETable.removeSelectedClass = function (cells) { + utils.each(cells, function (cell) { + domUtils.removeClasses(cell, "selectTdClass"); + }) + }; + UETable.addSelectedClass = function (cells) { + utils.each(cells, function (cell) { + domUtils.addClass(cell, "selectTdClass"); + }) + }; + UETable.isEmptyBlock = function (node) { + var reg = new RegExp(domUtils.fillChar, 'g'); + if (node[browser.ie ? 'innerText' : 'textContent'].replace(/^\s*$/, '').replace(reg, '').length > 0) { + return 0; + } + for (var i in dtd.$isNotEmpty) if (dtd.$isNotEmpty.hasOwnProperty(i)) { + if (node.getElementsByTagName(i).length) { + return 0; + } + } + return 1; + }; + UETable.getWidth = function (cell) { + if (!cell)return 0; + return parseInt(domUtils.getComputedStyle(cell, "width"), 10); + }; + + /** + * 获取单元格或者单元格组的“对齐”状态。 如果当前的检测对象是一个单元格组, 只有在满足所有单元格的 水平和竖直 对齐属性都相同的 + * 条件时才会返回其状态值,否则将返回null; 如果当前只检测了一个单元格, 则直接返回当前单元格的对齐状态; + * @param table cell or table cells , 支持单个单元格dom对象 或者 单元格dom对象数组 + * @return { align: 'left' || 'right' || 'center', valign: 'top' || 'middle' || 'bottom' } 或者 null + */ + UETable.getTableCellAlignState = function ( cells ) { + + !utils.isArray( cells ) && ( cells = [cells] ); + + var result = {}, + status = ['align', 'valign'], + tempStatus = null, + isSame = true;//状态是否相同 + + utils.each( cells, function( cellNode ){ + + utils.each( status, function( currentState ){ + + tempStatus = cellNode.getAttribute( currentState ); + + if( !result[ currentState ] && tempStatus ) { + result[ currentState ] = tempStatus; + } else if( !result[ currentState ] || ( tempStatus !== result[ currentState ] ) ) { + isSame = false; + return false; + } + + } ); + + return isSame; + + }); + + return isSame ? result : null; + + }; + + /** + * 根据当前选区获取相关的table信息 + * @return {Object} + */ + UETable.getTableItemsByRange = function (editor) { + var start = editor.selection.getStart(); + + //ff下会选中bookmark + if( start && start.id && start.id.indexOf('_baidu_bookmark_start_') === 0 && start.nextSibling) { + start = start.nextSibling; + } + + //在table或者td边缘有可能存在选中tr的情况 + var cell = start && domUtils.findParentByTagName(start, ["td", "th"], true), + tr = cell && cell.parentNode, + caption = start && domUtils.findParentByTagName(start, 'caption', true), + table = caption ? caption.parentNode : tr && tr.parentNode.parentNode; + + return { + cell:cell, + tr:tr, + table:table, + caption:caption + } + }; + UETable.getUETableBySelected = function (editor) { + var table = UETable.getTableItemsByRange(editor).table; + if (table && table.ueTable && table.ueTable.selectedTds.length) { + return table.ueTable; + } + return null; + }; + + UETable.getDefaultValue = function (editor, table) { + var borderMap = { + thin:'0px', + medium:'1px', + thick:'2px' + }, + tableBorder, tdPadding, tdBorder, tmpValue; + if (!table) { + table = editor.document.createElement('table'); + table.insertRow(0).insertCell(0).innerHTML = 'xxx'; + editor.body.appendChild(table); + var td = table.getElementsByTagName('td')[0]; + tmpValue = domUtils.getComputedStyle(table, 'border-left-width'); + tableBorder = parseInt(borderMap[tmpValue] || tmpValue, 10); + tmpValue = domUtils.getComputedStyle(td, 'padding-left'); + tdPadding = parseInt(borderMap[tmpValue] || tmpValue, 10); + tmpValue = domUtils.getComputedStyle(td, 'border-left-width'); + tdBorder = parseInt(borderMap[tmpValue] || tmpValue, 10); + domUtils.remove(table); + return { + tableBorder:tableBorder, + tdPadding:tdPadding, + tdBorder:tdBorder + }; + } else { + td = table.getElementsByTagName('td')[0]; + tmpValue = domUtils.getComputedStyle(table, 'border-left-width'); + tableBorder = parseInt(borderMap[tmpValue] || tmpValue, 10); + tmpValue = domUtils.getComputedStyle(td, 'padding-left'); + tdPadding = parseInt(borderMap[tmpValue] || tmpValue, 10); + tmpValue = domUtils.getComputedStyle(td, 'border-left-width'); + tdBorder = parseInt(borderMap[tmpValue] || tmpValue, 10); + return { + tableBorder:tableBorder, + tdPadding:tdPadding, + tdBorder:tdBorder + }; + } + }; + /** + * 根据当前点击的td或者table获取索引对象 + * @param tdOrTable + */ + UETable.getUETable = function (tdOrTable) { + var tag = tdOrTable.tagName.toLowerCase(); + tdOrTable = (tag == "td" || tag == "th" || tag == 'caption') ? domUtils.findParentByTagName(tdOrTable, "table", true) : tdOrTable; + if (!tdOrTable.ueTable) { + tdOrTable.ueTable = new UETable(tdOrTable); + } + return tdOrTable.ueTable; + }; + + UETable.cloneCell = function(cell,ignoreMerge,keepPro){ + if (!cell || utils.isString(cell)) { + return this.table.ownerDocument.createElement(cell || 'td'); + } + var flag = domUtils.hasClass(cell, "selectTdClass"); + flag && domUtils.removeClasses(cell, "selectTdClass"); + var tmpCell = cell.cloneNode(true); + if (ignoreMerge) { + tmpCell.rowSpan = tmpCell.colSpan = 1; + } + //去掉宽高 + !keepPro && domUtils.removeAttributes(tmpCell,'width height'); + !keepPro && domUtils.removeAttributes(tmpCell,'style'); + + tmpCell.style.borderLeftStyle = ""; + tmpCell.style.borderTopStyle = ""; + tmpCell.style.borderLeftColor = cell.style.borderRightColor; + tmpCell.style.borderLeftWidth = cell.style.borderRightWidth; + tmpCell.style.borderTopColor = cell.style.borderBottomColor; + tmpCell.style.borderTopWidth = cell.style.borderBottomWidth; + flag && domUtils.addClass(cell, "selectTdClass"); + return tmpCell; + } + + UETable.prototype = { + getMaxRows:function () { + var rows = this.table.rows, maxLen = 1; + for (var i = 0, row; row = rows[i]; i++) { + var currentMax = 1; + for (var j = 0, cj; cj = row.cells[j++];) { + currentMax = Math.max(cj.rowSpan || 1, currentMax); + } + maxLen = Math.max(currentMax + i, maxLen); + } + return maxLen; + }, + /** + * 获取当前表格的最大列数 + */ + getMaxCols:function () { + var rows = this.table.rows, maxLen = 0, cellRows = {}; + for (var i = 0, row; row = rows[i]; i++) { + var cellsNum = 0; + for (var j = 0, cj; cj = row.cells[j++];) { + cellsNum += (cj.colSpan || 1); + if (cj.rowSpan && cj.rowSpan > 1) { + for (var k = 1; k < cj.rowSpan; k++) { + if (!cellRows['row_' + (i + k)]) { + cellRows['row_' + (i + k)] = (cj.colSpan || 1); + } else { + cellRows['row_' + (i + k)]++ + } + } + + } + } + cellsNum += cellRows['row_' + i] || 0; + maxLen = Math.max(cellsNum, maxLen); + } + return maxLen; + }, + getCellColIndex:function (cell) { + + }, + /** + * 获取当前cell旁边的单元格, + * @param cell + * @param right + */ + getHSideCell:function (cell, right) { + try { + var cellInfo = this.getCellInfo(cell), + previewRowIndex, previewColIndex; + var len = this.selectedTds.length, + range = this.cellsRange; + //首行或者首列没有前置单元格 + if ((!right && (!len ? !cellInfo.colIndex : !range.beginColIndex)) || (right && (!len ? (cellInfo.colIndex == (this.colsNum - 1)) : (range.endColIndex == this.colsNum - 1)))) return null; + + previewRowIndex = !len ? cellInfo.rowIndex : range.beginRowIndex; + previewColIndex = !right ? ( !len ? (cellInfo.colIndex < 1 ? 0 : (cellInfo.colIndex - 1)) : range.beginColIndex - 1) + : ( !len ? cellInfo.colIndex + 1 : range.endColIndex + 1); + return this.getCell(this.indexTable[previewRowIndex][previewColIndex].rowIndex, this.indexTable[previewRowIndex][previewColIndex].cellIndex); + } catch (e) { + showError(e); + } + }, + getTabNextCell:function (cell, preRowIndex) { + var cellInfo = this.getCellInfo(cell), + rowIndex = preRowIndex || cellInfo.rowIndex, + colIndex = cellInfo.colIndex + 1 + (cellInfo.colSpan - 1), + nextCell; + try { + nextCell = this.getCell(this.indexTable[rowIndex][colIndex].rowIndex, this.indexTable[rowIndex][colIndex].cellIndex); + } catch (e) { + try { + rowIndex = rowIndex * 1 + 1; + colIndex = 0; + nextCell = this.getCell(this.indexTable[rowIndex][colIndex].rowIndex, this.indexTable[rowIndex][colIndex].cellIndex); + } catch (e) { + } + } + return nextCell; + + }, + /** + * 获取视觉上的后置单元格 + * @param cell + * @param bottom + */ + getVSideCell:function (cell, bottom, ignoreRange) { + try { + var cellInfo = this.getCellInfo(cell), + nextRowIndex, nextColIndex; + var len = this.selectedTds.length && !ignoreRange, + range = this.cellsRange; + //末行或者末列没有后置单元格 + if ((!bottom && (cellInfo.rowIndex == 0)) || (bottom && (!len ? (cellInfo.rowIndex + cellInfo.rowSpan > this.rowsNum - 1) : (range.endRowIndex == this.rowsNum - 1)))) return null; + + nextRowIndex = !bottom ? ( !len ? cellInfo.rowIndex - 1 : range.beginRowIndex - 1) + : ( !len ? (cellInfo.rowIndex + cellInfo.rowSpan) : range.endRowIndex + 1); + nextColIndex = !len ? cellInfo.colIndex : range.beginColIndex; + return this.getCell(this.indexTable[nextRowIndex][nextColIndex].rowIndex, this.indexTable[nextRowIndex][nextColIndex].cellIndex); + } catch (e) { + showError(e); + } + }, + /** + * 获取相同结束位置的单元格,xOrY指代了是获取x轴相同还是y轴相同 + */ + getSameEndPosCells:function (cell, xOrY) { + try { + var flag = (xOrY.toLowerCase() === "x"), + end = domUtils.getXY(cell)[flag ? 'x' : 'y'] + cell["offset" + (flag ? 'Width' : 'Height')], + rows = this.table.rows, + cells = null, returns = []; + for (var i = 0; i < this.rowsNum; i++) { + cells = rows[i].cells; + for (var j = 0, tmpCell; tmpCell = cells[j++];) { + var tmpEnd = domUtils.getXY(tmpCell)[flag ? 'x' : 'y'] + tmpCell["offset" + (flag ? 'Width' : 'Height')]; + //对应行的td已经被上面行rowSpan了 + if (tmpEnd > end && flag) break; + if (cell == tmpCell || end == tmpEnd) { + //只获取单一的单元格 + //todo 仅获取单一单元格在特定情况下会造成returns为空,从而影响后续的拖拽实现,修正这个。需考虑性能 + if (tmpCell[flag ? "colSpan" : "rowSpan"] == 1) { + returns.push(tmpCell); + } + if (flag) break; + } + } + } + return returns; + } catch (e) { + showError(e); + } + }, + setCellContent:function (cell, content) { + cell.innerHTML = content || (browser.ie ? domUtils.fillChar : "
    "); + }, + cloneCell:UETable.cloneCell, + /** + * 获取跟当前单元格的右边竖线为左边的所有未合并单元格 + */ + getSameStartPosXCells:function (cell) { + try { + var start = domUtils.getXY(cell).x + cell.offsetWidth, + rows = this.table.rows, cells , returns = []; + for (var i = 0; i < this.rowsNum; i++) { + cells = rows[i].cells; + for (var j = 0, tmpCell; tmpCell = cells[j++];) { + var tmpStart = domUtils.getXY(tmpCell).x; + if (tmpStart > start) break; + if (tmpStart == start && tmpCell.colSpan == 1) { + returns.push(tmpCell); + break; + } + } + } + return returns; + } catch (e) { + showError(e); + } + }, + /** + * 更新table对应的索引表 + */ + update:function (table) { + this.table = table || this.table; + this.selectedTds = []; + this.cellsRange = {}; + this.indexTable = []; + var rows = this.table.rows, + rowsNum = this.getMaxRows(), + dNum = rowsNum - rows.length, + colsNum = this.getMaxCols(); + while (dNum--) { + this.table.insertRow(rows.length); + } + this.rowsNum = rowsNum; + this.colsNum = colsNum; + for (var i = 0, len = rows.length; i < len; i++) { + this.indexTable[i] = new Array(colsNum); + } + //填充索引表 + for (var rowIndex = 0, row; row = rows[rowIndex]; rowIndex++) { + for (var cellIndex = 0, cell, cells = row.cells; cell = cells[cellIndex]; cellIndex++) { + //修正整行被rowSpan时导致的行数计算错误 + if (cell.rowSpan > rowsNum) { + cell.rowSpan = rowsNum; + } + var colIndex = cellIndex, + rowSpan = cell.rowSpan || 1, + colSpan = cell.colSpan || 1; + //当已经被上一行rowSpan或者被前一列colSpan了,则跳到下一个单元格进行 + while (this.indexTable[rowIndex][colIndex]) colIndex++; + for (var j = 0; j < rowSpan; j++) { + for (var k = 0; k < colSpan; k++) { + this.indexTable[rowIndex + j][colIndex + k] = { + rowIndex:rowIndex, + cellIndex:cellIndex, + colIndex:colIndex, + rowSpan:rowSpan, + colSpan:colSpan + } + } + } + } + } + //修复残缺td + for (j = 0; j < rowsNum; j++) { + for (k = 0; k < colsNum; k++) { + if (this.indexTable[j][k] === undefined) { + row = rows[j]; + cell = row.cells[row.cells.length - 1]; + cell = cell ? cell.cloneNode(true) : this.table.ownerDocument.createElement("td"); + this.setCellContent(cell); + if (cell.colSpan !== 1)cell.colSpan = 1; + if (cell.rowSpan !== 1)cell.rowSpan = 1; + row.appendChild(cell); + this.indexTable[j][k] = { + rowIndex:j, + cellIndex:cell.cellIndex, + colIndex:k, + rowSpan:1, + colSpan:1 + } + } + } + } + //当框选后删除行或者列后撤销,需要重建选区。 + var tds = domUtils.getElementsByTagName(this.table, "td"), + selectTds = []; + utils.each(tds, function (td) { + if (domUtils.hasClass(td, "selectTdClass")) { + selectTds.push(td); + } + }); + if (selectTds.length) { + var start = selectTds[0], + end = selectTds[selectTds.length - 1], + startInfo = this.getCellInfo(start), + endInfo = this.getCellInfo(end); + this.selectedTds = selectTds; + this.cellsRange = { + beginRowIndex:startInfo.rowIndex, + beginColIndex:startInfo.colIndex, + endRowIndex:endInfo.rowIndex + endInfo.rowSpan - 1, + endColIndex:endInfo.colIndex + endInfo.colSpan - 1 + }; + } + //给第一行设置firstRow的样式名称,在排序图标的样式上使用到 + if(!domUtils.hasClass(this.table.rows[0], "firstRow")) { + domUtils.addClass(this.table.rows[0], "firstRow"); + for(var i = 1; i< this.table.rows.length; i++) { + domUtils.removeClasses(this.table.rows[i], "firstRow"); + } + } + }, + /** + * 获取单元格的索引信息 + */ + getCellInfo:function (cell) { + if (!cell) return; + var cellIndex = cell.cellIndex, + rowIndex = cell.parentNode.rowIndex, + rowInfo = this.indexTable[rowIndex], + numCols = this.colsNum; + for (var colIndex = cellIndex; colIndex < numCols; colIndex++) { + var cellInfo = rowInfo[colIndex]; + if (cellInfo.rowIndex === rowIndex && cellInfo.cellIndex === cellIndex) { + return cellInfo; + } + } + }, + /** + * 根据行列号获取单元格 + */ + getCell:function (rowIndex, cellIndex) { + return rowIndex < this.rowsNum && this.table.rows[rowIndex].cells[cellIndex] || null; + }, + /** + * 删除单元格 + */ + deleteCell:function (cell, rowIndex) { + rowIndex = typeof rowIndex == 'number' ? rowIndex : cell.parentNode.rowIndex; + var row = this.table.rows[rowIndex]; + row.deleteCell(cell.cellIndex); + }, + /** + * 根据始末两个单元格获取被框选的所有单元格范围 + */ + getCellsRange:function (cellA, cellB) { + function checkRange(beginRowIndex, beginColIndex, endRowIndex, endColIndex) { + var tmpBeginRowIndex = beginRowIndex, + tmpBeginColIndex = beginColIndex, + tmpEndRowIndex = endRowIndex, + tmpEndColIndex = endColIndex, + cellInfo, colIndex, rowIndex; + // 通过indexTable检查是否存在超出TableRange上边界的情况 + if (beginRowIndex > 0) { + for (colIndex = beginColIndex; colIndex < endColIndex; colIndex++) { + cellInfo = me.indexTable[beginRowIndex][colIndex]; + rowIndex = cellInfo.rowIndex; + if (rowIndex < beginRowIndex) { + tmpBeginRowIndex = Math.min(rowIndex, tmpBeginRowIndex); + } + } + } + // 通过indexTable检查是否存在超出TableRange右边界的情况 + if (endColIndex < me.colsNum) { + for (rowIndex = beginRowIndex; rowIndex < endRowIndex; rowIndex++) { + cellInfo = me.indexTable[rowIndex][endColIndex]; + colIndex = cellInfo.colIndex + cellInfo.colSpan - 1; + if (colIndex > endColIndex) { + tmpEndColIndex = Math.max(colIndex, tmpEndColIndex); + } + } + } + // 检查是否有超出TableRange下边界的情况 + if (endRowIndex < me.rowsNum) { + for (colIndex = beginColIndex; colIndex < endColIndex; colIndex++) { + cellInfo = me.indexTable[endRowIndex][colIndex]; + rowIndex = cellInfo.rowIndex + cellInfo.rowSpan - 1; + if (rowIndex > endRowIndex) { + tmpEndRowIndex = Math.max(rowIndex, tmpEndRowIndex); + } + } + } + // 检查是否有超出TableRange左边界的情况 + if (beginColIndex > 0) { + for (rowIndex = beginRowIndex; rowIndex < endRowIndex; rowIndex++) { + cellInfo = me.indexTable[rowIndex][beginColIndex]; + colIndex = cellInfo.colIndex; + if (colIndex < beginColIndex) { + tmpBeginColIndex = Math.min(cellInfo.colIndex, tmpBeginColIndex); + } + } + } + //递归调用直至所有完成所有框选单元格的扩展 + if (tmpBeginRowIndex != beginRowIndex || tmpBeginColIndex != beginColIndex || tmpEndRowIndex != endRowIndex || tmpEndColIndex != endColIndex) { + return checkRange(tmpBeginRowIndex, tmpBeginColIndex, tmpEndRowIndex, tmpEndColIndex); + } else { + // 不需要扩展TableRange的情况 + return { + beginRowIndex:beginRowIndex, + beginColIndex:beginColIndex, + endRowIndex:endRowIndex, + endColIndex:endColIndex + }; + } + } + + try { + var me = this, + cellAInfo = me.getCellInfo(cellA); + if (cellA === cellB) { + return { + beginRowIndex:cellAInfo.rowIndex, + beginColIndex:cellAInfo.colIndex, + endRowIndex:cellAInfo.rowIndex + cellAInfo.rowSpan - 1, + endColIndex:cellAInfo.colIndex + cellAInfo.colSpan - 1 + }; + } + var cellBInfo = me.getCellInfo(cellB); + // 计算TableRange的四个边 + var beginRowIndex = Math.min(cellAInfo.rowIndex, cellBInfo.rowIndex), + beginColIndex = Math.min(cellAInfo.colIndex, cellBInfo.colIndex), + endRowIndex = Math.max(cellAInfo.rowIndex + cellAInfo.rowSpan - 1, cellBInfo.rowIndex + cellBInfo.rowSpan - 1), + endColIndex = Math.max(cellAInfo.colIndex + cellAInfo.colSpan - 1, cellBInfo.colIndex + cellBInfo.colSpan - 1); + + return checkRange(beginRowIndex, beginColIndex, endRowIndex, endColIndex); + } catch (e) { + //throw e; + } + }, + /** + * 依据cellsRange获取对应的单元格集合 + */ + getCells:function (range) { + //每次获取cells之前必须先清除上次的选择,否则会对后续获取操作造成影响 + this.clearSelected(); + var beginRowIndex = range.beginRowIndex, + beginColIndex = range.beginColIndex, + endRowIndex = range.endRowIndex, + endColIndex = range.endColIndex, + cellInfo, rowIndex, colIndex, tdHash = {}, returnTds = []; + for (var i = beginRowIndex; i <= endRowIndex; i++) { + for (var j = beginColIndex; j <= endColIndex; j++) { + cellInfo = this.indexTable[i][j]; + rowIndex = cellInfo.rowIndex; + colIndex = cellInfo.colIndex; + // 如果Cells里已经包含了此Cell则跳过 + var key = rowIndex + '|' + colIndex; + if (tdHash[key]) continue; + tdHash[key] = 1; + if (rowIndex < i || colIndex < j || rowIndex + cellInfo.rowSpan - 1 > endRowIndex || colIndex + cellInfo.colSpan - 1 > endColIndex) { + return null; + } + returnTds.push(this.getCell(rowIndex, cellInfo.cellIndex)); + } + } + return returnTds; + }, + /** + * 清理已经选中的单元格 + */ + clearSelected:function () { + UETable.removeSelectedClass(this.selectedTds); + this.selectedTds = []; + this.cellsRange = {}; + }, + /** + * 根据range设置已经选中的单元格 + */ + setSelected:function (range) { + var cells = this.getCells(range); + UETable.addSelectedClass(cells); + this.selectedTds = cells; + this.cellsRange = range; + }, + isFullRow:function () { + var range = this.cellsRange; + return (range.endColIndex - range.beginColIndex + 1) == this.colsNum; + }, + isFullCol:function () { + var range = this.cellsRange, + table = this.table, + ths = table.getElementsByTagName("th"), + rows = range.endRowIndex - range.beginRowIndex + 1; + return !ths.length ? rows == this.rowsNum : rows == this.rowsNum || (rows == this.rowsNum - 1); + + }, + /** + * 获取视觉上的前置单元格,默认是左边,top传入时 + * @param cell + * @param top + */ + getNextCell:function (cell, bottom, ignoreRange) { + try { + var cellInfo = this.getCellInfo(cell), + nextRowIndex, nextColIndex; + var len = this.selectedTds.length && !ignoreRange, + range = this.cellsRange; + //末行或者末列没有后置单元格 + if ((!bottom && (cellInfo.rowIndex == 0)) || (bottom && (!len ? (cellInfo.rowIndex + cellInfo.rowSpan > this.rowsNum - 1) : (range.endRowIndex == this.rowsNum - 1)))) return null; + + nextRowIndex = !bottom ? ( !len ? cellInfo.rowIndex - 1 : range.beginRowIndex - 1) + : ( !len ? (cellInfo.rowIndex + cellInfo.rowSpan) : range.endRowIndex + 1); + nextColIndex = !len ? cellInfo.colIndex : range.beginColIndex; + return this.getCell(this.indexTable[nextRowIndex][nextColIndex].rowIndex, this.indexTable[nextRowIndex][nextColIndex].cellIndex); + } catch (e) { + showError(e); + } + }, + getPreviewCell:function (cell, top) { + try { + var cellInfo = this.getCellInfo(cell), + previewRowIndex, previewColIndex; + var len = this.selectedTds.length, + range = this.cellsRange; + //首行或者首列没有前置单元格 + if ((!top && (!len ? !cellInfo.colIndex : !range.beginColIndex)) || (top && (!len ? (cellInfo.rowIndex > (this.colsNum - 1)) : (range.endColIndex == this.colsNum - 1)))) return null; + + previewRowIndex = !top ? ( !len ? cellInfo.rowIndex : range.beginRowIndex ) + : ( !len ? (cellInfo.rowIndex < 1 ? 0 : (cellInfo.rowIndex - 1)) : range.beginRowIndex); + previewColIndex = !top ? ( !len ? (cellInfo.colIndex < 1 ? 0 : (cellInfo.colIndex - 1)) : range.beginColIndex - 1) + : ( !len ? cellInfo.colIndex : range.endColIndex + 1); + return this.getCell(this.indexTable[previewRowIndex][previewColIndex].rowIndex, this.indexTable[previewRowIndex][previewColIndex].cellIndex); + } catch (e) { + showError(e); + } + }, + /** + * 移动单元格中的内容 + */ + moveContent:function (cellTo, cellFrom) { + if (UETable.isEmptyBlock(cellFrom)) return; + if (UETable.isEmptyBlock(cellTo)) { + cellTo.innerHTML = cellFrom.innerHTML; + return; + } + var child = cellTo.lastChild; + if (child.nodeType == 3 || !dtd.$block[child.tagName]) { + cellTo.appendChild(cellTo.ownerDocument.createElement('br')) + } + while (child = cellFrom.firstChild) { + cellTo.appendChild(child); + } + }, + /** + * 向右合并单元格 + */ + mergeRight:function (cell) { + var cellInfo = this.getCellInfo(cell), + rightColIndex = cellInfo.colIndex + cellInfo.colSpan, + rightCellInfo = this.indexTable[cellInfo.rowIndex][rightColIndex], + rightCell = this.getCell(rightCellInfo.rowIndex, rightCellInfo.cellIndex); + //合并 + cell.colSpan = cellInfo.colSpan + rightCellInfo.colSpan; + //被合并的单元格不应存在宽度属性 + cell.removeAttribute("width"); + //移动内容 + this.moveContent(cell, rightCell); + //删掉被合并的Cell + this.deleteCell(rightCell, rightCellInfo.rowIndex); + this.update(); + }, + /** + * 向下合并单元格 + */ + mergeDown:function (cell) { + var cellInfo = this.getCellInfo(cell), + downRowIndex = cellInfo.rowIndex + cellInfo.rowSpan, + downCellInfo = this.indexTable[downRowIndex][cellInfo.colIndex], + downCell = this.getCell(downCellInfo.rowIndex, downCellInfo.cellIndex); + cell.rowSpan = cellInfo.rowSpan + downCellInfo.rowSpan; + cell.removeAttribute("height"); + this.moveContent(cell, downCell); + this.deleteCell(downCell, downCellInfo.rowIndex); + this.update(); + }, + /** + * 合并整个range中的内容 + */ + mergeRange:function () { + //由于合并操作可以在任意时刻进行,所以无法通过鼠标位置等信息实时生成range,只能通过缓存实例中的cellsRange对象来访问 + var range = this.cellsRange, + leftTopCell = this.getCell(range.beginRowIndex, this.indexTable[range.beginRowIndex][range.beginColIndex].cellIndex); + + if (leftTopCell.tagName == "TH" && range.endRowIndex !== range.beginRowIndex) { + var index = this.indexTable, + info = this.getCellInfo(leftTopCell); + leftTopCell = this.getCell(1, index[1][info.colIndex].cellIndex); + range = this.getCellsRange(leftTopCell, this.getCell(index[this.rowsNum - 1][info.colIndex].rowIndex, index[this.rowsNum - 1][info.colIndex].cellIndex)); + } + + // 删除剩余的Cells + var cells = this.getCells(range); + for(var i= 0,ci;ci=cells[i++];){ + if (ci !== leftTopCell) { + this.moveContent(leftTopCell, ci); + this.deleteCell(ci); + } + } + // 修改左上角Cell的rowSpan和colSpan,并调整宽度属性设置 + leftTopCell.rowSpan = range.endRowIndex - range.beginRowIndex + 1; + leftTopCell.rowSpan > 1 && leftTopCell.removeAttribute("height"); + leftTopCell.colSpan = range.endColIndex - range.beginColIndex + 1; + leftTopCell.colSpan > 1 && leftTopCell.removeAttribute("width"); + if (leftTopCell.rowSpan == this.rowsNum && leftTopCell.colSpan != 1) { + leftTopCell.colSpan = 1; + } + + if (leftTopCell.colSpan == this.colsNum && leftTopCell.rowSpan != 1) { + var rowIndex = leftTopCell.parentNode.rowIndex; + //解决IE下的表格操作问题 + if( this.table.deleteRow ) { + for (var i = rowIndex+ 1, curIndex=rowIndex+ 1, len=leftTopCell.rowSpan; i < len; i++) { + this.table.deleteRow(curIndex); + } + } else { + for (var i = 0, len=leftTopCell.rowSpan - 1; i < len; i++) { + var row = this.table.rows[rowIndex + 1]; + row.parentNode.removeChild(row); + } + } + leftTopCell.rowSpan = 1; + } + this.update(); + }, + /** + * 插入一行单元格 + */ + insertRow:function (rowIndex, sourceCell) { + var numCols = this.colsNum, + table = this.table, + row = table.insertRow(rowIndex), cell, + isInsertTitle = typeof sourceCell == 'string' && sourceCell.toUpperCase() == 'TH'; + + function replaceTdToTh(colIndex, cell, tableRow) { + if (colIndex == 0) { + var tr = tableRow.nextSibling || tableRow.previousSibling, + th = tr.cells[colIndex]; + if (th.tagName == 'TH') { + th = cell.ownerDocument.createElement("th"); + th.appendChild(cell.firstChild); + tableRow.insertBefore(th, cell); + domUtils.remove(cell) + } + }else{ + if (cell.tagName == 'TH') { + var td = cell.ownerDocument.createElement("td"); + td.appendChild(cell.firstChild); + tableRow.insertBefore(td, cell); + domUtils.remove(cell) + } + } + } + + //首行直接插入,无需考虑部分单元格被rowspan的情况 + if (rowIndex == 0 || rowIndex == this.rowsNum) { + for (var colIndex = 0; colIndex < numCols; colIndex++) { + cell = this.cloneCell(sourceCell, true); + this.setCellContent(cell); + cell.getAttribute('vAlign') && cell.setAttribute('vAlign', cell.getAttribute('vAlign')); + row.appendChild(cell); + if(!isInsertTitle) replaceTdToTh(colIndex, cell, row); + } + } else { + var infoRow = this.indexTable[rowIndex], + cellIndex = 0; + for (colIndex = 0; colIndex < numCols; colIndex++) { + var cellInfo = infoRow[colIndex]; + //如果存在某个单元格的rowspan穿过待插入行的位置,则修改该单元格的rowspan即可,无需插入单元格 + if (cellInfo.rowIndex < rowIndex) { + cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex); + cell.rowSpan = cellInfo.rowSpan + 1; + } else { + cell = this.cloneCell(sourceCell, true); + this.setCellContent(cell); + row.appendChild(cell); + } + if(!isInsertTitle) replaceTdToTh(colIndex, cell, row); + } + } + //框选时插入不触发contentchange,需要手动更新索引。 + this.update(); + return row; + }, + /** + * 删除一行单元格 + * @param rowIndex + */ + deleteRow:function (rowIndex) { + var row = this.table.rows[rowIndex], + infoRow = this.indexTable[rowIndex], + colsNum = this.colsNum, + count = 0; //处理计数 + for (var colIndex = 0; colIndex < colsNum;) { + var cellInfo = infoRow[colIndex], + cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex); + if (cell.rowSpan > 1) { + if (cellInfo.rowIndex == rowIndex) { + var clone = cell.cloneNode(true); + clone.rowSpan = cell.rowSpan - 1; + clone.innerHTML = ""; + cell.rowSpan = 1; + var nextRowIndex = rowIndex + 1, + nextRow = this.table.rows[nextRowIndex], + insertCellIndex, + preMerged = this.getPreviewMergedCellsNum(nextRowIndex, colIndex) - count; + if (preMerged < colIndex) { + insertCellIndex = colIndex - preMerged - 1; + //nextRow.insertCell(insertCellIndex); + domUtils.insertAfter(nextRow.cells[insertCellIndex], clone); + } else { + if (nextRow.cells.length) nextRow.insertBefore(clone, nextRow.cells[0]) + } + count += 1; + //cell.parentNode.removeChild(cell); + } + } + colIndex += cell.colSpan || 1; + } + var deleteTds = [], cacheMap = {}; + for (colIndex = 0; colIndex < colsNum; colIndex++) { + var tmpRowIndex = infoRow[colIndex].rowIndex, + tmpCellIndex = infoRow[colIndex].cellIndex, + key = tmpRowIndex + "_" + tmpCellIndex; + if (cacheMap[key])continue; + cacheMap[key] = 1; + cell = this.getCell(tmpRowIndex, tmpCellIndex); + deleteTds.push(cell); + } + var mergeTds = []; + utils.each(deleteTds, function (td) { + if (td.rowSpan == 1) { + td.parentNode.removeChild(td); + } else { + mergeTds.push(td); + } + }); + utils.each(mergeTds, function (td) { + td.rowSpan--; + }); + row.parentNode.removeChild(row); + //浏览器方法本身存在bug,采用自定义方法删除 + //this.table.deleteRow(rowIndex); + this.update(); + }, + insertCol:function (colIndex, sourceCell, defaultValue) { + var rowsNum = this.rowsNum, + rowIndex = 0, + tableRow, cell, + backWidth = parseInt((this.table.offsetWidth - (this.colsNum + 1) * 20 - (this.colsNum + 1)) / (this.colsNum + 1), 10), + isInsertTitleCol = typeof sourceCell == 'string' && sourceCell.toUpperCase() == 'TH'; + + function replaceTdToTh(rowIndex, cell, tableRow) { + if (rowIndex == 0) { + var th = cell.nextSibling || cell.previousSibling; + if (th.tagName == 'TH') { + th = cell.ownerDocument.createElement("th"); + th.appendChild(cell.firstChild); + tableRow.insertBefore(th, cell); + domUtils.remove(cell) + } + }else{ + if (cell.tagName == 'TH') { + var td = cell.ownerDocument.createElement("td"); + td.appendChild(cell.firstChild); + tableRow.insertBefore(td, cell); + domUtils.remove(cell) + } + } + } + + var preCell; + if (colIndex == 0 || colIndex == this.colsNum) { + for (; rowIndex < rowsNum; rowIndex++) { + tableRow = this.table.rows[rowIndex]; + preCell = tableRow.cells[colIndex == 0 ? colIndex : tableRow.cells.length]; + cell = this.cloneCell(sourceCell, true); //tableRow.insertCell(colIndex == 0 ? colIndex : tableRow.cells.length); + this.setCellContent(cell); + cell.setAttribute('vAlign', cell.getAttribute('vAlign')); + preCell && cell.setAttribute('width', preCell.getAttribute('width')); + if (!colIndex) { + tableRow.insertBefore(cell, tableRow.cells[0]); + } else { + domUtils.insertAfter(tableRow.cells[tableRow.cells.length - 1], cell); + } + if(!isInsertTitleCol) replaceTdToTh(rowIndex, cell, tableRow) + } + } else { + for (; rowIndex < rowsNum; rowIndex++) { + var cellInfo = this.indexTable[rowIndex][colIndex]; + if (cellInfo.colIndex < colIndex) { + cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex); + cell.colSpan = cellInfo.colSpan + 1; + } else { + tableRow = this.table.rows[rowIndex]; + preCell = tableRow.cells[cellInfo.cellIndex]; + + cell = this.cloneCell(sourceCell, true);//tableRow.insertCell(cellInfo.cellIndex); + this.setCellContent(cell); + cell.setAttribute('vAlign', cell.getAttribute('vAlign')); + preCell && cell.setAttribute('width', preCell.getAttribute('width')); + //防止IE下报错 + preCell ? tableRow.insertBefore(cell, preCell) : tableRow.appendChild(cell); + } + if(!isInsertTitleCol) replaceTdToTh(rowIndex, cell, tableRow); + } + } + //框选时插入不触发contentchange,需要手动更新索引 + this.update(); + this.updateWidth(backWidth, defaultValue || {tdPadding:10, tdBorder:1}); + }, + updateWidth:function (width, defaultValue) { + var table = this.table, + tmpWidth = UETable.getWidth(table) - defaultValue.tdPadding * 2 - defaultValue.tdBorder + width; + if (tmpWidth < table.ownerDocument.body.offsetWidth) { + table.setAttribute("width", tmpWidth); + return; + } + var tds = domUtils.getElementsByTagName(this.table, "td th"); + utils.each(tds, function (td) { + td.setAttribute("width", width); + }) + }, + deleteCol:function (colIndex) { + var indexTable = this.indexTable, + tableRows = this.table.rows, + backTableWidth = this.table.getAttribute("width"), + backTdWidth = 0, + rowsNum = this.rowsNum, + cacheMap = {}; + for (var rowIndex = 0; rowIndex < rowsNum;) { + var infoRow = indexTable[rowIndex], + cellInfo = infoRow[colIndex], + key = cellInfo.rowIndex + '_' + cellInfo.colIndex; + // 跳过已经处理过的Cell + if (cacheMap[key])continue; + cacheMap[key] = 1; + var cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex); + if (!backTdWidth) backTdWidth = cell && parseInt(cell.offsetWidth / cell.colSpan, 10).toFixed(0); + // 如果Cell的colSpan大于1, 就修改colSpan, 否则就删掉这个Cell + if (cell.colSpan > 1) { + cell.colSpan--; + } else { + tableRows[rowIndex].deleteCell(cellInfo.cellIndex); + } + rowIndex += cellInfo.rowSpan || 1; + } + this.table.setAttribute("width", backTableWidth - backTdWidth); + this.update(); + }, + splitToCells:function (cell) { + var me = this, + cells = this.splitToRows(cell); + utils.each(cells, function (cell) { + me.splitToCols(cell); + }) + }, + splitToRows:function (cell) { + var cellInfo = this.getCellInfo(cell), + rowIndex = cellInfo.rowIndex, + colIndex = cellInfo.colIndex, + results = []; + // 修改Cell的rowSpan + cell.rowSpan = 1; + results.push(cell); + // 补齐单元格 + for (var i = rowIndex, endRow = rowIndex + cellInfo.rowSpan; i < endRow; i++) { + if (i == rowIndex)continue; + var tableRow = this.table.rows[i], + tmpCell = tableRow.insertCell(colIndex - this.getPreviewMergedCellsNum(i, colIndex)); + tmpCell.colSpan = cellInfo.colSpan; + this.setCellContent(tmpCell); + tmpCell.setAttribute('vAlign', cell.getAttribute('vAlign')); + tmpCell.setAttribute('align', cell.getAttribute('align')); + if (cell.style.cssText) { + tmpCell.style.cssText = cell.style.cssText; + } + results.push(tmpCell); + } + this.update(); + return results; + }, + getPreviewMergedCellsNum:function (rowIndex, colIndex) { + var indexRow = this.indexTable[rowIndex], + num = 0; + for (var i = 0; i < colIndex;) { + var colSpan = indexRow[i].colSpan, + tmpRowIndex = indexRow[i].rowIndex; + num += (colSpan - (tmpRowIndex == rowIndex ? 1 : 0)); + i += colSpan; + } + return num; + }, + splitToCols:function (cell) { + var backWidth = (cell.offsetWidth / cell.colSpan - 22).toFixed(0), + + cellInfo = this.getCellInfo(cell), + rowIndex = cellInfo.rowIndex, + colIndex = cellInfo.colIndex, + results = []; + // 修改Cell的rowSpan + cell.colSpan = 1; + cell.setAttribute("width", backWidth); + results.push(cell); + // 补齐单元格 + for (var j = colIndex, endCol = colIndex + cellInfo.colSpan; j < endCol; j++) { + if (j == colIndex)continue; + var tableRow = this.table.rows[rowIndex], + tmpCell = tableRow.insertCell(this.indexTable[rowIndex][j].cellIndex + 1); + tmpCell.rowSpan = cellInfo.rowSpan; + this.setCellContent(tmpCell); + tmpCell.setAttribute('vAlign', cell.getAttribute('vAlign')); + tmpCell.setAttribute('align', cell.getAttribute('align')); + tmpCell.setAttribute('width', backWidth); + if (cell.style.cssText) { + tmpCell.style.cssText = cell.style.cssText; + } + //处理th的情况 + if (cell.tagName == 'TH') { + var th = cell.ownerDocument.createElement('th'); + th.appendChild(tmpCell.firstChild); + th.setAttribute('vAlign', cell.getAttribute('vAlign')); + th.rowSpan = tmpCell.rowSpan; + tableRow.insertBefore(th, tmpCell); + domUtils.remove(tmpCell); + } + results.push(tmpCell); + } + this.update(); + return results; + }, + isLastCell:function (cell, rowsNum, colsNum) { + rowsNum = rowsNum || this.rowsNum; + colsNum = colsNum || this.colsNum; + var cellInfo = this.getCellInfo(cell); + return ((cellInfo.rowIndex + cellInfo.rowSpan) == rowsNum) && + ((cellInfo.colIndex + cellInfo.colSpan) == colsNum); + }, + getLastCell:function (cells) { + cells = cells || this.table.getElementsByTagName("td"); + var firstInfo = this.getCellInfo(cells[0]); + var me = this, last = cells[0], + tr = last.parentNode, + cellsNum = 0, cols = 0, rows; + utils.each(cells, function (cell) { + if (cell.parentNode == tr)cols += cell.colSpan || 1; + cellsNum += cell.rowSpan * cell.colSpan || 1; + }); + rows = cellsNum / cols; + utils.each(cells, function (cell) { + if (me.isLastCell(cell, rows, cols)) { + last = cell; + return false; + } + }); + return last; + + }, + selectRow:function (rowIndex) { + var indexRow = this.indexTable[rowIndex], + start = this.getCell(indexRow[0].rowIndex, indexRow[0].cellIndex), + end = this.getCell(indexRow[this.colsNum - 1].rowIndex, indexRow[this.colsNum - 1].cellIndex), + range = this.getCellsRange(start, end); + this.setSelected(range); + }, + selectTable:function () { + var tds = this.table.getElementsByTagName("td"), + range = this.getCellsRange(tds[0], tds[tds.length - 1]); + this.setSelected(range); + }, + setBackground:function (cells, value) { + if (typeof value === "string") { + utils.each(cells, function (cell) { + cell.style.backgroundColor = value; + }) + } else if (typeof value === "object") { + value = utils.extend({ + repeat:true, + colorList:["#ddd", "#fff"] + }, value); + var rowIndex = this.getCellInfo(cells[0]).rowIndex, + count = 0, + colors = value.colorList, + getColor = function (list, index, repeat) { + return list[index] ? list[index] : repeat ? list[index % list.length] : ""; + }; + for (var i = 0, cell; cell = cells[i++];) { + var cellInfo = this.getCellInfo(cell); + cell.style.backgroundColor = getColor(colors, ((rowIndex + count) == cellInfo.rowIndex) ? count : ++count, value.repeat); + } + } + }, + removeBackground:function (cells) { + utils.each(cells, function (cell) { + cell.style.backgroundColor = ""; + }) + } + + + }; + function showError(e) { + } +})(); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/table.sort.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/table.sort.js new file mode 100644 index 000000000..12030043e --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/table.sort.js @@ -0,0 +1,165 @@ +/** + * Created with JetBrains PhpStorm. + * User: Jinqn + * Date: 13-10-12 + * Time: 上午10:20 + * To change this template use File | Settings | File Templates. + */ + +UE.UETable.prototype.sortTable = function (sortByCellIndex, compareFn) { + var table = this.table, + rows = table.rows, + trArray = [], + flag = rows[0].cells[0].tagName === "TH", + lastRowIndex = 0; + if(this.selectedTds.length){ + var range = this.cellsRange, + len = range.endRowIndex + 1; + for (var i = range.beginRowIndex; i < len; i++) { + trArray[i] = rows[i]; + } + trArray.splice(0,range.beginRowIndex); + lastRowIndex = (range.endRowIndex +1) === this.rowsNum ? 0 : range.endRowIndex +1; + }else{ + for (var i = 0,len = rows.length; i < len; i++) { + trArray[i] = rows[i]; + } + } + + var Fn = { + 'reversecurrent': function(td1,td2){ + return 1; + }, + 'orderbyasc': function(td1,td2){ + var value1 = td1.innerText||td1.textContent, + value2 = td2.innerText||td2.textContent; + return value1.localeCompare(value2); + }, + 'reversebyasc': function(td1,td2){ + var value1 = td1.innerHTML, + value2 = td2.innerHTML; + return value2.localeCompare(value1); + }, + 'orderbynum': function(td1,td2){ + var value1 = td1[browser.ie ? 'innerText':'textContent'].match(/\d+/), + value2 = td2[browser.ie ? 'innerText':'textContent'].match(/\d+/); + if(value1) value1 = +value1[0]; + if(value2) value2 = +value2[0]; + return (value1||0) - (value2||0); + }, + 'reversebynum': function(td1,td2){ + var value1 = td1[browser.ie ? 'innerText':'textContent'].match(/\d+/), + value2 = td2[browser.ie ? 'innerText':'textContent'].match(/\d+/); + if(value1) value1 = +value1[0]; + if(value2) value2 = +value2[0]; + return (value2||0) - (value1||0); + } + }; + + //对表格设置排序的标记data-sort-type + table.setAttribute('data-sort-type', compareFn && typeof compareFn === "string" && Fn[compareFn] ? compareFn:''); + + //th不参与排序 + flag && trArray.splice(0, 1); + trArray = utils.sort(trArray,function (tr1, tr2) { + var result; + if (compareFn && typeof compareFn === "function") { + result = compareFn.call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex]); + } else if (compareFn && typeof compareFn === "number") { + result = 1; + } else if (compareFn && typeof compareFn === "string" && Fn[compareFn]) { + result = Fn[compareFn].call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex]); + } else { + result = Fn['orderbyasc'].call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex]); + } + return result; + }); + var fragment = table.ownerDocument.createDocumentFragment(); + for (var j = 0, len = trArray.length; j < len; j++) { + fragment.appendChild(trArray[j]); + } + var tbody = table.getElementsByTagName("tbody")[0]; + if(!lastRowIndex){ + tbody.appendChild(fragment); + }else{ + tbody.insertBefore(fragment,rows[lastRowIndex- range.endRowIndex + range.beginRowIndex - 1]) + } +}; + +UE.plugins['tablesort'] = function () { + var me = this, + UT = UE.UETable, + getUETable = function (tdOrTable) { + return UT.getUETable(tdOrTable); + }, + getTableItemsByRange = function (editor) { + return UT.getTableItemsByRange(editor); + }; + + + me.ready(function () { + //添加表格可排序的样式 + utils.cssRule('tablesort', + 'table.sortEnabled tr.firstRow th,table.sortEnabled tr.firstRow td{padding-right:20px;background-repeat: no-repeat;background-position: center right;' + + ' background-image:url(' + me.options.themePath + me.options.theme + '/images/sortable.png);}', + me.document); + + //做单元格合并操作时,清除可排序标识 + me.addListener("afterexeccommand", function (type, cmd) { + if( cmd == 'mergeright' || cmd == 'mergedown' || cmd == 'mergecells') { + this.execCommand('disablesort'); + } + }); + }); + + + + //表格排序 + UE.commands['sorttable'] = { + queryCommandState: function () { + var me = this, + tableItems = getTableItemsByRange(me); + if (!tableItems.cell) return -1; + var table = tableItems.table, + cells = table.getElementsByTagName("td"); + for (var i = 0, cell; cell = cells[i++];) { + if (cell.rowSpan != 1 || cell.colSpan != 1) return -1; + } + return 0; + }, + execCommand: function (cmd, fn) { + var me = this, + range = me.selection.getRange(), + bk = range.createBookmark(true), + tableItems = getTableItemsByRange(me), + cell = tableItems.cell, + ut = getUETable(tableItems.table), + cellInfo = ut.getCellInfo(cell); + ut.sortTable(cellInfo.cellIndex, fn); + range.moveToBookmark(bk); + try{ + range.select(); + }catch(e){} + } + }; + + //设置表格可排序,清除表格可排序 + UE.commands["enablesort"] = UE.commands["disablesort"] = { + queryCommandState: function (cmd) { + var table = getTableItemsByRange(this).table; + if(table && cmd=='enablesort') { + var cells = domUtils.getElementsByTagName(table, 'th td'); + for(var i = 0; i1 || cells[i].getAttribute('rowspan')>1) return -1; + } + } + + return !table ? -1: cmd=='enablesort' ^ table.getAttribute('data-sort')!='sortEnabled' ? -1:0; + }, + execCommand: function (cmd) { + var table = getTableItemsByRange(this).table; + table.setAttribute("data-sort", cmd == "enablesort" ? "sortEnabled" : "sortDisabled"); + cmd == "enablesort" ? domUtils.addClass(table,"sortEnabled"):domUtils.removeClasses(table,"sortEnabled"); + } + }; +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/template.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/template.js new file mode 100644 index 000000000..c3d13c5aa --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/template.js @@ -0,0 +1,39 @@ +///import core +///import plugins\inserthtml.js +///import plugins\cleardoc.js +///commands 模板 +///commandsName template +///commandsTitle 模板 +///commandsDialog dialogs\template +UE.plugins['template'] = function () { + UE.commands['template'] = { + execCommand:function (cmd, obj) { + obj.html && this.execCommand("inserthtml", obj.html); + } + }; + this.addListener("click", function (type, evt) { + var el = evt.target || evt.srcElement, + range = this.selection.getRange(); + var tnode = domUtils.findParent(el, function (node) { + if (node.className && domUtils.hasClass(node, "ue_t")) { + return node; + } + }, true); + tnode && range.selectNode(tnode).shrinkBoundary().select(); + }); + this.addListener("keydown", function (type, evt) { + var range = this.selection.getRange(); + if (!range.collapsed) { + if (!evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) { + var tnode = domUtils.findParent(range.startContainer, function (node) { + if (node.className && domUtils.hasClass(node, "ue_t")) { + return node; + } + }, true); + if (tnode) { + domUtils.removeClasses(tnode, ["ue_t"]); + } + } + } + }); +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/time.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/time.js new file mode 100644 index 000000000..3fdfd62c3 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/time.js @@ -0,0 +1,50 @@ +/** + * 插入时间和日期 + * @file + * @since 1.2.6.1 + */ + +/** + * 插入时间,默认格式:12:59:59 + * @command time + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'time'); + * ``` + */ + +/** + * 插入日期,默认格式:2013-08-30 + * @command date + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'date'); + * ``` + */ +UE.commands['time'] = UE.commands["date"] = { + execCommand : function(cmd, format){ + var date = new Date; + + function formatTime(date, format) { + var hh = ('0' + date.getHours()).slice(-2), + ii = ('0' + date.getMinutes()).slice(-2), + ss = ('0' + date.getSeconds()).slice(-2); + format = format || 'hh:ii:ss'; + return format.replace(/hh/ig, hh).replace(/ii/ig, ii).replace(/ss/ig, ss); + } + function formatDate(date, format) { + var yyyy = ('000' + date.getFullYear()).slice(-4), + yy = yyyy.slice(-2), + mm = ('0' + (date.getMonth()+1)).slice(-2), + dd = ('0' + date.getDate()).slice(-2); + format = format || 'yyyy-mm-dd'; + return format.replace(/yyyy/ig, yyyy).replace(/yy/ig, yy).replace(/mm/ig, mm).replace(/dd/ig, dd); + } + + this.execCommand('insertHtml',cmd == "time" ? formatTime(date, format):formatDate(date, format) ); + } +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/undo.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/undo.js new file mode 100644 index 000000000..93dd94839 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/undo.js @@ -0,0 +1,298 @@ +/** + * undo redo + * @file + * @since 1.2.6.1 + */ + +/** + * 撤销上一次执行的命令 + * @command undo + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'undo' ); + * ``` + */ + +/** + * 重做上一次执行的命令 + * @command redo + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'redo' ); + * ``` + */ + +UE.plugins['undo'] = function () { + var saveSceneTimer; + var me = this, + maxUndoCount = me.options.maxUndoCount || 20, + maxInputCount = me.options.maxInputCount || 20, + fillchar = new RegExp(domUtils.fillChar + '|<\/hr>', 'gi');// ie会产生多余的 + var noNeedFillCharTags = { + ol:1,ul:1,table:1,tbody:1,tr:1,body:1 + }; + var orgState = me.options.autoClearEmptyNode; + function compareAddr(indexA, indexB) { + if (indexA.length != indexB.length) + return 0; + for (var i = 0, l = indexA.length; i < l; i++) { + if (indexA[i] != indexB[i]) + return 0 + } + return 1; + } + + function compareRangeAddress(rngAddrA, rngAddrB) { + if (rngAddrA.collapsed != rngAddrB.collapsed) { + return 0; + } + if (!compareAddr(rngAddrA.startAddress, rngAddrB.startAddress) || !compareAddr(rngAddrA.endAddress, rngAddrB.endAddress)) { + return 0; + } + return 1; + } + + function UndoManager() { + this.list = []; + this.index = 0; + this.hasUndo = false; + this.hasRedo = false; + this.undo = function () { + if (this.hasUndo) { + if (!this.list[this.index - 1] && this.list.length == 1) { + this.reset(); + return; + } + while (this.list[this.index].content == this.list[this.index - 1].content) { + this.index--; + if (this.index == 0) { + return this.restore(0); + } + } + this.restore(--this.index); + } + }; + this.redo = function () { + if (this.hasRedo) { + while (this.list[this.index].content == this.list[this.index + 1].content) { + this.index++; + if (this.index == this.list.length - 1) { + return this.restore(this.index); + } + } + this.restore(++this.index); + } + }; + + this.restore = function () { + var me = this.editor; + var scene = this.list[this.index]; + var root = UE.htmlparser(scene.content.replace(fillchar, '')); + me.options.autoClearEmptyNode = false; + me.filterInputRule(root); + me.options.autoClearEmptyNode = orgState; + //trace:873 + //去掉展位符 + me.document.body.innerHTML = root.toHtml(); + me.fireEvent('afterscencerestore'); + //处理undo后空格不展位的问题 + if (browser.ie) { + utils.each(domUtils.getElementsByTagName(me.document,'td th caption p'),function(node){ + if(domUtils.isEmptyNode(node)){ + domUtils.fillNode(me.document, node); + } + }) + } + + try{ + var rng = new dom.Range(me.document).moveToAddress(scene.address); + rng.select(noNeedFillCharTags[rng.startContainer.nodeName.toLowerCase()]); + }catch(e){} + + this.update(); + this.clearKey(); + //不能把自己reset了 + me.fireEvent('reset', true); + }; + + this.getScene = function () { + var me = this.editor; + var rng = me.selection.getRange(), + rngAddress = rng.createAddress(false,true); + me.fireEvent('beforegetscene'); + var root = UE.htmlparser(me.body.innerHTML); + me.options.autoClearEmptyNode = false; + me.filterOutputRule(root); + me.options.autoClearEmptyNode = orgState; + var cont = root.toHtml(); + //trace:3461 + //这个会引起回退时导致空格丢失的情况 +// browser.ie && (cont = cont.replace(/> <').replace(/\s*\s*/g, '>')); + me.fireEvent('aftergetscene'); + + return { + address:rngAddress, + content:cont + } + }; + this.save = function (notCompareRange,notSetCursor) { + clearTimeout(saveSceneTimer); + var currentScene = this.getScene(notSetCursor), + lastScene = this.list[this.index]; + + if(lastScene && lastScene.content != currentScene.content){ + me.trigger('contentchange') + } + //内容相同位置相同不存 + if (lastScene && lastScene.content == currentScene.content && + ( notCompareRange ? 1 : compareRangeAddress(lastScene.address, currentScene.address) ) + ) { + return; + } + this.list = this.list.slice(0, this.index + 1); + this.list.push(currentScene); + //如果大于最大数量了,就把最前的剔除 + if (this.list.length > maxUndoCount) { + this.list.shift(); + } + this.index = this.list.length - 1; + this.clearKey(); + //跟新undo/redo状态 + this.update(); + + }; + this.update = function () { + this.hasRedo = !!this.list[this.index + 1]; + this.hasUndo = !!this.list[this.index - 1]; + }; + this.reset = function () { + this.list = []; + this.index = 0; + this.hasUndo = false; + this.hasRedo = false; + this.clearKey(); + }; + this.clearKey = function () { + keycont = 0; + lastKeyCode = null; + }; + } + + me.undoManger = new UndoManager(); + me.undoManger.editor = me; + function saveScene() { + this.undoManger.save(); + } + + me.addListener('saveScene', function () { + var args = Array.prototype.splice.call(arguments,1); + this.undoManger.save.apply(this.undoManger,args); + }); + +// me.addListener('beforeexeccommand', saveScene); +// me.addListener('afterexeccommand', saveScene); + + me.addListener('reset', function (type, exclude) { + if (!exclude) { + this.undoManger.reset(); + } + }); + me.commands['redo'] = me.commands['undo'] = { + execCommand:function (cmdName) { + this.undoManger[cmdName](); + }, + queryCommandState:function (cmdName) { + return this.undoManger['has' + (cmdName.toLowerCase() == 'undo' ? 'Undo' : 'Redo')] ? 0 : -1; + }, + notNeedUndo:1 + }; + + var keys = { + // /*Backspace*/ 8:1, /*Delete*/ 46:1, + /*Shift*/ 16:1, /*Ctrl*/ 17:1, /*Alt*/ 18:1, + 37:1, 38:1, 39:1, 40:1 + + }, + keycont = 0, + lastKeyCode; + //输入法状态下不计算字符数 + var inputType = false; + me.addListener('ready', function () { + domUtils.on(this.body, 'compositionstart', function () { + inputType = true; + }); + domUtils.on(this.body, 'compositionend', function () { + inputType = false; + }) + }); + //快捷键 + me.addshortcutkey({ + "Undo":"ctrl+90", //undo + "Redo":"ctrl+89" //redo + + }); + var isCollapsed = true; + me.addListener('keydown', function (type, evt) { + + var me = this; + var keyCode = evt.keyCode || evt.which; + if (!keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) { + if (inputType) + return; + + if(!me.selection.getRange().collapsed){ + me.undoManger.save(false,true); + isCollapsed = false; + return; + } + if (me.undoManger.list.length == 0) { + me.undoManger.save(true); + } + clearTimeout(saveSceneTimer); + function save(cont){ + cont.undoManger.save(false,true); + cont.fireEvent('selectionchange'); + } + saveSceneTimer = setTimeout(function(){ + if(inputType){ + var interalTimer = setInterval(function(){ + if(!inputType){ + save(me); + clearInterval(interalTimer) + } + },300) + return; + } + save(me); + },200); + + lastKeyCode = keyCode; + keycont++; + if (keycont >= maxInputCount ) { + save(me) + } + } + }); + me.addListener('keyup', function (type, evt) { + var keyCode = evt.keyCode || evt.which; + if (!keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) { + if (inputType) + return; + if(!isCollapsed){ + this.undoManger.save(false,true); + isCollapsed = true; + } + } + }); + //扩展实例,添加关闭和开启命令undo + me.stopCmdUndo = function(){ + me.__hasEnterExecCommand = true; + }; + me.startCmdUndo = function(){ + me.__hasEnterExecCommand = false; + } +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/video.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/video.js new file mode 100644 index 000000000..08654d7d5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/video.js @@ -0,0 +1,161 @@ +/** + * video插件, 为UEditor提供视频插入支持 + * @file + * @since 1.2.6.1 + */ + +UE.plugins['video'] = function (){ + var me =this; + + /** + * 创建插入视频字符窜 + * @param url 视频地址 + * @param width 视频宽度 + * @param height 视频高度 + * @param align 视频对齐 + * @param toEmbed 是否以flash代替显示 + * @param addParagraph 是否需要添加P 标签 + */ + function creatInsertStr(url,width,height,id,align,classname,type){ + + url = utils.unhtmlForUrl(url); + align = utils.unhtml(align); + classname = utils.unhtml(classname); + + width = parseInt(width, 10) || 0; + height = parseInt(height, 10) || 0; + + var str; + switch (type){ + case 'image': + str = '' + break; + case 'embed': + str = ''; + break; + case 'video': + var ext = url.substr(url.lastIndexOf('.') + 1); + if(ext == 'ogv') ext = 'ogg'; + str = '' + + ''; + break; + } + return str; + } + + function switchImgAndVideo(root,img2video){ + utils.each(root.getNodesByTagName(img2video ? 'img' : 'embed video'),function(node){ + var className = node.getAttr('class'); + if(className && className.indexOf('edui-faked-video') != -1){ + var html = creatInsertStr( img2video ? node.getAttr('_url') : node.getAttr('src'),node.getAttr('width'),node.getAttr('height'),null,node.getStyle('float') || '',className,img2video ? 'embed':'image'); + node.parentNode.replaceChild(UE.uNode.createElement(html),node); + } + if(className && className.indexOf('edui-upload-video') != -1){ + var html = creatInsertStr( img2video ? node.getAttr('_url') : node.getAttr('src'),node.getAttr('width'),node.getAttr('height'),null,node.getStyle('float') || '',className,img2video ? 'video':'image'); + node.parentNode.replaceChild(UE.uNode.createElement(html),node); + } + }) + } + + me.addOutputRule(function(root){ + switchImgAndVideo(root,true) + }); + me.addInputRule(function(root){ + switchImgAndVideo(root) + }); + + /** + * 插入视频 + * @command insertvideo + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { Object } videoAttr 键值对对象, 描述一个视频的所有属性 + * @example + * ```javascript + * + * var videoAttr = { + * //视频地址 + * url: 'http://www.youku.com/xxx', + * //视频宽高值, 单位px + * width: 200, + * height: 100 + * }; + * + * //editor 是编辑器实例 + * //向编辑器插入单个视频 + * editor.execCommand( 'insertvideo', videoAttr ); + * ``` + */ + + /** + * 插入视频 + * @command insertvideo + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { Array } videoArr 需要插入的视频的数组, 其中的每一个元素都是一个键值对对象, 描述了一个视频的所有属性 + * @example + * ```javascript + * + * var videoAttr1 = { + * //视频地址 + * url: 'http://www.youku.com/xxx', + * //视频宽高值, 单位px + * width: 200, + * height: 100 + * }, + * videoAttr2 = { + * //视频地址 + * url: 'http://www.youku.com/xxx', + * //视频宽高值, 单位px + * width: 200, + * height: 100 + * } + * + * //editor 是编辑器实例 + * //该方法将会向编辑器内插入两个视频 + * editor.execCommand( 'insertvideo', [ videoAttr1, videoAttr2 ] ); + * ``` + */ + + /** + * 查询当前光标所在处是否是一个视频 + * @command insertvideo + * @method queryCommandState + * @param { String } cmd 需要查询的命令字符串 + * @return { int } 如果当前光标所在处的元素是一个视频对象, 则返回1,否则返回0 + * @example + * ```javascript + * + * //editor 是编辑器实例 + * editor.queryCommandState( 'insertvideo' ); + * ``` + */ + me.commands["insertvideo"] = { + execCommand: function (cmd, videoObjs, type){ + videoObjs = utils.isArray(videoObjs)?videoObjs:[videoObjs]; + var html = [],id = 'tmpVedio', cl; + for(var i=0,vi,len = videoObjs.length;ihttp://app.baidu.com/ + * @param { Object } appOptions 应用所需的参数项, 支持的key有: title=>应用标题, width=>应用容器宽度, + * height=>应用容器高度,logo=>应用logo,url=>应用地址 + * @example + * ```javascript + * //editor是编辑器实例 + * //在编辑器里插入一个“植物大战僵尸”的APP + * editor.execCommand( 'webapp' , { + * title: '植物大战僵尸', + * width: 560, + * height: 465, + * logo: '应用展示的图片', + * url: '百度应用的地址' + * } ); + * ``` + */ + +//UE.plugins['webapp'] = function () { +// var me = this; +// function createInsertStr( obj, toIframe, addParagraph ) { +// return !toIframe ? +// (addParagraph ? '

    ' : '') + '' + +// (addParagraph ? '

    ' : '') +// : +// ''; +// } +// +// function switchImgAndIframe( img2frame ) { +// var tmpdiv, +// nodes = domUtils.getElementsByTagName( me.document, !img2frame ? "iframe" : "img" ); +// for ( var i = 0, node; node = nodes[i++]; ) { +// if ( node.className != "edui-faked-webapp" ){ +// continue; +// } +// tmpdiv = me.document.createElement( "div" ); +// tmpdiv.innerHTML = createInsertStr( img2frame ? {url:node.getAttribute( "_url" ), width:node.width, height:node.height,title:node.title,logo:node.style.backgroundImage.replace("url(","").replace(")","")} : {url:node.getAttribute( "src", 2 ),title:node.title, width:node.width, height:node.height,logo:node.getAttribute("logo_url")}, img2frame ? true : false,false ); +// node.parentNode.replaceChild( tmpdiv.firstChild, node ); +// } +// } +// +// me.addListener( "beforegetcontent", function () { +// switchImgAndIframe( true ); +// } ); +// me.addListener( 'aftersetcontent', function () { +// switchImgAndIframe( false ); +// } ); +// me.addListener( 'aftergetcontent', function ( cmdName ) { +// if ( cmdName == 'aftergetcontent' && me.queryCommandState( 'source' ) ){ +// return; +// } +// switchImgAndIframe( false ); +// } ); +// +// me.commands['webapp'] = { +// execCommand:function ( cmd, obj ) { +// me.execCommand( "inserthtml", createInsertStr( obj, false,true ) ); +// } +// }; +//}; + +UE.plugin.register('webapp', function (){ + var me = this; + function createInsertStr(obj,toEmbed){ + return !toEmbed ? + '' + : + '' + + } + return { + outputRule: function(root){ + utils.each(root.getNodesByTagName('img'),function(node){ + var html; + if(node.getAttr('class') == 'edui-faked-webapp'){ + html = createInsertStr({ + title:node.getAttr('title'), + 'width':node.getAttr('width'), + 'height':node.getAttr('height'), + 'align':node.getAttr('align'), + 'cssfloat':node.getStyle('float'), + 'url':node.getAttr("_url"), + 'logo':node.getAttr('_logo_url') + },true); + var embed = UE.uNode.createElement(html); + node.parentNode.replaceChild(embed,node); + } + }) + }, + inputRule:function(root){ + utils.each(root.getNodesByTagName('iframe'),function(node){ + if(node.getAttr('class') == 'edui-faked-webapp'){ + var img = UE.uNode.createElement(createInsertStr({ + title:node.getAttr('title'), + 'width':node.getAttr('width'), + 'height':node.getAttr('height'), + 'align':node.getAttr('align'), + 'cssfloat':node.getStyle('float'), + 'url':node.getAttr("src"), + 'logo':node.getAttr('logo_url') + })); + node.parentNode.replaceChild(img,node); + } + }) + + }, + commands:{ + /** + * 插入百度应用 + * @command webapp + * @method execCommand + * @remind 需要百度APPKey + * @remind 百度应用主页: http://app.baidu.com/ + * @param { Object } appOptions 应用所需的参数项, 支持的key有: title=>应用标题, width=>应用容器宽度, + * height=>应用容器高度,logo=>应用logo,url=>应用地址 + * @example + * ```javascript + * //editor是编辑器实例 + * //在编辑器里插入一个“植物大战僵尸”的APP + * editor.execCommand( 'webapp' , { + * title: '植物大战僵尸', + * width: 560, + * height: 465, + * logo: '应用展示的图片', + * url: '百度应用的地址' + * } ); + * ``` + */ + 'webapp':{ + execCommand:function (cmd, obj) { + + var me = this, + str = createInsertStr(utils.extend(obj,{ + align:'none' + }), false); + me.execCommand("inserthtml",str); + }, + queryCommandState:function () { + var me = this, + img = me.selection.getRange().getClosedNode(), + flag = img && (img.className == "edui-faked-webapp"); + return flag ? 1 : 0; + } + } + } + } +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/wordcount.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/wordcount.js new file mode 100644 index 000000000..57ef20fbf --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/wordcount.js @@ -0,0 +1,33 @@ +///import core +///commands 字数统计 +///commandsName WordCount,wordCount +///commandsTitle 字数统计 +/* + * Created by JetBrains WebStorm. + * User: taoqili + * Date: 11-9-7 + * Time: 下午8:18 + * To change this template use File | Settings | File Templates. + */ + +UE.plugins['wordcount'] = function(){ + var me = this; + me.setOpt('wordCount',true); + me.addListener('contentchange',function(){ + me.fireEvent('wordcount'); + }); + var timer; + me.addListener('ready',function(){ + var me = this; + domUtils.on(me.body,"keyup",function(evt){ + var code = evt.keyCode||evt.which, + //忽略的按键,ctr,alt,shift,方向键 + ignores = {"16":1,"18":1,"20":1,"37":1,"38":1,"39":1,"40":1}; + if(code in ignores) return; + clearTimeout(timer); + timer = setTimeout(function(){ + me.fireEvent('wordcount'); + },200) + }) + }); +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/wordimage.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/wordimage.js new file mode 100644 index 000000000..5772d163c --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/wordimage.js @@ -0,0 +1,53 @@ +///import core +///commands 本地图片引导上传 +///commandsName WordImage +///commandsTitle 本地图片引导上传 +///commandsDialog dialogs\wordimage + +UE.plugin.register('wordimage',function(){ + var me = this, + images = []; + return { + commands : { + 'wordimage':{ + execCommand:function () { + var images = domUtils.getElementsByTagName(me.body, "img"); + var urlList = []; + for (var i = 0, ci; ci = images[i++];) { + var url = ci.getAttribute("word_img"); + url && urlList.push(url); + } + return urlList; + }, + queryCommandState:function () { + images = domUtils.getElementsByTagName(me.body, "img"); + for (var i = 0, ci; ci = images[i++];) { + if (ci.getAttribute("word_img")) { + return 1; + } + } + return -1; + }, + notNeedUndo:true + } + }, + inputRule : function (root) { + utils.each(root.getNodesByTagName('img'), function (img) { + var attrs = img.attrs, + flag = parseInt(attrs.width) < 128 || parseInt(attrs.height) < 43, + opt = me.options, + src = opt.UEDITOR_HOME_URL + 'themes/default/images/spacer.gif'; + if (attrs['src'] && /^(?:(file:\/+))/.test(attrs['src'])) { + img.setAttr({ + width:attrs.width, + height:attrs.height, + alt:attrs.alt, + word_img: attrs.src, + src:src, + 'style':'background:url(' + ( flag ? opt.themePath + opt.theme + '/images/word.gif' : opt.langPath + opt.lang + '/images/localimage.png') + ') no-repeat center center;border:1px solid #ddd' + }) + } + }) + } + } +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/xssFilter.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/xssFilter.js new file mode 100644 index 000000000..39665eff1 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/plugins/xssFilter.js @@ -0,0 +1,79 @@ +/** + * @file xssFilter.js + * @desc xss过滤器 + * @author robbenmu + */ + +UE.plugins.xssFilter = function() { + + var config = UEDITOR_CONFIG; + var whitList = config.whitList; + + function filter(node) { + + var tagName = node.tagName; + var attrs = node.attrs; + + if (!whitList.hasOwnProperty(tagName)) { + node.parentNode.removeChild(node); + return false; + } + + UE.utils.each(attrs, function (val, key) { + + if (whitList[tagName].indexOf(key) === -1) { + node.setAttr(key); + } + }); + } + + // 添加inserthtml\paste等操作用的过滤规则 + if (whitList && config.xssFilterRules) { + this.options.filterRules = function () { + + var result = {}; + + UE.utils.each(whitList, function(val, key) { + result[key] = function (node) { + return filter(node); + }; + }); + + return result; + }(); + } + + var tagList = []; + + UE.utils.each(whitList, function (val, key) { + tagList.push(key); + }); + + // 添加input过滤规则 + // + if (whitList && config.inputXssFilter) { + this.addInputRule(function (root) { + + root.traversal(function(node) { + if (node.type !== 'element') { + return false; + } + filter(node); + }); + }); + } + // 添加output过滤规则 + // + if (whitList && config.outputXssFilter) { + this.addOutputRule(function (root) { + + root.traversal(function(node) { + if (node.type !== 'element') { + return false; + } + filter(node); + }); + }); + } + +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/autotypesetbutton.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/autotypesetbutton.js new file mode 100644 index 000000000..3cd67db8f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/autotypesetbutton.js @@ -0,0 +1,138 @@ +///import core +///import uicore +///import ui/popup.js +///import ui/autotypesetpicker.js +///import ui/splitbutton.js +(function (){ + var utils = baidu.editor.utils, + Popup = baidu.editor.ui.Popup, + AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker, + SplitButton = baidu.editor.ui.SplitButton, + AutoTypeSetButton = baidu.editor.ui.AutoTypeSetButton = function (options){ + this.initOptions(options); + this.initAutoTypeSetButton(); + }; + function getPara(me){ + + var opt = {}, + cont = me.getDom(), + editorId = me.editor.uid, + inputType = null, + attrName = null, + ipts = domUtils.getElementsByTagName(cont,"input"); + for(var i=ipts.length-1,ipt;ipt=ipts[i--];){ + inputType = ipt.getAttribute("type"); + if(inputType=="checkbox"){ + attrName = ipt.getAttribute("name"); + opt[attrName] && delete opt[attrName]; + if(ipt.checked){ + var attrValue = document.getElementById( attrName + "Value" + editorId ); + if(attrValue){ + if(/input/ig.test(attrValue.tagName)){ + opt[attrName] = attrValue.value; + } else { + var iptChilds = attrValue.getElementsByTagName("input"); + for(var j=iptChilds.length-1,iptchild;iptchild=iptChilds[j--];){ + if(iptchild.checked){ + opt[attrName] = iptchild.value; + break; + } + } + } + } else { + opt[attrName] = true; + } + } else { + opt[attrName] = false; + } + } else { + opt[ipt.getAttribute("value")] = ipt.checked; + } + + } + + var selects = domUtils.getElementsByTagName(cont,"select"); + for(var i=0,si;si=selects[i++];){ + var attr = si.getAttribute('name'); + opt[attr] = opt[attr] ? si.value : ''; + } + + utils.extend(me.editor.options.autotypeset,opt); + + me.editor.setPreferences('autotypeset', opt); + } + + AutoTypeSetButton.prototype = { + initAutoTypeSetButton: function (){ + + var me = this; + this.popup = new Popup({ + //传入配置参数 + content: new AutoTypeSetPicker({editor:me.editor}), + 'editor':me.editor, + hide : function(){ + if (!this._hidden && this.getDom()) { + getPara(this); + this.getDom().style.display = 'none'; + this._hidden = true; + this.fireEvent('hide'); + } + } + }); + var flag = 0; + this.popup.addListener('postRenderAfter',function(){ + var popupUI = this; + if(flag)return; + var cont = this.getDom(), + btn = cont.getElementsByTagName('button')[0]; + + btn.onclick = function(){ + getPara(popupUI); + me.editor.execCommand('autotypeset'); + popupUI.hide() + }; + + domUtils.on(cont, 'click', function(e) { + var target = e.target || e.srcElement, + editorId = me.editor.uid; + if (target && target.tagName == 'INPUT') { + + // 点击图片浮动的checkbox,去除对应的radio + if (target.name == 'imageBlockLine' || target.name == 'textAlign' || target.name == 'symbolConver') { + var checked = target.checked, + radioTd = document.getElementById( target.name + 'Value' + editorId), + radios = radioTd.getElementsByTagName('input'), + defalutSelect = { + 'imageBlockLine': 'none', + 'textAlign': 'left', + 'symbolConver': 'tobdc' + }; + + for (var i = 0; i < radios.length; i++) { + if (checked) { + if (radios[i].value == defalutSelect[target.name]) { + radios[i].checked = 'checked'; + } + } else { + radios[i].checked = false; + } + } + } + // 点击radio,选中对应的checkbox + if (target.name == ('imageBlockLineValue' + editorId) || target.name == ('textAlignValue' + editorId) || target.name == 'bdc') { + var checkboxs = target.parentNode.previousSibling.getElementsByTagName('input'); + checkboxs && (checkboxs[0].checked = true); + } + + getPara(popupUI); + } + }); + + flag = 1; + }); + this.initSplitButton(); + } + }; + utils.inherits(AutoTypeSetButton, SplitButton); + +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/autotypesetpicker.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/autotypesetpicker.js new file mode 100644 index 000000000..09ec296eb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/autotypesetpicker.js @@ -0,0 +1,66 @@ +///import core +///import uicore +(function () { + var utils = baidu.editor.utils, + UIBase = baidu.editor.ui.UIBase; + + var AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker = function (options) { + this.initOptions(options); + this.initAutoTypeSetPicker(); + }; + AutoTypeSetPicker.prototype = { + initAutoTypeSetPicker:function () { + this.initUIBase(); + }, + getHtmlTpl:function () { + var me = this.editor, + opt = me.options.autotypeset, + lang = me.getLang("autoTypeSet"); + + var textAlignInputName = 'textAlignValue' + me.uid, + imageBlockInputName = 'imageBlockLineValue' + me.uid, + symbolConverInputName = 'symbolConverValue' + me.uid; + + return '
    ' + + '
    ' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
    ' + lang.mergeLine + '' + lang.delLine + '
    ' + lang.removeFormat + '' + lang.indent + '
    ' + lang.alignment + '' + + '' + me.getLang("justifyleft") + + '' + me.getLang("justifycenter") + + '' + me.getLang("justifyright") + + '
    ' + lang.imageFloat + '' + + '' + me.getLang("default") + + '' + me.getLang("justifyleft") + + '' + me.getLang("justifycenter") + + '' + me.getLang("justifyright") + + '
    ' + lang.removeFontsize + '' + lang.removeFontFamily + '
    ' + lang.removeHtml + '
    ' + lang.pasteFilter + '
    ' + lang.symbol + '' + + '' + lang.bdc2sb + + '' + lang.tobdc + '' + + '
    ' + + '
    ' + + '
    '; + + + }, + _UIBase_render:UIBase.prototype.render + }; + utils.inherits(AutoTypeSetPicker, UIBase); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/breakline.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/breakline.js new file mode 100644 index 000000000..4ccb5fc21 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/breakline.js @@ -0,0 +1,19 @@ +(function (){ + var utils = baidu.editor.utils, + UIBase = baidu.editor.ui.UIBase, + Breakline = baidu.editor.ui.Breakline = function (options){ + this.initOptions(options); + this.initSeparator(); + }; + Breakline.prototype = { + uiName: 'Breakline', + initSeparator: function (){ + this.initUIBase(); + }, + getHtmlTpl: function (){ + return '
    '; + } + }; + utils.inherits(Breakline, UIBase); + +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/button.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/button.js new file mode 100644 index 000000000..6b7b7c674 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/button.js @@ -0,0 +1,69 @@ +///import core +///import uicore +///import ui/stateful.js +(function (){ + var utils = baidu.editor.utils, + UIBase = baidu.editor.ui.UIBase, + Stateful = baidu.editor.ui.Stateful, + Button = baidu.editor.ui.Button = function (options){ + if(options.name){ + var btnName = options.name; + var cssRules = options.cssRules; + if(!options.className){ + options.className = 'edui-for-' + btnName; + } + options.cssRules = '.edui-default .edui-for-'+ btnName +' .edui-icon {'+ cssRules +'}' + } + this.initOptions(options); + this.initButton(); + }; + Button.prototype = { + uiName: 'button', + label: '', + title: '', + showIcon: true, + showText: true, + cssRules:'', + initButton: function (){ + this.initUIBase(); + this.Stateful_init(); + if(this.cssRules){ + utils.cssRule('edui-customize-'+this.name+'-style',this.cssRules); + } + }, + getHtmlTpl: function (){ + return '
    ' + + '
    ' + + '
    ' + + (this.showIcon ? '
    ' : '') + + (this.showText ? '
    ' + this.label + '
    ' : '') + + '
    ' + + '
    ' + + '
    '; + }, + postRender: function (){ + this.Stateful_postRender(); + this.setDisabled(this.disabled) + }, + _onMouseDown: function (e){ + var target = e.target || e.srcElement, + tagName = target && target.tagName && target.tagName.toLowerCase(); + if (tagName == 'input' || tagName == 'object' || tagName == 'object') { + return false; + } + }, + _onClick: function (){ + if (!this.isDisabled()) { + this.fireEvent('click'); + } + }, + setTitle: function(text){ + var label = this.getDom('label'); + label.innerHTML = text; + } + }; + utils.inherits(Button, UIBase); + utils.extend(Button.prototype, Stateful); + +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/cellalignpicker.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/cellalignpicker.js new file mode 100644 index 000000000..c243644ea --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/cellalignpicker.js @@ -0,0 +1,96 @@ +///import core +///import uicore +(function () { + var utils = baidu.editor.utils, + Popup = baidu.editor.ui.Popup, + Stateful = baidu.editor.ui.Stateful, + UIBase = baidu.editor.ui.UIBase; + + /** + * 该参数将新增一个参数: selected, 参数类型为一个Object, 形如{ 'align': 'center', 'valign': 'top' }, 表示单元格的初始 + * 对齐状态为: 竖直居上,水平居中; 其中 align的取值为:'center', 'left', 'right'; valign的取值为: 'top', 'middle', 'bottom' + * @update 2013/4/2 hancong03@baidu.com + */ + var CellAlignPicker = baidu.editor.ui.CellAlignPicker = function (options) { + this.initOptions(options); + this.initSelected(); + this.initCellAlignPicker(); + }; + CellAlignPicker.prototype = { + //初始化选中状态, 该方法将根据传递进来的参数获取到应该选中的对齐方式图标的索引 + initSelected: function(){ + + var status = { + + valign: { + top: 0, + middle: 1, + bottom: 2 + }, + align: { + left: 0, + center: 1, + right: 2 + }, + count: 3 + + }, + result = -1; + + if( this.selected ) { + this.selectedIndex = status.valign[ this.selected.valign ] * status.count + status.align[ this.selected.align ]; + } + + }, + initCellAlignPicker:function () { + this.initUIBase(); + this.Stateful_init(); + }, + getHtmlTpl:function () { + + var alignType = [ 'left', 'center', 'right' ], + COUNT = 9, + tempClassName = null, + tempIndex = -1, + tmpl = []; + + + for( var i= 0; i'); + + tmpl.push( '
    ' ); + + tempIndex === 2 && tmpl.push(''); + + } + + return '
    ' + + '
    ' + + '' + + tmpl.join('') + + '
    ' + + '
    ' + + '
    '; + }, + getStateDom: function (){ + return this.target; + }, + _onClick: function (evt){ + var target= evt.target || evt.srcElement; + if(/icon/.test(target.className)){ + this.items[target.parentNode.getAttribute("index")].onclick(); + Popup.postHide(evt); + } + }, + _UIBase_render:UIBase.prototype.render + }; + utils.inherits(CellAlignPicker, UIBase); + utils.extend(CellAlignPicker.prototype, Stateful,true); +})(); + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/colorbutton.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/colorbutton.js new file mode 100644 index 000000000..b834f5111 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/colorbutton.js @@ -0,0 +1,60 @@ +///import core +///import uicore +///import ui/colorpicker.js +///import ui/popup.js +///import ui/splitbutton.js +(function (){ + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + ColorPicker = baidu.editor.ui.ColorPicker, + Popup = baidu.editor.ui.Popup, + SplitButton = baidu.editor.ui.SplitButton, + ColorButton = baidu.editor.ui.ColorButton = function (options){ + this.initOptions(options); + this.initColorButton(); + }; + ColorButton.prototype = { + initColorButton: function (){ + var me = this; + this.popup = new Popup({ + content: new ColorPicker({ + noColorText: me.editor.getLang("clearColor"), + editor:me.editor, + onpickcolor: function (t, color){ + me._onPickColor(color); + }, + onpicknocolor: function (t, color){ + me._onPickNoColor(color); + } + }), + editor:me.editor + }); + this.initSplitButton(); + }, + _SplitButton_postRender: SplitButton.prototype.postRender, + postRender: function (){ + this._SplitButton_postRender(); + this.getDom('button_body').appendChild( + uiUtils.createElementByHtml('
    ') + ); + this.getDom().className += ' edui-colorbutton'; + }, + setColor: function (color){ + this.getDom('colorlump').style.backgroundColor = color; + this.color = color; + }, + _onPickColor: function (color){ + if (this.fireEvent('pickcolor', color) !== false) { + this.setColor(color); + this.popup.hide(); + } + }, + _onPickNoColor: function (color){ + if (this.fireEvent('picknocolor') !== false) { + this.popup.hide(); + } + } + }; + utils.inherits(ColorButton, SplitButton); + +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/colorpicker.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/colorpicker.js new file mode 100644 index 000000000..73bd46b29 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/colorpicker.js @@ -0,0 +1,74 @@ +///import core +///import uicore +(function (){ + var utils = baidu.editor.utils, + UIBase = baidu.editor.ui.UIBase, + ColorPicker = baidu.editor.ui.ColorPicker = function (options){ + this.initOptions(options); + this.noColorText = this.noColorText || this.editor.getLang("clearColor"); + this.initUIBase(); + }; + + ColorPicker.prototype = { + getHtmlTpl: function (){ + return genColorPicker(this.noColorText,this.editor); + }, + _onTableClick: function (evt){ + var tgt = evt.target || evt.srcElement; + var color = tgt.getAttribute('data-color'); + if (color) { + this.fireEvent('pickcolor', color); + } + }, + _onTableOver: function (evt){ + var tgt = evt.target || evt.srcElement; + var color = tgt.getAttribute('data-color'); + if (color) { + this.getDom('preview').style.backgroundColor = color; + } + }, + _onTableOut: function (){ + this.getDom('preview').style.backgroundColor = ''; + }, + _onPickNoColor: function (){ + this.fireEvent('picknocolor'); + } + }; + utils.inherits(ColorPicker, UIBase); + + var COLORS = ( + 'ffffff,000000,eeece1,1f497d,4f81bd,c0504d,9bbb59,8064a2,4bacc6,f79646,' + + 'f2f2f2,7f7f7f,ddd9c3,c6d9f0,dbe5f1,f2dcdb,ebf1dd,e5e0ec,dbeef3,fdeada,' + + 'd8d8d8,595959,c4bd97,8db3e2,b8cce4,e5b9b7,d7e3bc,ccc1d9,b7dde8,fbd5b5,' + + 'bfbfbf,3f3f3f,938953,548dd4,95b3d7,d99694,c3d69b,b2a2c7,92cddc,fac08f,' + + 'a5a5a5,262626,494429,17365d,366092,953734,76923c,5f497a,31859b,e36c09,' + + '7f7f7f,0c0c0c,1d1b10,0f243e,244061,632423,4f6128,3f3151,205867,974806,' + + 'c00000,ff0000,ffc000,ffff00,92d050,00b050,00b0f0,0070c0,002060,7030a0,').split(','); + + function genColorPicker(noColorText,editor){ + var html = '
    ' + + '
    ' + + '
    ' + + '
    '+ noColorText +'
    ' + + '
    ' + + '' + + ''+ + ''; + for (var i=0; i':'')+''; + } + html += i<70 ? '':''; + } + html += '
    '+editor.getLang("themeColor")+'
    '+editor.getLang("standardColor")+'
    '; + return html; + } +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/combox.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/combox.js new file mode 100644 index 000000000..a7aa06ba4 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/combox.js @@ -0,0 +1,96 @@ +///import core +///import uicore +///import ui/menu.js +///import ui/splitbutton.js +(function (){ + // todo: menu和item提成通用list + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + Menu = baidu.editor.ui.Menu, + SplitButton = baidu.editor.ui.SplitButton, + Combox = baidu.editor.ui.Combox = function (options){ + this.initOptions(options); + this.initCombox(); + }; + Combox.prototype = { + uiName: 'combox', + onbuttonclick:function () { + this.showPopup(); + }, + initCombox: function (){ + var me = this; + this.items = this.items || []; + for (var i=0; i vpRect.right) { + left = vpRect.right - rect.width; + } + var top = offset.top; + if (top + rect.height > vpRect.bottom) { + top = vpRect.bottom - rect.height; + } + el.style.left = Math.max(left, 0) + 'px'; + el.style.top = Math.max(top, 0) + 'px'; + }, + showAtCenter: function (){ + + var vpRect = uiUtils.getViewportRect(); + + if ( !this.fullscreen ) { + this.getDom().style.display = ''; + var popSize = this.fitSize(); + var titleHeight = this.getDom('titlebar').offsetHeight | 0; + var left = vpRect.width / 2 - popSize.width / 2; + var top = vpRect.height / 2 - (popSize.height - titleHeight) / 2 - titleHeight; + var popEl = this.getDom(); + this.safeSetOffset({ + left: Math.max(left | 0, 0), + top: Math.max(top | 0, 0) + }); + if (!domUtils.hasClass(popEl, 'edui-state-centered')) { + popEl.className += ' edui-state-centered'; + } + } else { + var dialogWrapNode = this.getDom(), + contentNode = this.getDom('content'); + + dialogWrapNode.style.display = "block"; + + var wrapRect = UE.ui.uiUtils.getClientRect( dialogWrapNode ), + contentRect = UE.ui.uiUtils.getClientRect( contentNode ); + dialogWrapNode.style.left = "-100000px"; + + contentNode.style.width = ( vpRect.width - wrapRect.width + contentRect.width ) + "px"; + contentNode.style.height = ( vpRect.height - wrapRect.height + contentRect.height ) + "px"; + + dialogWrapNode.style.width = vpRect.width + "px"; + dialogWrapNode.style.height = vpRect.height + "px"; + dialogWrapNode.style.left = 0; + + //保存环境的overflow值 + this._originalContext = { + html: { + overflowX: document.documentElement.style.overflowX, + overflowY: document.documentElement.style.overflowY + }, + body: { + overflowX: document.body.style.overflowX, + overflowY: document.body.style.overflowY + } + }; + + document.documentElement.style.overflowX = 'hidden'; + document.documentElement.style.overflowY = 'hidden'; + document.body.style.overflowX = 'hidden'; + document.body.style.overflowY = 'hidden'; + + } + + this._show(); + }, + getContentHtml: function (){ + var contentHtml = ''; + if (typeof this.content == 'string') { + contentHtml = this.content; + } else if (this.iframeUrl) { + contentHtml = ''; + } + return contentHtml; + }, + getHtmlTpl: function (){ + var footHtml = ''; + + if (this.buttons) { + var buff = []; + for (var i=0; i' + buff.join('') + '' + + ''; + } + + return '
    ' + + '
    ' + + '
    ' + + '
    ' + + '' + (this.title || '') + '' + + '
    ' + + this.closeButton.renderHtml() + + '
    ' + + '
    '+ ( this.autoReset ? '' : this.getContentHtml()) +'
    ' + + footHtml + + '
    '; + }, + postRender: function (){ + // todo: 保持居中/记住上次关闭位置选项 + if (!this.modalMask.getDom()) { + this.modalMask.render(); + this.modalMask.hide(); + } + if (!this.dragMask.getDom()) { + this.dragMask.render(); + this.dragMask.hide(); + } + var me = this; + this.addListener('show', function (){ + me.modalMask.show(this.getDom().style.zIndex - 2); + }); + this.addListener('hide', function (){ + me.modalMask.hide(); + }); + if (this.buttons) { + for (var i=0; i'; + }, + postRender: function (){ + var me = this; + domUtils.on(window, 'resize', function (){ + setTimeout(function (){ + if (!me.isHidden()) { + me._fill(); + } + }); + }); + }, + show: function (zIndex){ + this._fill(); + this.getDom().style.display = ''; + this.getDom().style.zIndex = zIndex; + }, + hide: function (){ + this.getDom().style.display = 'none'; + this.getDom().style.zIndex = ''; + }, + isHidden: function (){ + return this.getDom().style.display == 'none'; + }, + _onMouseDown: function (){ + return false; + }, + _onClick: function (e, target){ + this.fireEvent('click', e, target); + }, + _fill: function (){ + var el = this.getDom(); + var vpRect = uiUtils.getViewportRect(); + el.style.width = vpRect.width + 'px'; + el.style.height = vpRect.height + 'px'; + } + }; + utils.inherits(Mask, UIBase); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/menu.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/menu.js new file mode 100644 index 000000000..7e947b0a2 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/menu.js @@ -0,0 +1,276 @@ +///import core +///import uicore +///import ui\popup.js +///import ui\stateful.js +(function () { + var utils = baidu.editor.utils, + domUtils = baidu.editor.dom.domUtils, + uiUtils = baidu.editor.ui.uiUtils, + UIBase = baidu.editor.ui.UIBase, + Popup = baidu.editor.ui.Popup, + Stateful = baidu.editor.ui.Stateful, + CellAlignPicker = baidu.editor.ui.CellAlignPicker, + + Menu = baidu.editor.ui.Menu = function (options) { + this.initOptions(options); + this.initMenu(); + }; + + var menuSeparator = { + renderHtml:function () { + return '
    '; + }, + postRender:function () { + }, + queryAutoHide:function () { + return true; + } + }; + Menu.prototype = { + items:null, + uiName:'menu', + initMenu:function () { + this.items = this.items || []; + this.initPopup(); + this.initItems(); + }, + initItems:function () { + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + if (item == '-') { + this.items[i] = this.getSeparator(); + } else if (!(item instanceof MenuItem)) { + item.editor = this.editor; + item.theme = this.editor.options.theme; + this.items[i] = this.createItem(item); + } + } + }, + getSeparator:function () { + return menuSeparator; + }, + createItem:function (item) { + //新增一个参数menu, 该参数存储了menuItem所对应的menu引用 + item.menu = this; + return new MenuItem(item); + }, + _Popup_getContentHtmlTpl:Popup.prototype.getContentHtmlTpl, + getContentHtmlTpl:function () { + if (this.items.length == 0) { + return this._Popup_getContentHtmlTpl(); + } + var buff = []; + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + buff[i] = item.renderHtml(); + } + return ('
    ' + buff.join('') + '
    '); + }, + _Popup_postRender:Popup.prototype.postRender, + postRender:function () { + var me = this; + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + item.ownerMenu = this; + item.postRender(); + } + domUtils.on(this.getDom(), 'mouseover', function (evt) { + evt = evt || event; + var rel = evt.relatedTarget || evt.fromElement; + var el = me.getDom(); + if (!uiUtils.contains(el, rel) && el !== rel) { + me.fireEvent('over'); + } + }); + this._Popup_postRender(); + }, + queryAutoHide:function (el) { + if (el) { + if (uiUtils.contains(this.getDom(), el)) { + return false; + } + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + if (item.queryAutoHide(el) === false) { + return false; + } + } + } + }, + clearItems:function () { + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + clearTimeout(item._showingTimer); + clearTimeout(item._closingTimer); + if (item.subMenu) { + item.subMenu.destroy(); + } + } + this.items = []; + }, + destroy:function () { + if (this.getDom()) { + domUtils.remove(this.getDom()); + } + this.clearItems(); + }, + dispose:function () { + this.destroy(); + } + }; + utils.inherits(Menu, Popup); + + /** + * @update 2013/04/03 hancong03 新增一个参数menu, 该参数存储了menuItem所对应的menu引用 + * @type {Function} + */ + var MenuItem = baidu.editor.ui.MenuItem = function (options) { + this.initOptions(options); + this.initUIBase(); + this.Stateful_init(); + if (this.subMenu && !(this.subMenu instanceof Menu)) { + if (options.className && options.className.indexOf("aligntd") != -1) { + var me = this; + + //获取单元格对齐初始状态 + this.subMenu.selected = this.editor.queryCommandValue( 'cellalignment' ); + + this.subMenu = new Popup({ + content:new CellAlignPicker(this.subMenu), + parentMenu:me, + editor:me.editor, + destroy:function () { + if (this.getDom()) { + domUtils.remove(this.getDom()); + } + } + }); + this.subMenu.addListener("postRenderAfter", function () { + domUtils.on(this.getDom(), "mouseover", function () { + me.addState('opened'); + }); + }); + } else { + this.subMenu = new Menu(this.subMenu); + } + } + }; + MenuItem.prototype = { + label:'', + subMenu:null, + ownerMenu:null, + uiName:'menuitem', + alwalysHoverable:true, + getHtmlTpl:function () { + return '
    ' + + '
    ' + + this.renderLabelHtml() + + '
    ' + + '
    '; + }, + postRender:function () { + var me = this; + this.addListener('over', function () { + me.ownerMenu.fireEvent('submenuover', me); + if (me.subMenu) { + me.delayShowSubMenu(); + } + }); + if (this.subMenu) { + this.getDom().className += ' edui-hassubmenu'; + this.subMenu.render(); + this.addListener('out', function () { + me.delayHideSubMenu(); + }); + this.subMenu.addListener('over', function () { + clearTimeout(me._closingTimer); + me._closingTimer = null; + me.addState('opened'); + }); + this.ownerMenu.addListener('hide', function () { + me.hideSubMenu(); + }); + this.ownerMenu.addListener('submenuover', function (t, subMenu) { + if (subMenu !== me) { + me.delayHideSubMenu(); + } + }); + this.subMenu._bakQueryAutoHide = this.subMenu.queryAutoHide; + this.subMenu.queryAutoHide = function (el) { + if (el && uiUtils.contains(me.getDom(), el)) { + return false; + } + return this._bakQueryAutoHide(el); + }; + } + this.getDom().style.tabIndex = '-1'; + uiUtils.makeUnselectable(this.getDom()); + this.Stateful_postRender(); + }, + delayShowSubMenu:function () { + var me = this; + if (!me.isDisabled()) { + me.addState('opened'); + clearTimeout(me._showingTimer); + clearTimeout(me._closingTimer); + me._closingTimer = null; + me._showingTimer = setTimeout(function () { + me.showSubMenu(); + }, 250); + } + }, + delayHideSubMenu:function () { + var me = this; + if (!me.isDisabled()) { + me.removeState('opened'); + clearTimeout(me._showingTimer); + if (!me._closingTimer) { + me._closingTimer = setTimeout(function () { + if (!me.hasState('opened')) { + me.hideSubMenu(); + } + me._closingTimer = null; + }, 400); + } + } + }, + renderLabelHtml:function () { + return '
    ' + + '
    ' + + '
    ' + (this.label || '') + '
    '; + }, + getStateDom:function () { + return this.getDom(); + }, + queryAutoHide:function (el) { + if (this.subMenu && this.hasState('opened')) { + return this.subMenu.queryAutoHide(el); + } + }, + _onClick:function (event, this_) { + if (this.hasState('disabled')) return; + if (this.fireEvent('click', event, this_) !== false) { + if (this.subMenu) { + this.showSubMenu(); + } else { + Popup.postHide(event); + } + } + }, + showSubMenu:function () { + var rect = uiUtils.getClientRect(this.getDom()); + rect.right -= 5; + rect.left += 2; + rect.width -= 7; + rect.top -= 4; + rect.bottom += 4; + rect.height += 8; + this.subMenu.showAnchorRect(rect, true, true); + }, + hideSubMenu:function () { + this.subMenu.hide(); + } + }; + utils.inherits(MenuItem, UIBase); + utils.extend(MenuItem.prototype, Stateful, true); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/menubutton.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/menubutton.js new file mode 100644 index 000000000..a627d4dfe --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/menubutton.js @@ -0,0 +1,40 @@ +///import core +///import uicore +///import ui/menu.js +///import ui/splitbutton.js +(function (){ + var utils = baidu.editor.utils, + Menu = baidu.editor.ui.Menu, + SplitButton = baidu.editor.ui.SplitButton, + MenuButton = baidu.editor.ui.MenuButton = function (options){ + this.initOptions(options); + this.initMenuButton(); + }; + MenuButton.prototype = { + initMenuButton: function (){ + var me = this; + this.uiName = "menubutton"; + this.popup = new Menu({ + items: me.items, + className: me.className, + editor:me.editor + }); + this.popup.addListener('show', function (){ + var list = this; + for (var i=0; i' + + '
    ×
    ' + + '
    ' + + ' ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + ''; + }, + reset: function(opt){ + var me = this; + if (!opt.keepshow) { + clearTimeout(this.timer); + me.timer = setTimeout(function(){ + me.hide(); + }, opt.timeout || 4000); + } + + opt.content !== undefined && me.setContent(opt.content); + opt.type !== undefined && me.setType(opt.type); + + me.show(); + }, + postRender: function(){ + var me = this, + closer = this.getDom('closer'); + closer && domUtils.on(closer, 'click', function(){ + me.hide(); + }); + }, + setContent: function(content){ + this.getDom('content').innerHTML = content; + }, + setType: function(type){ + type = type || 'info'; + var body = this.getDom('body'); + body.className = body.className.replace(/edui-message-type-[\w-]+/, 'edui-message-type-' + type); + }, + getContent: function(){ + return this.getDom('content').innerHTML; + }, + getType: function(){ + var arr = this.getDom('body').match(/edui-message-type-([\w-]+)/); + return arr ? arr[1]:''; + }, + show: function (){ + this.getDom().style.display = 'block'; + }, + hide: function (){ + var dom = this.getDom(); + if (dom) { + dom.style.display = 'none'; + dom.parentNode && dom.parentNode.removeChild(dom); + } + } + }; + + utils.inherits(Message, UIBase); + +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/multiMenu.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/multiMenu.js new file mode 100644 index 000000000..05ed55d06 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/multiMenu.js @@ -0,0 +1,39 @@ +///import core +///import uicore + ///commands 表情 +(function(){ + var utils = baidu.editor.utils, + Popup = baidu.editor.ui.Popup, + SplitButton = baidu.editor.ui.SplitButton, + MultiMenuPop = baidu.editor.ui.MultiMenuPop = function(options){ + this.initOptions(options); + this.initMultiMenu(); + }; + + MultiMenuPop.prototype = { + initMultiMenu: function (){ + var me = this; + this.popup = new Popup({ + content: '', + editor : me.editor, + iframe_rendered: false, + onshow: function (){ + if (!this.iframe_rendered) { + this.iframe_rendered = true; + this.getDom('content').innerHTML = ''; + me.editor.container.style.zIndex && (this.getDom().style.zIndex = me.editor.container.style.zIndex * 1 + 1); + } + } + // canSideUp:false, + // canSideLeft:false + }); + this.onbuttonclick = function(){ + this.showPopup(); + }; + this.initSplitButton(); + } + + }; + + utils.inherits(MultiMenuPop, SplitButton); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/pastepicker.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/pastepicker.js new file mode 100644 index 000000000..0676fa054 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/pastepicker.js @@ -0,0 +1,66 @@ +///import core +///import uicore +(function () { + var utils = baidu.editor.utils, + Stateful = baidu.editor.ui.Stateful, + uiUtils = baidu.editor.ui.uiUtils, + UIBase = baidu.editor.ui.UIBase; + + var PastePicker = baidu.editor.ui.PastePicker = function (options) { + this.initOptions(options); + this.initPastePicker(); + }; + PastePicker.prototype = { + initPastePicker:function () { + this.initUIBase(); + this.Stateful_init(); + }, + getHtmlTpl:function () { + return '
    ' + + '
    ' + + '
    ' + this.editor.getLang("pasteOpt") + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '' + }, + getStateDom:function () { + return this.target; + }, + format:function (param) { + this.editor.ui._isTransfer = true; + this.editor.fireEvent('pasteTransfer', param); + }, + _onClick:function (cur) { + var node = domUtils.getNextDomNode(cur), + screenHt = uiUtils.getViewportRect().height, + subPop = uiUtils.getClientRect(node); + + if ((subPop.top + subPop.height) > screenHt) + node.style.top = (-subPop.height - cur.offsetHeight) + "px"; + else + node.style.top = ""; + + if (/hidden/ig.test(domUtils.getComputedStyle(node, "visibility"))) { + node.style.visibility = "visible"; + domUtils.addClass(cur, "edui-state-opened"); + } else { + node.style.visibility = "hidden"; + domUtils.removeClasses(cur, "edui-state-opened") + } + }, + _UIBase_render:UIBase.prototype.render + }; + utils.inherits(PastePicker, UIBase); + utils.extend(PastePicker.prototype, Stateful, true); +})(); + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/popup.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/popup.js new file mode 100644 index 000000000..3bccb06cd --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/popup.js @@ -0,0 +1,257 @@ +///import core +///import uicore +(function () { + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + domUtils = baidu.editor.dom.domUtils, + UIBase = baidu.editor.ui.UIBase, + Popup = baidu.editor.ui.Popup = function (options){ + this.initOptions(options); + this.initPopup(); + }; + + var allPopups = []; + function closeAllPopup( evt,el ){ + for ( var i = 0; i < allPopups.length; i++ ) { + var pop = allPopups[i]; + if (!pop.isHidden()) { + if (pop.queryAutoHide(el) !== false) { + if(evt&&/scroll/ig.test(evt.type)&&pop.className=="edui-wordpastepop") return; + pop.hide(); + } + } + } + + if(allPopups.length) + pop.editor.fireEvent("afterhidepop"); + } + + Popup.postHide = closeAllPopup; + + var ANCHOR_CLASSES = ['edui-anchor-topleft','edui-anchor-topright', + 'edui-anchor-bottomleft','edui-anchor-bottomright']; + Popup.prototype = { + SHADOW_RADIUS: 5, + content: null, + _hidden: false, + autoRender: true, + canSideLeft: true, + canSideUp: true, + initPopup: function (){ + this.initUIBase(); + allPopups.push( this ); + }, + getHtmlTpl: function (){ + return '
    ' + + '
    ' + + ' ' + + '
    ' + + '
    ' + + this.getContentHtmlTpl() + + '
    ' + + '
    ' + + '
    '; + }, + getContentHtmlTpl: function (){ + if(this.content){ + if (typeof this.content == 'string') { + return this.content; + } + return this.content.renderHtml(); + }else{ + return '' + } + + }, + _UIBase_postRender: UIBase.prototype.postRender, + postRender: function (){ + + + if (this.content instanceof UIBase) { + this.content.postRender(); + } + + //捕获鼠标滚轮 + if( this.captureWheel && !this.captured ) { + + this.captured = true; + + var winHeight = ( document.documentElement.clientHeight || document.body.clientHeight ) - 80, + _height = this.getDom().offsetHeight, + _top = uiUtils.getClientRect( this.combox.getDom() ).top, + content = this.getDom('content'), + ifr = this.getDom('body').getElementsByTagName('iframe'), + me = this; + + ifr.length && ( ifr = ifr[0] ); + + while( _top + _height > winHeight ) { + _height -= 30; + } + content.style.height = _height + 'px'; + //同步更改iframe高度 + ifr && ( ifr.style.height = _height + 'px' ); + + //阻止在combox上的鼠标滚轮事件, 防止用户的正常操作被误解 + if( window.XMLHttpRequest ) { + + domUtils.on( content, ( 'onmousewheel' in document.body ) ? 'mousewheel' :'DOMMouseScroll' , function(e){ + + if(e.preventDefault) { + e.preventDefault(); + } else { + e.returnValue = false; + } + + if( e.wheelDelta ) { + + content.scrollTop -= ( e.wheelDelta / 120 )*60; + + } else { + + content.scrollTop -= ( e.detail / -3 )*60; + + } + + }); + + } else { + + //ie6 + domUtils.on( this.getDom(), 'mousewheel' , function(e){ + + e.returnValue = false; + + me.getDom('content').scrollTop -= ( e.wheelDelta / 120 )*60; + + }); + + } + + } + this.fireEvent('postRenderAfter'); + this.hide(true); + this._UIBase_postRender(); + }, + _doAutoRender: function (){ + if (!this.getDom() && this.autoRender) { + this.render(); + } + }, + mesureSize: function (){ + var box = this.getDom('content'); + return uiUtils.getClientRect(box); + }, + fitSize: function (){ + if( this.captureWheel && this.sized ) { + return this.__size; + } + this.sized = true; + var popBodyEl = this.getDom('body'); + popBodyEl.style.width = ''; + popBodyEl.style.height = ''; + var size = this.mesureSize(); + if( this.captureWheel ) { + popBodyEl.style.width = -(-20 -size.width) + 'px'; + var height = parseInt( this.getDom('content').style.height, 10 ); + !window.isNaN( height ) && ( size.height = height ); + } else { + popBodyEl.style.width = size.width + 'px'; + } + popBodyEl.style.height = size.height + 'px'; + this.__size = size; + this.captureWheel && (this.getDom('content').style.overflow = 'auto'); + return size; + }, + showAnchor: function ( element, hoz ){ + this.showAnchorRect( uiUtils.getClientRect( element ), hoz ); + }, + showAnchorRect: function ( rect, hoz, adj ){ + this._doAutoRender(); + var vpRect = uiUtils.getViewportRect(); + this.getDom().style.visibility = 'hidden'; + this._show(); + var popSize = this.fitSize(); + + var sideLeft, sideUp, left, top; + if (hoz) { + sideLeft = this.canSideLeft && (rect.right + popSize.width > vpRect.right && rect.left > popSize.width); + sideUp = this.canSideUp && (rect.top + popSize.height > vpRect.bottom && rect.bottom > popSize.height); + left = (sideLeft ? rect.left - popSize.width : rect.right); + top = (sideUp ? rect.bottom - popSize.height : rect.top); + } else { + sideLeft = this.canSideLeft && (rect.right + popSize.width > vpRect.right && rect.left > popSize.width); + sideUp = this.canSideUp && (rect.top + popSize.height > vpRect.bottom && rect.bottom > popSize.height); + left = (sideLeft ? rect.right - popSize.width : rect.left); + top = (sideUp ? rect.top - popSize.height : rect.bottom); + } + + var popEl = this.getDom(); + uiUtils.setViewportOffset(popEl, { + left: left, + top: top + }); + domUtils.removeClasses(popEl, ANCHOR_CLASSES); + popEl.className += ' ' + ANCHOR_CLASSES[(sideUp ? 1 : 0) * 2 + (sideLeft ? 1 : 0)]; + if(this.editor){ + popEl.style.zIndex = this.editor.container.style.zIndex * 1 + 10; + baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = popEl.style.zIndex - 1; + } + this.getDom().style.visibility = 'visible'; + + }, + showAt: function (offset) { + var left = offset.left; + var top = offset.top; + var rect = { + left: left, + top: top, + right: left, + bottom: top, + height: 0, + width: 0 + }; + this.showAnchorRect(rect, false, true); + }, + _show: function (){ + if (this._hidden) { + var box = this.getDom(); + box.style.display = ''; + this._hidden = false; +// if (box.setActive) { +// box.setActive(); +// } + this.fireEvent('show'); + } + }, + isHidden: function (){ + return this._hidden; + }, + show: function (){ + this._doAutoRender(); + this._show(); + }, + hide: function (notNofity){ + if (!this._hidden && this.getDom()) { + this.getDom().style.display = 'none'; + this._hidden = true; + if (!notNofity) { + this.fireEvent('hide'); + } + } + }, + queryAutoHide: function (el){ + return !el || !uiUtils.contains(this.getDom(), el); + } + }; + utils.inherits(Popup, UIBase); + + domUtils.on( document, 'mousedown', function ( evt ) { + var el = evt.target || evt.srcElement; + closeAllPopup( evt,el ); + } ); + domUtils.on( window, 'scroll', function (evt,el) { + closeAllPopup( evt,el ); + } ); + +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/separator.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/separator.js new file mode 100644 index 000000000..0041c8d58 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/separator.js @@ -0,0 +1,19 @@ +(function (){ + var utils = baidu.editor.utils, + UIBase = baidu.editor.ui.UIBase, + Separator = baidu.editor.ui.Separator = function (options){ + this.initOptions(options); + this.initSeparator(); + }; + Separator.prototype = { + uiName: 'separator', + initSeparator: function (){ + this.initUIBase(); + }, + getHtmlTpl: function (){ + return '
    '; + } + }; + utils.inherits(Separator, UIBase); + +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/shortcutmenu.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/shortcutmenu.js new file mode 100644 index 000000000..9b71bd2fd --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/shortcutmenu.js @@ -0,0 +1,232 @@ +(function () { + var UI = baidu.editor.ui, + UIBase = UI.UIBase, + uiUtils = UI.uiUtils, + utils = baidu.editor.utils, + domUtils = baidu.editor.dom.domUtils; + + var allMenus = [],//存储所有快捷菜单 + timeID, + isSubMenuShow = false;//是否有子pop显示 + + var ShortCutMenu = UI.ShortCutMenu = function (options) { + this.initOptions (options); + this.initShortCutMenu (); + }; + + ShortCutMenu.postHide = hideAllMenu; + + ShortCutMenu.prototype = { + isHidden : true , + SPACE : 5 , + initShortCutMenu : function () { + this.items = this.items || []; + this.initUIBase (); + this.initItems (); + this.initEvent (); + allMenus.push (this); + } , + initEvent : function () { + var me = this, + doc = me.editor.document; + + domUtils.on (doc , "mousemove" , function (e) { + if (me.isHidden === false) { + //有pop显示就不隐藏快捷菜单 + if (me.getSubMenuMark () || me.eventType == "contextmenu") return; + + + var flag = true, + el = me.getDom (), + wt = el.offsetWidth, + ht = el.offsetHeight, + distanceX = wt / 2 + me.SPACE,//距离中心X标准 + distanceY = ht / 2,//距离中心Y标准 + x = Math.abs (e.screenX - me.left),//离中心距离横坐标 + y = Math.abs (e.screenY - me.top);//离中心距离纵坐标 + + clearTimeout (timeID); + timeID = setTimeout (function () { + if (y > 0 && y < distanceY) { + me.setOpacity (el , "1"); + } else if (y > distanceY && y < distanceY + 70) { + me.setOpacity (el , "0.5"); + flag = false; + } else if (y > distanceY + 70 && y < distanceY + 140) { + me.hide (); + } + + if (flag && x > 0 && x < distanceX) { + me.setOpacity (el , "1") + } else if (x > distanceX && x < distanceX + 70) { + me.setOpacity (el , "0.5") + } else if (x > distanceX + 70 && x < distanceX + 140) { + me.hide (); + } + }); + } + }); + + //ie\ff下 mouseout不准 + if (browser.chrome) { + domUtils.on (doc , "mouseout" , function (e) { + var relatedTgt = e.relatedTarget || e.toElement; + + if (relatedTgt == null || relatedTgt.tagName == "HTML") { + me.hide (); + } + }); + } + + me.editor.addListener ("afterhidepop" , function () { + if (!me.isHidden) { + isSubMenuShow = true; + } + }); + + } , + initItems : function () { + if (utils.isArray (this.items)) { + for (var i = 0, len = this.items.length ; i < len ; i++) { + var item = this.items[i].toLowerCase (); + + if (UI[item]) { + this.items[i] = new UI[item] (this.editor); + this.items[i].className += " edui-shortcutsubmenu "; + } + } + } + } , + setOpacity : function (el , value) { + if (browser.ie && browser.version < 9) { + el.style.filter = "alpha(opacity = " + parseFloat (value) * 100 + ");" + } else { + el.style.opacity = value; + } + } , + getSubMenuMark : function () { + isSubMenuShow = false; + var layerEle = uiUtils.getFixedLayer (); + var list = domUtils.getElementsByTagName (layerEle , "div" , function (node) { + return domUtils.hasClass (node , "edui-shortcutsubmenu edui-popup") + }); + + for (var i = 0, node ; node = list[i++] ;) { + if (node.style.display != "none") { + isSubMenuShow = true; + } + } + return isSubMenuShow; + } , + show : function (e , hasContextmenu) { + var me = this, + offset = {}, + el = this.getDom (), + fixedlayer = uiUtils.getFixedLayer (); + + function setPos (offset) { + if (offset.left < 0) { + offset.left = 0; + } + if (offset.top < 0) { + offset.top = 0; + } + el.style.cssText = "position:absolute;left:" + offset.left + "px;top:" + offset.top + "px;"; + } + + function setPosByCxtMenu (menu) { + if (!menu.tagName) { + menu = menu.getDom (); + } + offset.left = parseInt (menu.style.left); + offset.top = parseInt (menu.style.top); + offset.top -= el.offsetHeight + 15; + setPos (offset); + } + + + me.eventType = e.type; + el.style.cssText = "display:block;left:-9999px"; + + if (e.type == "contextmenu" && hasContextmenu) { + var menu = domUtils.getElementsByTagName (fixedlayer , "div" , "edui-contextmenu")[0]; + if (menu) { + setPosByCxtMenu (menu) + } else { + me.editor.addListener ("aftershowcontextmenu" , function (type , menu) { + setPosByCxtMenu (menu); + }); + } + } else { + offset = uiUtils.getViewportOffsetByEvent (e); + offset.top -= el.offsetHeight + me.SPACE; + offset.left += me.SPACE + 20; + setPos (offset); + me.setOpacity (el , 0.2); + } + + + me.isHidden = false; + me.left = e.screenX + el.offsetWidth / 2 - me.SPACE; + me.top = e.screenY - (el.offsetHeight / 2) - me.SPACE; + + if (me.editor) { + el.style.zIndex = me.editor.container.style.zIndex * 1 + 10; + fixedlayer.style.zIndex = el.style.zIndex - 1; + } + } , + hide : function () { + if (this.getDom ()) { + this.getDom ().style.display = "none"; + } + this.isHidden = true; + } , + postRender : function () { + if (utils.isArray (this.items)) { + for (var i = 0, item ; item = this.items[i++] ;) { + item.postRender (); + } + } + } , + getHtmlTpl : function () { + var buff; + if (utils.isArray (this.items)) { + buff = []; + for (var i = 0 ; i < this.items.length ; i++) { + buff[i] = this.items[i].renderHtml (); + } + buff = buff.join (""); + } else { + buff = this.items; + } + + return '
    ' + + buff + + '
    '; + } + }; + + utils.inherits (ShortCutMenu , UIBase); + + function hideAllMenu (e) { + var tgt = e.target || e.srcElement, + cur = domUtils.findParent (tgt , function (node) { + return domUtils.hasClass (node , "edui-shortcutmenu") || domUtils.hasClass (node , "edui-popup"); + } , true); + + if (!cur) { + for (var i = 0, menu ; menu = allMenus[i++] ;) { + menu.hide () + } + } + } + + domUtils.on (document , 'mousedown' , function (e) { + hideAllMenu (e); + }); + + domUtils.on (window , 'scroll' , function (e) { + hideAllMenu (e); + }); + +}) (); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/splitbutton.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/splitbutton.js new file mode 100644 index 000000000..cbc7f1171 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/splitbutton.js @@ -0,0 +1,87 @@ +///import core +///import uicore +///import ui/stateful.js +(function (){ + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + domUtils = baidu.editor.dom.domUtils, + UIBase = baidu.editor.ui.UIBase, + Stateful = baidu.editor.ui.Stateful, + SplitButton = baidu.editor.ui.SplitButton = function (options){ + this.initOptions(options); + this.initSplitButton(); + }; + SplitButton.prototype = { + popup: null, + uiName: 'splitbutton', + title: '', + initSplitButton: function (){ + this.initUIBase(); + this.Stateful_init(); + var me = this; + if (this.popup != null) { + var popup = this.popup; + this.popup = null; + this.setPopup(popup); + } + }, + _UIBase_postRender: UIBase.prototype.postRender, + postRender: function (){ + this.Stateful_postRender(); + this._UIBase_postRender(); + }, + setPopup: function (popup){ + if (this.popup === popup) return; + if (this.popup != null) { + this.popup.dispose(); + } + popup.addListener('show', utils.bind(this._onPopupShow, this)); + popup.addListener('hide', utils.bind(this._onPopupHide, this)); + popup.addListener('postrender', utils.bind(function (){ + popup.getDom('body').appendChild( + uiUtils.createElementByHtml('
    ') + ); + popup.getDom().className += ' ' + this.className; + }, this)); + this.popup = popup; + }, + _onPopupShow: function (){ + this.addState('opened'); + }, + _onPopupHide: function (){ + this.removeState('opened'); + }, + getHtmlTpl: function (){ + return '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    '; + }, + showPopup: function (){ + // 当popup往上弹出的时候,做特殊处理 + var rect = uiUtils.getClientRect(this.getDom()); + rect.top -= this.popup.SHADOW_RADIUS; + rect.height += this.popup.SHADOW_RADIUS; + this.popup.showAnchorRect(rect); + }, + _onArrowClick: function (event, el){ + if (!this.isDisabled()) { + this.showPopup(); + } + }, + _onButtonClick: function (){ + if (!this.isDisabled()) { + this.fireEvent('buttonclick'); + } + } + }; + utils.inherits(SplitButton, UIBase); + utils.extend(SplitButton.prototype, Stateful, true); + +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/stateful.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/stateful.js new file mode 100644 index 000000000..43d610fbb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/stateful.js @@ -0,0 +1,108 @@ +(function (){ + var browser = baidu.editor.browser, + domUtils = baidu.editor.dom.domUtils, + uiUtils = baidu.editor.ui.uiUtils; + + var TPL_STATEFUL = 'onmousedown="$$.Stateful_onMouseDown(event, this);"' + + ' onmouseup="$$.Stateful_onMouseUp(event, this);"' + + ( browser.ie ? ( + ' onmouseenter="$$.Stateful_onMouseEnter(event, this);"' + + ' onmouseleave="$$.Stateful_onMouseLeave(event, this);"' ) + : ( + ' onmouseover="$$.Stateful_onMouseOver(event, this);"' + + ' onmouseout="$$.Stateful_onMouseOut(event, this);"' )); + + baidu.editor.ui.Stateful = { + alwalysHoverable: false, + target:null,//目标元素和this指向dom不一样 + Stateful_init: function (){ + this._Stateful_dGetHtmlTpl = this.getHtmlTpl; + this.getHtmlTpl = this.Stateful_getHtmlTpl; + }, + Stateful_getHtmlTpl: function (){ + var tpl = this._Stateful_dGetHtmlTpl(); + // 使用function避免$转义 + return tpl.replace(/stateful/g, function (){ return TPL_STATEFUL; }); + }, + Stateful_onMouseEnter: function (evt, el){ + this.target=el; + if (!this.isDisabled() || this.alwalysHoverable) { + this.addState('hover'); + this.fireEvent('over'); + } + }, + Stateful_onMouseLeave: function (evt, el){ + if (!this.isDisabled() || this.alwalysHoverable) { + this.removeState('hover'); + this.removeState('active'); + this.fireEvent('out'); + } + }, + Stateful_onMouseOver: function (evt, el){ + var rel = evt.relatedTarget; + if (!uiUtils.contains(el, rel) && el !== rel) { + this.Stateful_onMouseEnter(evt, el); + } + }, + Stateful_onMouseOut: function (evt, el){ + var rel = evt.relatedTarget; + if (!uiUtils.contains(el, rel) && el !== rel) { + this.Stateful_onMouseLeave(evt, el); + } + }, + Stateful_onMouseDown: function (evt, el){ + if (!this.isDisabled()) { + this.addState('active'); + } + }, + Stateful_onMouseUp: function (evt, el){ + if (!this.isDisabled()) { + this.removeState('active'); + } + }, + Stateful_postRender: function (){ + if (this.disabled && !this.hasState('disabled')) { + this.addState('disabled'); + } + }, + hasState: function (state){ + return domUtils.hasClass(this.getStateDom(), 'edui-state-' + state); + }, + addState: function (state){ + if (!this.hasState(state)) { + this.getStateDom().className += ' edui-state-' + state; + } + }, + removeState: function (state){ + if (this.hasState(state)) { + domUtils.removeClasses(this.getStateDom(), ['edui-state-' + state]); + } + }, + getStateDom: function (){ + return this.getDom('state'); + }, + isChecked: function (){ + return this.hasState('checked'); + }, + setChecked: function (checked){ + if (!this.isDisabled() && checked) { + this.addState('checked'); + } else { + this.removeState('checked'); + } + }, + isDisabled: function (){ + return this.hasState('disabled'); + }, + setDisabled: function (disabled){ + if (disabled) { + this.removeState('hover'); + this.removeState('checked'); + this.removeState('active'); + this.addState('disabled'); + } else { + this.removeState('disabled'); + } + } + }; +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/tablebutton.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/tablebutton.js new file mode 100644 index 000000000..4ce1c63ce --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/tablebutton.js @@ -0,0 +1,37 @@ +///import core +///import uicore +///import ui/popup.js +///import ui/tablepicker.js +///import ui/splitbutton.js +(function (){ + var utils = baidu.editor.utils, + Popup = baidu.editor.ui.Popup, + TablePicker = baidu.editor.ui.TablePicker, + SplitButton = baidu.editor.ui.SplitButton, + TableButton = baidu.editor.ui.TableButton = function (options){ + this.initOptions(options); + this.initTableButton(); + }; + TableButton.prototype = { + initTableButton: function (){ + var me = this; + this.popup = new Popup({ + content: new TablePicker({ + editor:me.editor, + onpicktable: function (t, numCols, numRows){ + me._onPickTable(numCols, numRows); + } + }), + 'editor':me.editor + }); + this.initSplitButton(); + }, + _onPickTable: function (numCols, numRows){ + if (this.fireEvent('picktable', numCols, numRows) !== false) { + this.popup.hide(); + } + } + }; + utils.inherits(TableButton, SplitButton); + +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/tablepicker.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/tablepicker.js new file mode 100644 index 000000000..bf1c250a3 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/tablepicker.js @@ -0,0 +1,83 @@ +///import core +///import uicore +(function (){ + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + UIBase = baidu.editor.ui.UIBase; + + var TablePicker = baidu.editor.ui.TablePicker = function (options){ + this.initOptions(options); + this.initTablePicker(); + }; + TablePicker.prototype = { + defaultNumRows: 10, + defaultNumCols: 10, + maxNumRows: 20, + maxNumCols: 20, + numRows: 10, + numCols: 10, + lengthOfCellSide: 22, + initTablePicker: function (){ + this.initUIBase(); + }, + getHtmlTpl: function (){ + var me = this; + return '
    ' + + '
    ' + + '
    ' + + '' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    '; + }, + _UIBase_render: UIBase.prototype.render, + render: function (holder){ + this._UIBase_render(holder); + this.getDom('label').innerHTML = '0'+this.editor.getLang("t_row")+' x 0'+this.editor.getLang("t_col"); + }, + _track: function (numCols, numRows){ + var style = this.getDom('overlay').style; + var sideLen = this.lengthOfCellSide; + style.width = numCols * sideLen + 'px'; + style.height = numRows * sideLen + 'px'; + var label = this.getDom('label'); + label.innerHTML = numCols +this.editor.getLang("t_col")+' x ' + numRows + this.editor.getLang("t_row"); + this.numCols = numCols; + this.numRows = numRows; + }, + _onMouseOver: function (evt, el){ + var rel = evt.relatedTarget || evt.fromElement; + if (!uiUtils.contains(el, rel) && el !== rel) { + this.getDom('label').innerHTML = '0'+this.editor.getLang("t_col")+' x 0'+this.editor.getLang("t_row"); + this.getDom('overlay').style.visibility = ''; + } + }, + _onMouseOut: function (evt, el){ + var rel = evt.relatedTarget || evt.toElement; + if (!uiUtils.contains(el, rel) && el !== rel) { + this.getDom('label').innerHTML = '0'+this.editor.getLang("t_col")+' x 0'+this.editor.getLang("t_row"); + this.getDom('overlay').style.visibility = 'hidden'; + } + }, + _onMouseMove: function (evt, el){ + var style = this.getDom('overlay').style; + var offset = uiUtils.getEventOffset(evt); + var sideLen = this.lengthOfCellSide; + var numCols = Math.ceil(offset.left / sideLen); + var numRows = Math.ceil(offset.top / sideLen); + this._track(numCols, numRows); + }, + _onClick: function (){ + this.fireEvent('picktable', this.numCols, this.numRows); + } + }; + utils.inherits(TablePicker, UIBase); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/toolbar.js b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/toolbar.js new file mode 100644 index 000000000..f7f2b8655 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_src/ui/toolbar.js @@ -0,0 +1,49 @@ +(function (){ + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + UIBase = baidu.editor.ui.UIBase, + Toolbar = baidu.editor.ui.Toolbar = function (options){ + this.initOptions(options); + this.initToolbar(); + }; + Toolbar.prototype = { + items: null, + initToolbar: function (){ + this.items = this.items || []; + this.initUIBase(); + }, + add: function (item,index){ + if(index === undefined){ + this.items.push(item); + }else{ + this.items.splice(index,0,item) + } + + }, + getHtmlTpl: function (){ + var buff = []; + for (var i=0; i' + + buff.join('') + + '' + }, + postRender: function (){ + var box = this.getDom(); + for (var i=0; i
    dd

    "); +// equal(editor.getContent(), "


    dd

    ", 'hasContents判断不为空'); +// equal(editor.getContent("", function () { +// return false +// }), "", '为空'); +// setTimeout(function () { +// UE.delEditor('test1'); +// setTimeout(function () { +// start(); +// }, 50); +// }, 100); +// }, 50); +//}); +//test('', function () { +// stop(); +//}); +test('contentchange在命令调用时的触发机制', function () { + var editor = te.obj[1]; + var container = te.dom[0]; + + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + editor.ready(function () { + editor.commands['test1'] = { + execCommand: function () { + editor.body.innerHTML = '1123'; + } + }; + var count = 0; + editor.on('contentchange', function () { + count++; + }); + + editor.commands['test'] = { + execCommand: function () { + editor.execCommand('test1') + }, + ignoreContentChange: true + }; + setTimeout(function () { + editor.execCommand('test1'); + equals(count, 1); + count = 0; + editor.execCommand('test'); + equals(count, 0); + start(); + }, 200); + + }); + stop(); +}); + +test("initialStyle", function () { + if(ua.browser.gecko)return;//todo 1.4.0 + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor('ue', {initialStyle: "body{font-family: arial black;}.testCss{ color: rgb(192, 0, 0); }", initialContent: "

    测试样式,红色,字体: arial black

    ", autoHeightEnabled: false}); + editor.ready(function () { + equal(ua.formatColor(ua.getComputedStyle(editor.body.firstChild.firstChild).color), '#c00000', 'initialStyle中设置的class样式有效'); + ok(/arial black/.test(ua.getComputedStyle(editor.body.firstChild.firstChild).fontFamily), 'initialStyle中设置的body样式有效'); + setTimeout(function () { + UE.delEditor('ue'); + te.dom.push(document.getElementById('ue')); + start(); + }, 200); + }); + stop(); +}); + +test("autoSyncData:true,textarea容器(由setcontent触发的)", function () { + var div = document.body.appendChild(document.createElement('div')); + div.innerHTML = '
    '; + equal(document.getElementById('form').childNodes.length, 1, 'form里只有一个子节点'); + var editor_a = UE.getEditor('myEditor', {autoHeightEnabled: false}); + stop(); + editor_a.ready(function () { + equal(document.getElementById('form').childNodes.length, 2, 'form里有2个子节点'); + editor_a.setContent('

    设置内容autoSyncData 1

    '); + setTimeout(function () { + var form = document.getElementById('form'); + equal(form.childNodes.length, 2, '失去焦点,form里多了textarea'); + equal(form.lastChild.tagName.toLowerCase(), 'textarea', '失去焦点,form里多了textarea'); + equal(form.lastChild.value, '

    设置内容autoSyncData 1

    ', 'textarea内容正确'); + setTimeout(function () { + UE.delEditor('myEditor'); + document.getElementById('form').parentNode.removeChild(document.getElementById('form')); + document.getElementById('test1') && te.dom.push(document.getElementById('test1')); + start(); + }, 200); + }, 100); + }); +}); +test("autoSyncData:true(由blur触发的)", function () { + //todo ie8里事件触发有问题,暂用手动测 + if (ua.browser.ie > 8 || !ua.browser.ie) { + var div = document.body.appendChild(document.createElement('div')); + div.innerHTML = '
    '; + var editor_a = UE.getEditor('myEditor', {autoHeightEnabled: false}); + stop(); + editor_a.ready(function () { + editor_a.body.innerHTML = '

    设置内容autoSyncData 2

    '; + equal(document.getElementsByTagName('textarea').length, 0, '内容空没有textarea'); + ua.blur(editor_a.body); + stop(); + setTimeout(function () { + var form = document.getElementById('form'); + equal(form.childNodes.length, 2, '失去焦点,form里多了textarea'); + equal(form.lastChild.tagName.toLowerCase(), 'textarea', '失去焦点,form里多了textarea'); + equal(form.lastChild.value, '

    设置内容autoSyncData 2

    ', 'textarea内容正确'); + UE.delEditor('myEditor'); + form.parentNode.removeChild(form); + start(); + }, 200); + }); + } +}); +test("sync", function () { + var div = document.body.appendChild(document.createElement('div')); + div.innerHTML = '
    '; + var editor_a = UE.getEditor('myEditor', {autoHeightEnabled: false}); + stop(); + editor_a.ready(function () { + editor_a.body.innerHTML = '

    hello

    '; + editor_a.sync("form"); + setTimeout(function () { + var form = document.getElementById('form'); + equal(form.lastChild.value, '

    hello

    ', '同步内容正确'); + div = form.parentNode; + UE.delEditor('myEditor'); + div.parentNode.removeChild(div); + start(); + }, 100); + }); +}); +test("hide,show", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + editor.ready(function () { + equal(editor.body.getElementsByTagName('span').length, 0, '初始没有书签'); + editor.hide(); + setTimeout(function () { + equal($(editor.container).css('display'), 'none', '隐藏编辑器'); + equal(editor.body.getElementsByTagName('span').length, 1, '插入书签'); + ok(/_baidu_bookmark_start/.test(editor.body.getElementsByTagName('span')[0].id), '书签'); + editor.show(); + setTimeout(function () { + equal($(te.dom[0]).css('display'), 'block', '显示编辑器'); + var br = ua.browser.ie ? '' : '
    '; + equal(ua.getChildHTML(editor.body), '

    tool

    ', '删除书签'); + start(); + }, 50); + }, 50); + }); + stop(); +}); + +test("_setDefaultContent--focus", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + editor.ready(function () { + editor._setDefaultContent('hello'); + editor.fireEvent('focus'); + setTimeout(function () { + var br = ua.browser.ie ? '' : '
    '; + equal(ua.getChildHTML(editor.body), '

    ' + br + '

    ', 'focus'); + start(); + }, 50); + }); + stop(); +}); + +test("_setDefaultContent--firstBeforeExecCommand", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + editor.ready(function () { + editor._setDefaultContent('hello'); + editor.fireEvent('firstBeforeExecCommand'); + setTimeout(function () { + var br = ua.browser.ie ? '' : '
    '; + equal(ua.getChildHTML(editor.body), '

    ' + br + '

    ', 'firstBeforeExecCommand'); + start(); + }, 50); + }); + stop(); +}); +test("setDisabled,setEnabled", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + editor.ready(function () { + editor.setContent('

    欢迎使用ueditor!

    '); + editor.focus(); + setTimeout(function () { + var startContainer = editor.selection.getRange().startContainer.outerHTML; + var startOffset = editor.selection.getRange().startOffset; + var collapse = editor.selection.getRange().collapsed; + editor.setDisabled(); + setTimeout(function () { + equal(editor.body.contentEditable, 'false', 'setDisabled'); + equal(editor.body.firstChild.firstChild.tagName.toLowerCase(), 'span', '插入书签'); + equal($(editor.body.firstChild.firstChild).css('display'), 'none', '检查style'); + equal($(editor.body.firstChild.firstChild).css('line-height'), '0px', '检查style'); + ok(/_baidu_bookmark_start/.test(editor.body.firstChild.firstChild.id), '书签');///_baidu_bookmark_start/.test() + editor.setEnabled(); + setTimeout(function () { + equal(editor.body.contentEditable, 'true', 'setEnabled'); + equal(ua.getChildHTML(editor.body), '

    欢迎使用ueditor!

    ', '内容恢复'); + if (!ua.browser.ie || ua.browser.ie < 9) {// ie9,10改range 之后,ie9,10这里的前后range不一致,focus时是text,setEnabled后是p + equal(editor.selection.getRange().startContainer.outerHTML, startContainer, '检查range'); + } + equal(editor.selection.getRange().startOffset, startOffset, '检查range'); + equal(editor.selection.getRange().collapsed, collapse, '检查range'); + start(); + }, 50); + }, 50); + }, 50); + }); + stop(); +}); +test("render-- element", function () { + var editor = new baidu.editor.Editor({'UEDITOR_HOME_URL': '../../../', 'autoFloatEnabled': false}); + var div = document.body.appendChild(document.createElement('div')); + equal(div.innerHTML, "", "before render"); + editor.render(div); + equal(div.firstChild.tagName.toLocaleLowerCase(), 'iframe', 'check iframe'); + ok(/ueditor_/.test(div.firstChild.id), 'check iframe id'); + te.dom.push(div); +}); + +test("render-- elementid", function () { + var editor = te.obj[1]; + var div = te.dom[0]; + editor.render(div.id); + equal(div.firstChild.tagName.toLocaleLowerCase(), 'iframe', 'check iframe'); + ok(/ueditor_/.test(div.firstChild.id), 'check iframe id'); +}); + +test("render-- options", function () { + var options = {'initialContent': 'xxx
    xxx

    ', 'UEDITOR_HOME_URL': '../../../', autoClearinitialContent: false, 'autoFloatEnabled': false}; + var editor = new baidu.editor.Editor(options); + + var div = document.body.appendChild(document.createElement('div')); + editor.render(div); + /*会自动用p标签包围*/ + var space = baidu.editor.browser.ie ? ' ' : '
    '; + //策略变化,自1.2.6,div 标签都会被过滤 + stop(); + editor.ready(function () { + equal(ua.getChildHTML(editor.body), '

    xxx

    xxx

    ' + space + '

    ', 'check initialContent'); + te.dom.push(div); + start(); + }); +}); + +test('destroy', function () { +// var editor = new baidu.editor.Editor( {'autoFloatEnabled':false} ); + var editor = new UE.ui.Editor({'autoFloatEnabled': false}); + editor.key = 'ed'; + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ed'; + editor.render(div); + editor.ready(function () { + setTimeout(function () { + editor.destroy(); + equal(document.getElementById('ed').tagName.toLowerCase(), 'textarea', '容器被删掉了'); + document.getElementById('ed') && te.dom.push(document.getElementById('ed')); + start(); + }, 200); + + }); + stop(); +}); + +//test( "setup--ready event", function() { +// //todo +//} ); +// +test("testBindshortcutKeys", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + expect(1); + editor.ready(function () { + editor.addshortcutkey({ + "testBindshortcutKeys": "ctrl+67"//^C + }); + editor.commands["testbindshortcutkeys"] = { + execCommand: function (cmdName) { + ok(1, '') + }, + queryCommandState: function () { + return 0; + } + } + ua.keydown(editor.body, {keyCode: 67, ctrlKey: true}); + setTimeout(function () { + start(); + }, 200); + }); + stop(); +}); +test("getContent--转换空格,nbsp与空格相间显示", function () { + var editor = te.obj[1]; + var div = te.dom[0]; + editor.render(div); + stop(); + editor.ready(function () { + setTimeout(function () { + editor.focus(); + var innerHTML = '
    x x x    x    
    '; + editor.setContent(innerHTML); + equal(editor.getContent(), '

    x  x   x    x     

    ', "转换空格,nbsp与空格相间显示,原nbsp不变"); + setTimeout(function () { +// UE.delEditor('test1'); + start(); + }, 100); + }, 100); + }); +}); + +test('getContent--参数为函数', function () { + var editor = te.obj[1]; + var div = te.dom[0]; + editor.render(div); + stop(); + editor.ready(function () { + editor.focus(); + editor.setContent("


    dd

    "); + equal(editor.getContent(), "


    dd

    ", 'hasContents判断不为空'); + equal(editor.getContent(function () { + return false + }), "", '为空'); + setTimeout(function () { +// UE.delEditor('test1'); + setTimeout(function () { + start(); + }, 50); + }, 100); + }); +}); + +test('getContent--2个参数,第一个参数为参数为函数', function () { + var editor = te.obj[1]; + var div = te.dom[0]; + editor.render(div); + stop(); + editor.ready(function () { + editor.focus(); + editor.setContent("


    dd

    "); + equal(editor.getContent(), "


    dd

    ", 'hasContents判断不为空'); + equal(editor.getContent("", function () { + return false + }), "", '为空'); + setTimeout(function () { +// UE.delEditor('test1'); +// setTimeout(function () { + start(); +// }, 50); + }, 100); + }); +}); + +/*ie自动把左边的空格去掉,所以就不测这个了*/ +//test( "getContent--空格不会被去掉", function() { +// var editor = te.obj[1]; +// var div = te.dom[0]; +// editor.render( div ); +// editor.focus(); +// var innerHTML = '你好 '; +// editor.setContent( innerHTML ); +// equal( editor.getContent().toLowerCase(), '

    你好

    ', "删除不可见字符" ); +//} ); +test("setContent", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + stop(); + editor.ready(function () { + editor.focus(); + expect(2); + editor.addListener("beforesetcontent", function () { + ok(true, "beforesetcontent"); + }); + editor.addListener("aftersetcontent", function () { + ok(true, "aftersetcontent"); + }); + var html = 'xxem
    xxxx
    '; + editor.setContent(html); + var div_new = document.createElement('div'); + div_new.innerHTML = '

    xxem

    xxxx
    '; + var div2 = document.createElement('div'); + div2.innerHTML = editor.body.innerHTML; + ua.haveSameAllChildAttribs(div2, div_new, 'check contents'); + start(); + }); +}); + +test("setContent 追加", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + stop(); + editor.ready(function () { + editor.focus(); + expect(2); + editor.addListener("beforesetcontent", function () { + ok(true, "beforesetcontent"); + }); + editor.addListener("aftersetcontent", function () { + ok(true, "aftersetcontent"); + }); + var html = 'xxem
    xxxx
    '; + editor.setContent(html); + var div_new = document.createElement('div'); + div_new.innerHTML = '

    xxem

    xxxx
    '; + var div2 = document.createElement('div'); + div2.innerHTML = editor.body.innerHTML; + ua.haveSameAllChildAttribs(div2, div_new, 'check contents'); + start(); + }, 50); +}); +//test( "focus", function() { +// var editor = te.obj[1]; +// expect( 1 ); +// /*设置onfocus事件,必须同步处理,否则在ie下onfocus会在用例执行结束后才会触发*/ +// stop(); +// editor.window.onfocus = function() { +// ok( true, 'onfocus event dispatched' ); +// start(); +// }; +// editor.focus(); +//} ); +test("focus(false)", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + stop(); + editor.ready(function () { + editor.setContent("

    hello1

    hello2

    "); + setTimeout(function () { + editor.focus(false); + setTimeout(function () { + + var range = editor.selection.getRange(); + equal(range.startOffset, 0, "focus(false)焦点在最前面"); + equal(range.endOffset, 0, "focus(false)焦点在最前面"); + if (ua.browser.gecko||ua.browser.webkit) { + equal(range.startContainer, editor.body.firstChild, "focus(false)焦点在最前面"); + equal(range.collapsed, true, "focus(false)焦点在最前面"); + } + else { + equal(range.startContainer, editor.body.firstChild.firstChild, "focus(false)焦点在最前面"); + equal(range.endContainer, editor.body.firstChild.firstChild, "focus(false)焦点在最前面"); + } + start(); + }, 200); + }, 100); + }); +}); + +test("focus(true)", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + stop(); + editor.ready(function () { + editor.setContent("

    hello1

    hello2

    "); + setTimeout(function () { + + editor.focus(true); + setTimeout(function () { + + if (ua.browser.gecko||ua.browser.webkit) { + equal(editor.selection.getRange().startContainer, editor.body.lastChild, "focus( true)焦点在最后面"); + equal(editor.selection.getRange().endContainer, editor.body.lastChild, "focus( true)焦点在最后面"); + equal(editor.selection.getRange().startOffset, editor.body.lastChild.childNodes.length, "focus( true)焦点在最后面"); + equal(editor.selection.getRange().endOffset, editor.body.lastChild.childNodes.length, "focus( true)焦点在最后面"); + } + else { + equal(editor.selection.getRange().startContainer, editor.body.lastChild.lastChild, "focus( true)焦点在最后面"); + equal(editor.selection.getRange().endContainer, editor.body.lastChild.lastChild, "focus( true)焦点在最后面"); + equal(editor.selection.getRange().startOffset, editor.body.lastChild.lastChild.length, "focus( true)焦点在最后面"); + equal(editor.selection.getRange().endOffset, editor.body.lastChild.lastChild.length, "focus( true)焦点在最后面"); + } + start(); + }, 200); + }, 100); + + }); +}); + +test("isFocus()", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + stop(); + editor.ready(function () { + editor.focus(); + setTimeout(function () { + ok(editor.isFocus()); + start(); + }, 200); + }); +}); + +test("blur()", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + stop(); + editor.ready(function () { + editor.focus(); + ok(editor.isFocus()); + editor.blur(); + ok(!editor.isFocus()); + editor.blur();//多次使用不报错 + ok(!editor.isFocus()); + start(); + }); +}); +test("_initEvents,_proxyDomEvent--click", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + stop(); + editor.ready(function () { + editor.focus(); + expect(1); + stop(); + editor.addListener('click', function () { + ok(true, 'click event dispatched'); + start(); + }); + ua.click(editor.document); + }); +}); + +//test("_initEvents,_proxyDomEvent--focus", function() { +// var editor = te.obj[1]; +// +// expect(1); stop(); +// editor.addListener('focus', function() { +// ok(true, 'focus event dispatched'); +// start(); +// }); +// editor.setContent("

    hello1

    hello2

    "); +// editor.focus(); +//}); + +////TODO +//test( "_selectionChange--测试event是否被触发", function() { +// var editor = te.obj[1]; +// var div = te.dom[0]; +// editor.render( div ); +// editor.focus(); +// expect( 2 ); +// stop(); +// editor.addListener( 'beforeselectionchange', function() { +// ok( true, 'before selection change' ); +// } ); +// editor.addListener( 'selectionchange', function() { +// ok( true, 'selection changed' ); +// } ); +// +// ua.mousedown( editor.document, {clientX:0,clientY:0} ); +// setTimeout( function() { +// ua.mouseup( editor.document, {clientX:0,clientY:0} ); +// }, 50 ); +// +// /*_selectionChange有一定的延时才会触发,所以需要等一会*/ +// setTimeout( function() { +// start(); +// }, 200 ); +//} ); + +//test("_selectionChange--fillData", function() { +// var editor = te.obj[1]; +// var div = te.dom[0]; +// editor.focus(); +// //TODO fillData干嘛用的 +//}); + +/*按钮高亮、正常和灰色*/ +test("queryCommandState", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + stop(); + editor.ready(function () { + editor.focus(); + editor.setContent("

    xxxxxx

    "); + var p = editor.document.getElementsByTagName('p')[0]; + var r = new baidu.editor.dom.Range(editor.document); + r.setStart(p.firstChild, 0).setEnd(p.firstChild, 1).select(); + equal(editor.queryCommandState('bold'), 1, '加粗状态为1'); + r.setStart(p, 1).setEnd(p, 2).select(); + setTimeout(function () { + equal(editor.queryCommandState('bold'), 0, '加粗状态为0'); + start(); + }, 100); + }); +}); +test("queryCommandValue", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + stop(); + editor.ready(function () { + editor.focus(); + editor.setContent('

    xxx

    '); + var range = new baidu.editor.dom.Range(editor.document); + var p = editor.document.getElementsByTagName("p")[0]; + range.selectNode(p).select(); + equal(editor.queryCommandValue('justify'), 'left', 'text align is left'); + start(); + }); +}); +test("execCommand", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + stop(); + editor.ready(function () { + editor.focus(); + editor.setContent("

    xx

    xxx

    "); + var doc = editor.document; + var range = new baidu.editor.dom.Range(doc); + var p = doc.getElementsByTagName('p')[1]; + range.setStart(p, 0).setEnd(p, 1).select(); + editor.execCommand('justify', 'right'); + equal($(p).css('text-align'), 'right', 'execCommand align'); + /*给span加style不会重复添加span*/ + range.selectNode(p).select(); + editor.execCommand("forecolor", "red"); + /*span发生了变化,需要重新获取*/ + + var span = doc.getElementsByTagName('span')[0]; + equal(span.style['color'], 'red', 'check execCommand color'); + var div_new = document.createElement('div'); + div_new.innerHTML = '

    xx

    xxx

    '; + + var div1 = document.createElement('div'); + div1.innerHTML = editor.body.innerHTML; + ok(ua.haveSameAllChildAttribs(div_new, div1), 'check style'); + start(); + }); +}); + +test("hasContents", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + stop(); + editor.ready(function () { + editor.focus(); + editor.setContent(''); + ok(!editor.hasContents(), "have't content"); + editor.setContent("xxx"); + ok(editor.hasContents(), "has contents"); + editor.setContent('


    '); + ok(!editor.hasContents(), '空p认为是空'); + start(); + }); +}); +//test( "hasContents--只有空格", function() { +// var editor = te.obj[1]; +// editor.focus(); +// editor.setContent( ' ' ); +// ok( editor.hasContents(), "空格不被过滤" ); +// editor.setContent( "

    \t\n

    " ); +// ok( editor.hasContents(), "空格不过滤" ); +//} ); + +/*参数是对原有认为是空的标签的一个扩展,即原来的dtd认为br为空,加上这个参数可以认为br存在时body也不是空*/ +test("hasContents--有参数", function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + stop(); + editor.ready(function () { + editor.focus(); + editor.setContent('

    你好

    1. ddd

    '); + ok(editor.hasContents(['ol', 'li', 'table']), "有ol和li"); + ok(editor.hasContents(['td', 'li', 'table']), "有li"); + editor.setContent('


    '); + ok(!editor.hasContents(['']), "为空"); + ok(editor.hasContents(['br']), "不为空"); + start(); + }); +}); +//test( 'getContentTxt--文本前后中间有空格', function() { +// var editor = te.obj[1]; +// editor.focus(); +// editor.setContent( '你 好\t\n' ); +// equal( editor.getContentTxt(), '你 好\t\n' ) +// equal( editor.getContentTxt().length, 3, '3个字符,空格不会被过滤' ) +//} ); + +test('trace 1964 getPlainTxt--得到有格式的编辑器的纯文本内容', function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + stop(); + editor.ready(function () { + editor.focus(); + editor.setContent('

     

      hell\no
    hello

    '); + var html = (ua.browser.ie > 0 && ua.browser.ie < 9) ? "\n hell o\nhello\n" : "\n hello\nhello\n"; + equal(editor.getPlainTxt(), html, '得到编辑器的纯文本内容,但会保留段落格式'); + start(); + }); +}); + +test('getContentTxt--文本前后的空格,&nbs p转成空格', function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + + stop(); + editor.ready(function () { + editor.focus(); + editor.setContent('  你 好   '); + equal(editor.getContentTxt(), ' 你 好 '); + equal(editor.getContentTxt().length, 8, '8个字符,空格不被过滤'); + + start(); + }); +}); +test('getAllHtml', function () { + var editor = te.obj[1]; + var container = te.dom[0]; + $(container).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + editor.render(container); + stop(); + editor.ready(function () { + editor.focus(); + var html = editor.getAllHtml(); + ok(/iframe.css/.test(html), '引入样式'); + + start(); + }); +}); +test('2个实例采用2个配置文件', function () { + var head = document.getElementsByTagName('head')[0]; + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = '../../editor_config.js'; + head.appendChild(script); + expect(6); + stop(); + /*动态加载js需要时间,用这个ueditor.config.js覆盖默认的配置文件*/ + setTimeout(function () { + var div1 = document.body.appendChild(document.createElement('div')); + div1.id = 'div1'; + div1.style.height = '200px'; + var div2 = document.body.appendChild(document.createElement('div')); + div2.id = 'div2'; + var editor1 = UE.getEditor('div1', {'UEDITOR_HOME_URL': '../../../', 'initialContent': '欢迎使用ueditor', 'autoFloatEnabled': false}); + editor1.ready(function () { + var editor2 = UE.getEditor('div2', UEDITOR_CONFIG2); + editor2.ready(function () { + //1.2.6 高度是iframe容器的高度 + equal(editor1.ui.getDom('iframeholder').style.height, '200px', '编辑器高度为200px'); + equal(editor2.ui.getDom('iframeholder').style.height, '400px', '自定义div高度为400px'); + var html = UEDITOR_CONFIG2.initialContent; + ua.checkHTMLSameStyle(html, editor2.document, editor2.body.firstChild, '初始内容为自定制的'); + equal(editor2.options.enterTag, 'br', 'enterTag is br'); + html = '欢迎使用ueditor'; + equal(html, editor1.body.firstChild.innerHTML, '内容和ueditor.config一致'); + equal(editor1.options.enterTag, 'p', 'enterTag is p'); + setTimeout(function () { + UE.delEditor('div1'); + UE.delEditor('div2'); + document.getElementById('div1') && te.dom.push(document.getElementById('div1')); + document.getElementById('div2') && te.dom.push(document.getElementById('div2')); + start(); + }, 500); + }); + }); + }, 300); +}); +test('绑定事件', function () { + document.onmouseup = function (event) { + ok(true, "mouseup is fired"); + }; + document.onmousedown = function (event) { + ok(true, "mousedown is fired"); + }; + document.onmouseover = function (event) { + ok(true, "mouseover is fired"); + }; + document.onkeydown = function (event) { + ok(true, "keydown is fired"); + }; + document.onkeyup = function (event) { + ok(true, "keyup is fired"); + }; + var editor = new baidu.editor.Editor({'autoFloatEnabled': false}); + var div = document.body.appendChild(document.createElement('div')); + editor.render(div); + expect(5); + editor.ready(function () { + setTimeout(function () { + editor.focus(); + ua.mousedown(document.body); + ua.mouseup(document.body); + ua.mouseover(document.body); + ua.keydown(document.body, {'keyCode': 13}); + ua.keyup(document.body, {'keyCode': 13}); + setTimeout(function () { + document.getElementById('div') && te.dom.push(document.getElementById('div')); + start(); + }, 1000); + }, 50); + }); + stop(); +}); +////.fireMouseEvent(target, "contextmenu", options); +//test('dragover',function(){ +// var editor = new baidu.editor.Editor({'autoFloatEnabled':false}); +// var div = document.body.appendChild(document.createElement('div')); +// editor.render(div); +// editor.ready(function(){ +// editor.focus(); +// ua.fireMouseEvent(document.body, "dragover"); +// setTimeout(function(){ +// expect(5); +// start(); +// },100); +// }); +//}); + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/core/EventBase.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/EventBase.js new file mode 100644 index 000000000..d9181fbff --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/EventBase.js @@ -0,0 +1,194 @@ +module( "EventBase" ); + +test( "addListener,fireEvent", function() { + var editor = te.obj[1]; + var div = te.dom[0]; + expect(6); + editor.render(div); + stop(); + editor.ready(function () { + editor.focus(); + + editor.addListener("event1", function () { + ok(true, "listener1 is fired"); + }); + editor.addListener("event2", function () { + ok(true, "listener2 is fired"); + }); + editor.fireEvent("event1"); + editor.fireEvent("event2"); + + editor.fireEvent("event1 event2"); + var fun = function (type) { + ok(true, type + " is fired"); + }; + editor.addListener("event3 event4 ", fun); + editor.fireEvent("event3 event4 "); + start(); + }); +} ); +test( "on,trigger", function() { + var editor = te.obj[1]; + var div = te.dom[0]; + expect(6); + editor.render(div); + stop(); + editor.ready(function () { + editor.focus(); + + editor.on("event1", function () { + ok(true, "listener1 is fired"); + }); + editor.on("event2", function () { + ok(true, "listener2 is fired"); + }); + editor.trigger("event1"); + editor.trigger("event2"); + + editor.trigger("event1 event2"); + var fun = function (type) { + ok(true, type + " is fired"); + }; + editor.on("event3 event4 ", fun); + editor.trigger("event3 event4 "); + start(); + }); +} ); +test( "addListener,fireEvent --同一个侦听器绑定多个事件", function() { + var editor = te.obj[1]; + var div = te.dom[0]; + editor.render( div ); + expect( 2 ); + stop(); + editor.ready(function () { + editor.focus(); + editor.addListener( "event1", function() { + ok( true, "listener1 is fired" ); + } ); + editor.addListener( "event1", function() { + ok( true, "listener2 is fired" ); + } ); + editor.fireEvent( "event1" ); + start(); + }); +} ); +test( "on,trigger --同一个侦听器绑定多个事件", function() { + var editor = te.obj[1]; + var div = te.dom[0]; + editor.render( div ); + expect( 2 ); + stop(); + editor.ready(function () { + editor.focus(); + editor.on( "event1", function() { + ok( true, "listener1 is fired" ); + } ); + editor.on( "event1", function() { + ok( true, "listener2 is fired" ); + } ); + editor.trigger( "event1" ); + start(); + }); +} ); +test( "removeListener", function() { + var editor = te.obj[1]; + var div = te.dom[0]; + editor.render( div); + expect(3); + stop(); + editor.ready(function () { + editor.focus(); + function fun1() { + ok(true, "listener1 is fired"); + } + + function fun2() { + ok(true, "listener2 is fired"); + } + + editor.addListener("event1", fun1); + editor.addListener("event1", fun2); + editor.fireEvent("event1"); + + editor.removeListener("event1", fun1); + editor.fireEvent("event1"); + + function fun(type) { + ok(true, type + " is fired"); + } + + editor.addListener("event3 event4 ", fun); + editor.removeListener("event3 event4 ", fun); + editor.fireEvent("event3 event4 "); + start(); + }); +} ); + +test( "off", function() { + var editor = te.obj[1]; + var div = te.dom[0]; + editor.render( div); + expect(3); + stop(); + editor.ready(function () { + editor.focus(); + function fun1() { + ok(true, "listener1 is fired"); + } + + function fun2() { + ok(true, "listener2 is fired"); + } + + editor.on("event1", fun1); + editor.on("event1", fun2); + editor.trigger("event1"); + + editor.off("event1", fun1); + editor.trigger("event1"); + + function fun(type) { + ok(true, type + " is fired"); + } + + editor.on("event3 event4 ", fun); + editor.off("event3 event4 ", fun); + editor.trigger("event3 event4 "); + start(); + }); +} ); +test( "fireEvent--nolisteners", function() { + var editor = te.obj[1]; + var div = te.dom[0]; + editor.render(div); + stop(); + editor.ready(function () { + editor.focus(); + function fun1() { + ok(true, "listener1 is fired"); + } + + editor.fireEvent("event1");//no listener is fired + editor.addListener("event1", fun1); + editor.fireEvent("event1");//listener1 and listener2 are both fired + start(); + }); +} ); + +test( "trigger--nolisteners", function() { + var editor = te.obj[1]; + var div = te.dom[0]; + editor.render(div); + stop(); + editor.ready(function () { + editor.focus(); + function fun1() { + ok(true, "listener1 is fired"); + } + + editor.trigger("event1");//no listener is fired + editor.on("event1", fun1); + editor.trigger("event1");//listener1 and listener2 are both fired + start(); + }); +} ); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/core/Range.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/Range.js new file mode 100644 index 000000000..668287bf7 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/Range.js @@ -0,0 +1,1582 @@ +module('core.Range'); + +var checkBookmark = function (bookmark, pre, latter, id) { + same(bookmark['start'], pre, '检查start返回值'); + same(bookmark['end'], latter, '检查end返回值'); + equal(bookmark['id'], id, '检查id'); +}; + +test('init', function () { + expect(6); + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + ua.checkResult(range, null, null, null, null, true, 'for init range'); + same(range.document, document, 'check current document of range'); +}); + + +test('setStart/startEnd 自闭合元素', function () { + var range = new baidu.editor.dom.Range(document); + var div = te.dom[2]; + var img = document.createElement('img'); + div.appendChild(img); + range.setStart(img, 0); + ua.checkResult(range, div, div, 0, 0, true, "endContainer is null"); + range.setEnd(img, 0); + ua.checkResult(range, div, div, 0, 1, false, "startContainer is not null"); + range.startContainer = null; + range.setEnd(img, 0); + ua.checkResult(range, div, div, 1, 1, true, "startContainer is null"); + range.setStart(img, 0); + ua.checkResult(range, div, div, 0, 1, false, "endContainer is not null"); +}); + +test('setStart/startEnd--nodeType不为1', function () { + var range = new baidu.editor.dom.Range(document); + var div = te.dom[2]; + var text = document.createTextNode("text"); + div.appendChild(text); + range.setStart(text, 0); + ua.checkResult(range, text, text, 0, 0, true, "endContainer is null"); + range.setEnd(text, 1); + ua.checkResult(range, text, text, 0, 1, false, "startContainer is not null"); +}); + +test('setStart/setEnd--nodeType为1', function () { + var range = new baidu.editor.dom.Range(document); + var div = te.dom[2]; + range.setStart(div, 0); + ua.checkResult(range, div, div, 0, 0, true, "endContainer is null"); + range.setEnd(div, 1); + ua.checkResult(range, div, div, 0, 1, false, "startContainer is not null"); +}); +/* + * 测的内容比较多,updateCollapse,setEndPoint,setStart,setEnd,collapse + * 因为updateCollapse和setEndPoint无法通过Range对象获取, 必须间接调用验证 + */ +test('setStartAfter,setStartBefore', function () { + var div = te.dom[2]; + div.innerHTML = ''; + var span = div.firstChild; + var a = div.lastChild; + var range = new baidu.editor.dom.Range(document); + range.setStartAfter(a); + equal(range.startOffset, 2, 'check startOffset for setStartAfter--boundary testing'); + range.setStartAfter(span); + equal(range.startOffset, 1, 'check startOffset for setStartAfter'); + range.setStartBefore(span); + equal(range.startOffset, 0, 'check startOffset for setStartBefore--boundary testing'); + range.setStartBefore(a); + equal(range.startOffset, 1, 'check startOffset for setStartBefore'); + var txtNode = document.createTextNode("text"); + div.innerHTML = ""; + div.appendChild(txtNode); + range.setStartBefore(txtNode); + equal(range.startOffset, 0, 'check startOffset in text node'); +}); + +test('setEndAfter,setEndBefore', function () { + var div = te.dom[2]; + div.innerHTML = ''; + var span = div.firstChild; + var a = div.lastChild; + var range = new baidu.editor.dom.Range(document); + range.setEndAfter(a); + equal(range.endOffset, 2, 'check startOffset for setEndAfter--boundary testing'); + range.setEndAfter(span); + equal(range.endOffset, 1, 'check startOffset for setEndAfter'); + range.setEndBefore(span); + equal(range.endOffset, 0, 'check startOffset for setEndBefore--boundary testing'); + range.setEndBefore(a); + equal(range.endOffset, 1, 'check startOffset for setEndBefore'); +}); + +/* 校验collapse方法 */ +test('collapse', function () { + var text = document.createTextNode('TextNode'); + te.dom[2].appendChild(text); + var range = new baidu.editor.dom.Range(document); + range.setStart(text, 1); +// ua.checkResult(range.endContainer,range.startContainer,0) + ok(range.collapsed, 'check collapse method true--setStart'); + equal(range.startContainer, range.endContainer, 'compare startContainer and endContainer--setStart'); + range.startContainer = null; + range.setEnd(text, 0); + equal(range.startContainer, range.endContainer, 'compare startContainer and endContainer--setEnd'); + equal(range.startOffset, range.endOffset, 'compare startOffset and endOffset--setEnd'); + ok(range.collapsed, 'check collapsed is true--setEnd'); + var img = document.createElement("img"); + range.insertNode(img).selectNode(img); + equal(range.startContainer, range.endContainer, "img startContainer and endContainer is same,but startOffset and endOffset is not same"); +}); + +//TODO 空节点
    + +test('selectNode', function () { + var div = te.dom[2]; + div.innerHTML = "text!"; + div.id = 'div_id'; + var range = new baidu.editor.dom.Range(document); + range.selectNode(div); + var index = ua.getIndex(div); + ua.checkResult(range, document.body, document.body, index, index + 1, false, 'check selectNode'); +}); + +test('selectNode--空节点', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + range.selectNode(div); + var index = ua.getIndex(div); + ua.checkResult(range, document.body, document.body, index, index + 1, false, 'check selectNode'); +}); + +test('selectNode--空文本节点', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + var textNode = document.createTextNode(''); + div.appendChild(textNode); + range.selectNode(div); + var index = ua.getIndex(div); + ua.checkResult(range, document.body, document.body, index, index + 1, false, 'check selectNode'); +}); + +test('selectNodeContents', function () { + expect(15); + var div = te.dom[2]; + div.innerHTML = '
    text
    '; + var text = div.firstChild.firstChild; + var range = new baidu.editor.dom.Range(document); + range = range.selectNodeContents(div); + ua.checkResult(range, div, div, 0, 2, false, 'selectNodeContents'); + /*textNode*/ + range = range.selectNodeContents((text)); + ua.checkResult(range, text, text, 0, 4, false, 'selectNodeContents for textNode'); + div.innerHTML = 'xxxxxxxxx'; + range = new baidu.editor.dom.Range(document); + range = range.selectNodeContents(div.firstChild); + ua.checkResult(range, div.firstChild, div.firstChild, 0, 3, false, 'selectNodeContents'); + +}); + + +test('cloneRange', function () { + expect(5); + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '
    cloneRange
    '; + range.setStart(div, 0); + range.setEnd(div, 1); + var cloneRange = range.cloneRange(range); + ua.checkResult(range, cloneRange.startContainer, cloneRange.endContainer, + cloneRange.startOffset, cloneRange.endOffset, false, 'cloneRange'); +}); + + +/*循环缩进子节点,直到子节点元素类型不为1或为自闭合元素*/ +test('shrinkBoundary--not ignore end', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); +// $('#test').css('background','red'); + div.innerHTML = '
    div1_text
    a_text
    span_textdiv3_text
    '; + + var a = div.firstChild.nextSibling; + var div_2 = div.lastChild; + range.setStart(div, 1).setEnd(div, 3); + range.shrinkBoundary(); + ua.checkResult(range, a, div_2, 0, 2, false, 'shrinkBoundary--not ignore end'); +}); + +test('shrinkBoundary--ignoreEnd', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = "

    p_text

    "; + var div_child = div.firstChild; + var p = div_child.firstChild; + range.setStart(div_child, 0).setEnd(div_child, 0); + //TODO + range.shrinkBoundary(true); + ua.checkResult(range, p, p, 0, 0, true, '检查前后闭合是否一致'); +}); +test('shrinkBonudaryl', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'xxxxxxxxxxx'; + /*ignoreEnd=true*/ + range.selectNodeContents(div).shrinkBoundary(true); + + var i = div.firstChild.firstChild; + ua.checkResult(range, i, div, 0, 1, false, 'shrinkBoundary--ignoreEnd'); + /*ignoreEnd = null*/ + var b = div.firstChild; + range.selectNodeContents(div).shrinkBoundary(); + ua.checkResult(range, i, b, 0, b.childNodes.length, false, 'shrinkBoundary--not ignoreEnd'); + + div.innerHTML = 'xxxxssss'; + var u = div.getElementsByTagName('u')[0]; + range.selectNode(div.getElementsByTagName('b')[0]).shrinkBoundary(); + ua.checkResult(range, u, u, 0, 0, true, '初始startContainer和endContainer相同'); + + div.innerHTML = '
    sssss
    '; + var td = div.getElementsByTagName('td')[0]; + var table = div.firstChild; + range.setStart(table, 0).setEnd(table.getElementsByTagName('tr')[0], 1).shrinkBoundary(); + ua.checkResult(range, td, td, 0, 1, false, '初始startContainer和endContainer不同'); + + div.innerHTML = ''; + range.setStart(div, 0).setEnd(div, 1).shrinkBoundary(); + ua.checkResult(range, div, div, 0, 1, false, '子节点为自闭合元素,未能进入函数内部的逻辑'); + + div.innerHTML = 'text'; + var text = div.firstChild; + range.setStart(text, 1).setEnd(text, 4).shrinkBoundary(); + ua.checkResult(range, text, text, 1, 4, false, '节点为文本节点,未能进入函数内部的逻辑'); + + range.setStart(div, 0).setEnd(div, 1).shrinkBoundary(); + ua.checkResult(range, div, div, 0, 1, false, '子节点为文本节点,未能进入函数内部的逻辑'); + + range.setStart(div, 0).setEnd(div, 0).shrinkBoundary(); + ua.checkResult(range, div, div, 0, 0, true, '元素collapsed'); + + range.setStart(div, 0).setEnd(text, 4).shrinkBoundary(); + ua.checkResult(range, div, text, 0, 4, false, 'endContainer为文本节点'); +}); + + +/*调整边界,针对TextNode*/ +test('txtToElmBoundary', function () { + var div = te.dom[2]; + div.innerHTML = 'text_node'; + var range = new baidu.editor.dom.Range(document); + var text = div.firstChild; + /*endOffset大于text的长度*/ + range.setStart(text, 0).setEnd(text, 10); + range.txtToElmBoundary(); + ua.checkResult(range, div, div, 0, 1, false, 'endOffset大于text的长度'); + /*endOffset小于text的长度*/ + range.setStart(text, 1).setEnd(text, 4).txtToElmBoundary(); + ua.checkResult(range, text, text, 1, 4, false, 'endOffset小于text长度'); + range.setStart(text, 1).setEnd(text, 10).txtToElmBoundary(); + ua.checkResult(range, text, div, 1, 1, false, 'startOffset不为0,endOffset大于text长度'); + /*startOffset和endOffset都大于text长度*/ + range.setStart(text, 10).setEnd(text, 11).txtToElmBoundary(); + ua.checkResult(range, div, div, 1, 1, true, 'endOffset和startOffset大于text长度'); + /*startOffset和endOffset都等于0*/ + range.setStart(text, 0).setEnd(text, 0).txtToElmBoundary(); + ua.checkResult(range, text, text, 0, 0, true, 'startOffset和endOffset为0'); +}); + +/*切分文本节点*/ +test('trimBonudary', function () { + var div = te.dom[2]; + div.innerHTML = '
    td_xxxxu_text
    '; + var range = new baidu.editor.dom.Range(document); + var td = div.getElementsByTagName('td')[0]; + var td_text = td.firstChild; + /*startOffset为0,在第一个孩子节点前插入*/ + range.setStart(td_text, 0).setEnd(td_text, 5); + + range.trimBoundary(); + ua.checkResult(range, td, td, 0, 1, false, '切分文本节点'); + /*text_node被切分为2个文本节点*/ + equal(td_text.data, "td_xx", "check text of tr"); + + var u = div.getElementsByTagName('u')[0]; + var u_text = u.firstChild; + + /*startOffset=0 && collapsed=true,则不对后面的文本节点进行操作*/ + range.setStart(u_text, 0).setEnd(u_text, 0); + range.trimBoundary(); + ua.checkResult(range, u, u, 0, 0, true, 'startOffset=endOffset=0'); + + /*endOffset大于text的长度,从左边切'*/ + range.setStart(u_text, 3).setEnd(u_text, 10); + range.trimBoundary().select(); + ua.checkResult(range, u, u, 1, 2, false, 'endOffset大于text的长度'); + equal(u_text.data, 'u_t', '从左边切分textNode'); + + /*endOffset大小于text的长度,从中间切'*/ + range.setStart(u_text, 1).setEnd(u_text, 2); + range.trimBoundary(); + ua.checkResult(range, u, u, 1, 2, false, 'endOffset小于text的长度'); + equal(u_text.data, 'u', '从中间切分textNode'); + + div.innerHTML = '123456'; + range.setStart(div.firstChild, 2).setEnd(div.firstChild, 4).trimBoundary(true); + ua.checkResult(range, div, div.lastChild, 1, 2, false, 'ignoreEnd'); +}); + +/*前面尽可能往右边跳,后面尽可能往左边跳*/ +test('adjustmentBoundary--startContainer为文本节点', function () { + var range = new baidu.editor.dom.Range(document); + var div = te.dom[2]; + div.innerHTML = 'div_text

    span_text

    div_text2

    p_textem_text

    '; + var span_text = document.getElementById('span').firstChild; + var p = document.getElementById('p'); + range.setStart(span_text, 9).setEnd(p, 0); + range.adjustmentBoundary(); + ua.checkResult(range, div, div, 2, 3, false, 'startContainer为文本节点'); + +}); + +//TODO +test('adjustmentBoundary--非文本节点', function () { + var range = new baidu.editor.dom.Range(document); + var div = te.dom[2]; + div.innerHTML = 'div_text

    span_text

    div_text2

    p_textem_text

    '; + var span = document.getElementById('span'); + var p = document.getElementById('p'); + range.setStart(span, 1).setEnd(p, 0); + range.adjustmentBoundary(); + ua.checkResult(range, div, div, 2, 3, false, 'startContainer为非文本节点'); + +}); + +test('getCommonAncestor--初始startContainer和endContainer相同', function () { + var range = new baidu.editor.dom.Range(document); + var div = te.dom[2]; + div.innerHTML = "div_text

    span_text

    div_text2"; + range.setStart(div, 0).setEnd(div, 1); + /*--初始startContainer和endContainer相同*/ + var ancestor = range.getCommonAncestor(); + same(ancestor, div, '祖先节点为startContainer'); + /*文本节点*/ + var span = div.getElementsByTagName('span')[0]; + range.setStart(span.firstChild, 0).setEnd(span.firstChild, 4); + ancestor = range.getCommonAncestor(); + same(ancestor, span.firstChild, "文本节点的祖先节点"); + /*忽略文本节点*/ + ancestor = range.getCommonAncestor(true, true); + same(ancestor, span, "文本节点的祖先节点--忽略文本节点"); + + range.setStart(div, 1).setEnd(div, 2); + ancestor = range.getCommonAncestor(true, true); + same(ancestor, span.parentNode, "文本节点的祖先节点--includeSelf=true"); + range.setStart(div, 1).setEnd(div, 2); + ancestor = range.getCommonAncestor(false, true); + same(ancestor, div, "文本节点的祖先节点--includeSelf=false"); +}); + + +test('getCommonAncestor--初始startContainer和endContainer不同', function () { + var range = new baidu.editor.dom.Range(document); + var div = te.dom[2]; + div.innerHTML = "div_text

    span_text

    div_text2"; + var span = div.getElementsByTagName('span')[0]; + range.setStart(div, 0).setEnd(span, 1); + /*--初始startContainer和endContainer相同*/ + var ancestor = range.getCommonAncestor(); + same(ancestor, div, 'startContainer是endContainer的祖先'); + + range.setStart(div.firstChild, 0).setEnd(span, 1); + ancestor = range.getCommonAncestor(); + same(ancestor, div, 'startContainer和endContainer是兄弟'); +}); + +test('selectNodeContents', function () { + var div = te.dom[2]; + div.innerHTML = 'xxxxdiv_text'; + var range = new baidu.editor.dom.Range(document); + /*选中非文本节点*/ + range.selectNodeContents(div); + ua.checkResult(range, div, div, 0, 2, false, 'selectNodeContents'); + /*选中文本节点*/ + range.selectNodeContents(div.lastChild); + ua.checkResult(range, div.lastChild, div.lastChild, 0, 8, false, 'selectNodeContents--'); +}); + +test('cloneContents', function () { + var div = te.dom[2]; + div.innerHTML = 'b_textdiv_text'; +// div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var range = new baidu.editor.dom.Range(document); + var b = div.firstChild; + range.setStart(b, 1).setEnd(div, 1); + var frag = range.cloneContents(); + /*类型:xxxx||div_text("|"表示切的位置)*/ + equal(ua.getHTML(frag), '', ' 只选中一个b标签,插入空文本节点'); + + /*类型:t|_extdiv|_text("|"表示切的位置)*/ + range.setStart(b.firstChild, 1).setEnd(b.nextSibling, 3); + frag = range.cloneContents(); + equal(ua.getHTML(frag), '_textdiv', '从文本节点中间切'); + /*类型:|b_t|extdiv_text("|"表示切的位置)*/ + range.setStart(div, 0).setEnd(b.firstChild, 3); + frag = range.cloneContents(); + equal(ua.getHTML(frag), 'b_t', '选中文本的前半部分'); + /*类型:b|_textdiv_text|("|"表示切的位置)*/ + range.setStart(b.firstChild, 1).setEnd(div, 2); + frag = range.cloneContents(); + equal(ua.getHTML(frag), '_textdiv_text', '选中文本的前半部分'); + /*类型:xxxx|xxxxc22c|("|"表示切的位置)*/ + div.innerHTML = 'xxxxxxxxc22c'; + range.setStart(div.firstChild, 1).setEnd(div.lastChild, 1); + equals(ua.getHTML(range.cloneContents()), 'xxxxc22c'); +}); + +/*startContainer和endContainer为文本节点,补全后面之类的标签*/ +test('cloneContents--补全后面的标签', function () { + var div = te.dom[2]; + var r = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var first = document.getElementById('first').firstChild; + var two = document.getElementById('two').firstChild; + r.setStart(first, 1).setEnd(two, 2); + ua.checkSameHtml(ua.getHTML(r.cloneContents()), '

    irst strong strong second em strong.

    bar

    some textem textmore text

    1ab
    '); + ua.checkResult(r, first, two, 1, 2, false, 'cloneContents--补全后面的标签'); +}); + +/*startContainer和endContainer为文本节点,层级各不相同,补全前面 的之类的标签*/ +test('cloneContents--补全前面的标签', function () { + var div = te.dom[2]; + var r = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var last = document.getElementById('last').firstChild; + var two = document.getElementById('two').firstChild; + r.setStart(two, 1); + r.setEnd(last, 2); + ua.checkSameHtml(ua.getHTML(r.cloneContents()), '
    bc
    34

    te

    '); + ua.checkResult(r, two, last, 1, 2, false, 'cloneContents--补全前面的标签'); +}); + +/*startContainer和endContainer为文本节点,为兄弟节点*/ +test('cloneContents--切的部分为兄弟节点', function () { + var div = te.dom[2]; + var r = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var first = document.getElementById('first'); + + r.setStart(first.firstChild, 1).setEnd(first.lastChild, 4); + /*strong前面有空格*/ + ua.checkSameHtml(ua.getHTML(r.cloneContents()), 'irst strong strong second em str'); + ua.checkResult(r, first.firstChild, first.lastChild, 1, 4, false, 'cloneContents--startContainer和endContainer为兄弟节点'); +}); + + +test('cloneContents--切同一个文本节点', function () { + var div = te.dom[2]; + var r = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var first = document.getElementById('first').firstChild; + + r.setStart(first, 1).setEnd(first, 4); + equals(ua.getHTML(r.cloneContents()), 'irs'); + ua.checkResult(r, first, first, 1, 4, false, 'cloneContents--切同一个文本节点'); +}); + +/*startContainer和endContainer的nodeType=1*/ +test('cloneContents--startContainer和endContainer为非文本节点', function () { + var div = te.dom[2]; + var r = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var first = document.getElementById('first'); + var last = document.getElementById('last'); + r.setStart(first, 0).setEnd(last, 0); + ua.checkSameHtml(ua.getHTML(r.cloneContents()), '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    '); + ua.checkResult(r, first, last, 0, 0, false, 'cloneContents--开始和结束位置都是文本'); + + r.setStart(first, 1).setEnd(last, 1); + ua.checkSameHtml(ua.getHTML(r.cloneContents()), '

    strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabc

    '); + ua.checkResult(r, first, last, 1, 1, false, 'cloneContents--开始位置有注释'); +}); + + +test('cloneContents--完整切掉一个节点', function () { + var div = te.dom[2]; + var r = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var first = document.getElementById('first'); + r.setStart(div, 0).setEnd(div, div.childNodes.length - 1); + ua.checkSameHtml(ua.getHTML(r.cloneContents()), '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34
    '); + ua.checkResult(r, div, div, 0, div.childNodes.length - 1, false, 'cloneContents--完整切掉一个节点'); +}); + +test('cloneContents--startContainer和endContainer节点类型不同', function () { + var div = te.dom[2]; + var r = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var first = document.getElementById('first'); + var last = document.getElementById('last'); + r.setStart(first, 0).setEnd(last.firstChild, 1); + ua.checkSameHtml(ua.getHTML(r.cloneContents()), '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    t

    '); + ua.checkResult(r, first, last.firstChild, 0, 1, false, 'cloneContents--startContainer的nodeType=1,endContainer为文本节点'); + + r.setStart(first.firstChild, 1).setEnd(last, 0); + ua.checkSameHtml(ua.getHTML(r.cloneContents()), '

    irst strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    '); + ua.checkResult(r, first.firstChild, last, 1, 0, false, 'cloneContents--endContainer为文本节点,startContainer的nodeType=1'); +}); + + +test('cloneContents--endContainer为em', function () { + var div = te.dom[2]; + var r = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var traverse = document.getElementById('traverse'); + r.setStart(div, 0).setEnd(traverse, 1); + equals(ua.getHTML(r.cloneContents()), '

    first strong strong second em strong.

    bar

    some text

    '); + ua.checkResult(r, div, traverse, 0, 1, false, 'cloneContents--startContainer的nodeType=1,endContainer为b'); + r.setStart(div, 0).setEnd(traverse, 2); + equals(ua.getHTML(r.cloneContents()), '

    first strong strong second em strong.

    bar

    some textem text

    '); + ua.checkResult(r, div, traverse, 0, 2, false, 'cloneContents--startContainer的nodeType=1,endContainer为em'); +}); + + +test('cloneContents--元素闭合', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '

    p_text

    '; +// if ( baidu.editor.browser.gecko ) { + + var text = div.firstChild.firstChild; + range.setStart(text, 1).setEnd(text, 1); + equals(ua.getHTML(range.cloneContents()), 'null', '元素闭合直接返回null'); + ua.checkResult(range, text, text, 1, 1, true, 'cloneContents--startContainer的nodeType=1,endContainer为em'); + var p = div.firstChild; + range.setStart(p, 1).setEnd(p, 1); + equals(ua.getHTML(range.cloneContents()), 'null', '元素闭合直接返回null'); + ua.checkResult(range, p, p, 1, 1, true, 'cloneContents--startContainer的nodeType=1,endContainer为em'); +}); + + +test('cloneContents--自闭合元素', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'b_texti_textxxx'; + var b = div.firstChild; + range.setStart(b.firstChild, 2).setEnd(b, b.childNodes.length); + /*只能获得而不是的标签*/ + equal(ua.getHTML(range.cloneContents()), 'texti_text'); + ua.checkResult(range, b.firstChild, b, 2, b.childNodes.length, false, '选中结束位置为自闭合元素-1'); + + var i = b.firstChild.nextSibling; + range.setStart(i, 1).setEnd(b, b.childNodes.length); + equal(ua.getHTML(range.cloneContents()), ''); + ua.checkResult(range, i, b, 1, b.childNodes.length, false, '选中结束位置为自闭合元素-2'); + + range.setStart(i.firstChild, 2).setEnd(div, 2); + equal(ua.getHTML(range.cloneContents()), 'textxxx'); + ua.checkResult(range, i.firstChild, div, 2, 2, false, '选中结束位置为自闭合元素-3'); + + div.innerHTML = 'xxxxxxxi_Textxxx'; + var i_text = document.getElementById('ii').firstChild; + range.setStart(div, 0).setEnd(i_text, 2); + equals(ua.getHTML(range.cloneContents()), 'xxxxxxxi_'); + ua.checkResult(range, div, i_text, 0, 2, false, '选中结束位置为自闭合元素-4'); +}); + +test('deleteContents--删除空', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '

    p_text

    '; + var p_text = div.firstChild.firstChild; + range.setStart(p_text, 2).setEnd(p_text, 2); + range.deleteContents(); + ua.checkResult(range, p_text, p_text, 2, 2, true, '删除空'); + equal(ua.getHTML(div), '

    p_text

    ', 'div的innerHTML没有改变 '); +}); + +test('deleteContents--删除相邻节点之间的内容', function () { + var div = te.dom[2]; + var html = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + div.innerHTML = html; + var r = new baidu.editor.dom.Range(document); + var two = document.getElementById('two'); + var last = document.getElementById('last'); + r.setStart(two, 1).setEnd(last, 2); + r.deleteContents(); + ua.checkSameHtml(ua.getHTML(div), '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc

    '); + + ua.checkResult(r, div, div, 4, 4, true, '删除相邻节点的内容'); +}); + + +test('deleteContents--删除子节点', function () { + var div = te.dom[2]; + var html = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + div.innerHTML = html; + var r = new baidu.editor.dom.Range(document); + + r.setStart(div, 0).setEnd(div, 2); + r.deleteContents(); + ua.checkSameHtml(ua.getHTML(r.startContainer), '

    some textem textmore text

    1abc
    34

    textabcspan

    '); + + ua.checkResult(r, div, div, 0, 0, true, '删除子节点的内容'); +}); + + +test('deleteContents--删除同一文本节点内容', function () { + var div = te.dom[2]; + var html = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + div.innerHTML = html; + var r = new baidu.editor.dom.Range(document); + var p = div.firstChild; + var strong_text = document.getElementById('strong').firstChild; + r.setStart(strong_text, 0).setEnd(strong_text, 2); + r.deleteContents(); + equals(ua.getHTML(r.startContainer), 'rong'); + + ua.checkSameHtml(ua.getHTML(div), '

    first strong rong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '); + ua.checkResult(r, strong_text, strong_text, 0, 0, true, '删除子节点的内容'); +}); + +test('deleteContents--startContainer是endContainer父亲', function () { + var div = te.dom[2]; + var r = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + r.setStart(div, 0); + r.setEnd(document.getElementById('traverse'), 2); + r.deleteContents(); + ua.checkSameHtml(ua.getHTML(div), '

    more text

    1abc
    34

    textabcspan

    '); + ua.checkResult(r, div, div, 0, 0, true, 'startContainer是endContainer父亲'); +}); + +test('deleteContents--startContainer和endContainer为不同文本节点', function () { + var div = te.dom[2]; + var html = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + div.innerHTML = html; + var r = new baidu.editor.dom.Range(document); + var first = document.getElementById('first'); + r.setStart(first.firstChild, 1).setEnd(first.lastChild, 4); + var p = div.firstChild; + r.deleteContents(); + equals(ua.getHTML(r.startContainer), '

    fong.

    '); + ua.checkResult(r, p, p, 1, 1, true, 'startContainer和endContainer为文本节点内容'); + ua.checkSameHtml(ua.getHTML(div), '

    fong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '); + equals(ua.getHTML(r.endContainer), '

    fong.

    '); +}); + + +test('deleteContents--startContainer是endContainer后代', function () { + var div = te.dom[2]; + var html = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + div.innerHTML = html; + var r = new baidu.editor.dom.Range(document); + var em = document.getElementById('em'); + r.setStart(em, 1).setEnd(div, 3); + r.deleteContents(); + ua.checkSameHtml(ua.getHTML(r.startContainer), '

    first strong strong second em

    1abc
    34

    textabcspan

    '); + ua.checkResult(r, div, div, 1, 1, true, 'startContainer是endContainer后代'); +}); + +test('deleteContents--startContainer是文本,endContainer的nodeType=1', function () { + var div = te.dom[2]; + var html = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + div.innerHTML = html; + var r = new baidu.editor.dom.Range(document); + var em = document.getElementById('em').firstChild; + var two = document.getElementById('two'); + r.setStart(em, 1).setEnd(two, 0); + r.deleteContents(); + ua.checkSameHtml(ua.getHTML(r.startContainer), '

    first strong strong second e

    abc
    34

    textabcspan

    '); + ua.checkResult(r, div, div, 1, 1, true, 'startContainer是文本,endContainer的nodeType=1'); +}); + + +/*startContainer和endContainer为文本节点,补全后面
    之类的标签*/ +test('extractContents--补全后面的标签', function () { + var div = te.dom[2]; + var r = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var first = document.getElementById('first').firstChild; + var two = document.getElementById('two').firstChild; + r.setStart(first, 1).setEnd(two, 2); + ua.checkSameHtml(ua.getHTML(r.extractContents()), '

    irst strong strong second em strong.

    bar

    some textem textmore text

    1ab
    '); + ua.checkSameHtml(ua.getHTML(r.startContainer), '

    f

    c
    34

    textabcspan

    '); + ua.checkResult(r, div, div, 1, 1, true, 'startContainer--补全后面的标签'); +}); + +/*startContainer和endContainer为文本节点,层级各不相同,补全前面 的之类的标签*/ +test('extractContents--补全前面的标签', function () { + var div = te.dom[2]; + var r = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var last = document.getElementById('last').firstChild; + var two = document.getElementById('two').firstChild; + r.setStart(two, 1).setEnd(last, 2); + ua.checkSameHtml(ua.getHTML(r.extractContents()), '
    bc
    34

    te

    '); + ua.checkSameHtml(ua.getHTML(r.startContainer), '

    first strong strong second em strong.

    bar

    some textem textmore text

    1a

    xtabcspan

    '); + ua.checkResult(r, div, div, 4, 4, true, 'startContainer--补全前面的标签'); +}); + +/*startContainer和endContainer为文本节点,为兄弟节点*/ +test('extractContents--切的部分为兄弟节点', function () { + var div = te.dom[2]; + var r = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var first = document.getElementById('first'); + + r.setStart(first.firstChild, 1).setEnd(first.lastChild, 4); + /*strong前面有空格*/ + ua.checkSameHtml(ua.getHTML(r.extractContents()), 'irst strong strong second em str'); + ua.checkSameHtml(ua.getHTML(r.startContainer), '

    fong.

    ', 'check startContainer html'); + ua.checkResult(r, first, first, 1, 1, true, 'startContainer--startContainer和endContainer为兄弟节点'); +}); + + +test('extractContents--切同一个文本节点', function () { + var div = te.dom[2]; + var r = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var first = document.getElementById('first').firstChild; + + r.setStart(first, 1).setEnd(first, 4); + equals(ua.getHTML(r.extractContents()), 'irs'); + equal(ua.getHTML(r.startContainer), 'ft'); + ua.checkResult(r, first, first, 1, 1, true, 'startContainer--切同一个文本节点'); +}); + +/*startContainer和endContainer的nodeType=1*/ +test('extractContents--startContainer和endContainer为非文本节点', function () { + var div = te.dom[2]; + var r = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var first = document.getElementById('first'); + var last = document.getElementById('last'); + r.setStart(first, 0).setEnd(last, 0); + ua.checkSameHtml(ua.getHTML(r.extractContents()), '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    '); + ua.checkSameHtml(ua.getHTML(r.startContainer), '

    textabcspan

    '); + ua.checkResult(r, div, div, 1, 1, true, 'cloneContents--开始和结束位置都是文本'); + + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + first = document.getElementById('first'); + last = document.getElementById('last'); + r.setStart(first, 2).setEnd(last, 1); + ua.checkSameHtml(ua.getHTML(r.extractContents()), '

    strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabc

    ', '检查得到的contents'); + + ua.checkSameHtml(ua.getHTML(r.startContainer), '

    first

    span

    ', '检查切除后'); + ua.checkResult(r, div, div, 1, 1, true, 'extractContents--开始位置有注释'); +}); + + +test('extractContents--完整切掉一个节点', function () { + var div = te.dom[2]; + var r = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var first = document.getElementById('first'); + r.setStart(div, 0).setEnd(div, div.childNodes.length - 1); + ua.checkSameHtml(ua.getHTML(r.extractContents()), '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34
    '); + ua.checkSameHtml(ua.getHTML(r.startContainer), '

    textabcspan

    '); + ua.checkResult(r, div, div, 0, 0, true, 'extractContents--完整切掉一个节点'); +}); + +test('extractContents--元素闭合', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '

    p_text

    '; + var text = div.firstChild.firstChild; + range.setStart(text, 1).setEnd(text, 1); + equals(ua.getHTML(range.extractContents()), 'null', '元素闭合直接返回null'); + equal(ua.getHTML(range.startContainer), 'p_text'); + ua.checkResult(range, text, text, 1, 1, true, 'extractContents--startContainer的nodeType=1,endContainer为em'); + var p = div.firstChild; + range.setStart(p, 1).setEnd(p, 1); + equals(ua.getHTML(range.extractContents()), 'null', '元素闭合直接返回null'); + equal(ua.getHTML(range.startContainer), '

    p_text

    '); + ua.checkResult(range, p, p, 1, 1, true, 'extractContents--startContainer的nodeType=1,endContainer为em'); +}); + + +test('extractContents--自闭合元素', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + var inner = 'b_texti_textxxx'; + div.innerHTML = inner; + var b = div.firstChild; + + div.innerHTML = inner; + b = div.firstChild; + range.setStart(b.firstChild, 2).setEnd(b, b.childNodes.length); + /*只能获得而不是的标签*/ + equal(ua.getHTML(range.extractContents()), 'texti_text', '获取带有的内容'); + equal(ua.getHTML(range.startContainer), 'b_', '检查切除元素后'); + ua.checkResult(range, b, b, 1, 1, true, '选中结束位置为自闭合元素'); +}); + +test('extractContents', function () { + function trans(range) { + return { + startContainer:range.startContainer.id, + startOffset:range.startOffset, + endContainer:range.endContainer.id, + endOffset:range.endOffset + }; + } + + var div = te.dom[2]; + + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var r = range; + + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + + r.setStart(document.getElementById('test'), 0); + r.setEnd(document.getElementById('traverse'), 2); + + ua.checkSameHtml(ua.getHTML(r.extractContents()), '

    first strong strong second em strong.

    bar

    some textem text

    '); + ua.checkSameHtml(ua.getHTML(r.startContainer), '

    more text

    1abc
    34

    textabcspan

    '); + equals(r.startOffset, 0); + equals(r.endContainer.nodeType, 1); + equals(r.endOffset, 0); + ua.checkSameHtml(ua.getHTML(r.endContainer), '

    more text

    1abc
    34

    textabcspan

    '); + ua.checkSameHtml(ua.getHTML(document.getElementById('test')), '

    more text

    1abc
    34

    textabcspan

    '); + equals(r.collapsed, true); +}); + +/*只要邻居节点不是块元素就左扩或右扩*/ +test('enlarge--文本节点左边扩到body', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabc

    div_text

    '; + var first = document.getElementById('first').firstChild; + var last = document.getElementById('last').firstChild; + range.setStart(first, 1).setEnd(last, 2); + range.enlarge(true); + /*左边的文本节点是左边第一个节点,所以一直左扩直到body,右边的文本节点右边有兄弟,因此只扩到第一个块元素祖先*/ + ua.checkResult(range, document.body, div, ua.getIndex(div), 5, false, '左边扩到body'); + +}); + +test('enlarge--文本节点右边扩到body', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '

    xxx

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var strong = document.getElementById('strong').firstChild; + var span = document.getElementById('last').lastChild.firstChild; + range.setStart(strong, 1).setEnd(span, 2); + range.enlarge(true); + /*右边的文本节点是右边最后一个节点,所以一直右扩直到body,左边的文本节点左边边有块元素兄弟,因此只扩到第一个块元素祖先*/ + ua.checkResult(range, div.firstChild, document.body, 1, ua.getIndex(div) + 1, false, '右边扩到body'); + +}); + +test('enlarge--文本节点左右边扩到body', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var first = document.getElementById('first').firstChild; + var span = document.getElementById('last').lastChild.firstChild; + range.setStart(first, 1).setEnd(span, 2); + range.enlarge(true); + /*右边的文本节点是右边最后一个节点,所以一直右扩直到body,左边的文本节点是左边第一个节点,所以一直左扩直到body*/ + ua.checkResult(range, document.body, document.body, ua.getIndex(div), ua.getIndex(div) + 1, false, '左右边扩到body'); + +}); + +test('enlarge--startContainer和endContainer的nodeType为1', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strongstrong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + range.setStart(div, 0).setEnd(div, 2); + range.enlarge(true); + ua.checkResult(range, document.body, div, ua.getIndex(div), 2, false, '左边扩到块元素父节点,右边扩到body'); + +}); + +test('enlarge--左边非块元素节点', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var strong = document.getElementById('strong'); + var table = div.getElementsByTagName('table')[0]; + range.setStart(strong, 0).setEnd(table, 1); + range.enlarge(true); + ua.checkResult(range, document.body, div, ua.getIndex(div), 4, false, '左边扩到块元素父节点,右边扩到父节点'); + +}); + +test('enlarge--左右属于同一非块元素节点', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var strong = document.getElementById('strong'); + range.setStart(strong, 0).setEnd(strong, 1); + range.enlarge(true); + ua.checkResult(range, document.body, div, ua.getIndex(div), 1, false, '左边扩到body'); + + /*文本节点*/ + var strong_text = strong.firstChild; + range.setStart(strong_text, 2).setEnd(strong_text, 3); + range.enlarge(true); + ua.checkResult(range, document.body, div, ua.getIndex(div), 1, false, '左右均扩到第一个块元素祖先节点'); +}); + +test('enlarge--isBlock为null', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'xxxxxxxxxxxxx'; + + range.selectNodeContents(div.getElementsByTagName('i')[0]); + range.enlarge(); + ua.checkResult(range, div, div.lastChild, 1, 1, false, 'isBlock为null'); + +}); + +test('enlarge--stopFn', function () { + var div = te.dom[2]; + var stopFn = function (container) { + if (container.tagName.toLowerCase() == 'table') + return true; + return false; + }; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '

    first strong strong second em strong.

    bar

    some textem textmore text

    1abc
    34

    textabcspan

    '; + var strong = document.getElementById('strong'); + var table = div.getElementsByTagName('table')[0]; + range.setStart(strong, 0).setEnd(table, 1); + range.enlarge(true, stopFn); + ua.checkResult(range, document.body, table, ua.getIndex(div), 1, false, '左边扩到块元素父节点,右边不扩(stopFn为false)'); + +}); + + +//test( 'enlarge--闭合特殊情况,有歧义', function() { +// var div = te.dom[2]; +// var range = new baidu.editor.dom.Range( document ); +// div.innerHTML = '

    p_text

    '; +// var p = div.firstChild; +// range.setStart( p.firstChild, 0 ).setEnd( p.firstChild, 3 ).trimBoundary(); +// range.setStart( p, 1 ).setEnd( p, 1 ); +// range.enlarge( true ); +// +// //TODO +//} ); + +test('enlarge--闭合', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'xxx

    xxxxx

    xxxxxxxxxxxxxxxxx|xxx

    bbbbb

    xx'; + range.setStart(div.getElementsByTagName('b')[0], 2).collapse(true); + + range.enlarge(true); + ua.checkResult(range, div, div, 2, 6, false, "初始为闭合,文本父节点为非块元素"); + + div.innerHTML = '
    xxxx
    '; + range.setStart(div.firstChild.nextSibling, 2).collapse(true) + range.enlarge(true); + ua.checkResult(range, div, div, 1, 2, false, "初始为闭合,文本父节点为块元素"); +}); + + +test('insertNode--文本中插入', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'div_text1

    p_text

    xxxem_textxxxxxxxxxxx|xxx

    bbbbb

    text2_div'; + var p_text = div.firstChild.nextSibling.firstChild; + range.setStart(p_text, 1).setEnd(p_text, 2); + /*插入块元素*/ + var new_div = document.createElement('div'); + range.insertNode(new_div); + + ua.checkResult(range, p_text.parentNode, new_div.nextSibling, 1, 1, false, '插入div'); + + /*插入文本节点,原来闭合*/ + var em_text = div.getElementsByTagName('em')[0].firstChild; + range.setStart(em_text, 0).setEnd(em_text, 0); + range.insertNode(document.createTextNode('new_text')); + ua.checkResult(range, em_text.parentNode, em_text.parentNode, 0, 1, false, '闭合情况下插入文本'); + /*插入inline元素*/ + range.setStart(div.firstChild, 1).setEnd(div.lastChild, 1); + range.insertNode(document.createElement('i')); + ua.checkResult(range, div, div.lastChild, 1, 1, false, '插入inline元素'); +}); + +test('inserNode--块元素中插入', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'div_text1

    p_text

    xxxem_textxxxxxxxxxxx|xxx

    bbbbb

    text2_div'; +// var p_text = div.firstChild.nextSibling.firstChild; + range.setStart(div, 1).setEnd(div.lastChild, 2); + /*插入块元素*/ + var new_div = document.createElement('div'); + range.insertNode(new_div); + + ua.checkResult(range, div, div.lastChild, 1, 2, false, '插入div'); + +}); + +test('insertNode--插入的节点为endContainer孩子', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'xxx

    xxxxx

    xxxxxxxxxxxxxxxxx|xxx

    bbbbb

    xx'; + var length = div.childNodes.length; + range.setStart(div, 1).setEnd(div, length); + var new_div = document.createElement('div'); + new_div.innerHTML = 'xxxx
    div_text
    i_textem_textxxxx'; + range.insertNode(new_div); + ua.checkResult(range, div, div, 1, length + 1, false, '插入节点为endContainer的孩子'); + equal(ua.getHTML(div), '
    xxx
    xxxx
    div_text
    i_textem_textxxxx

    xxxxx

    xxxxxxxxxxxxxxxxx|xxx

    bbbbb

    xx
    ') +}); + +test('insertNode--插入的fragment为endContainer孩子', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + var frag = document.createDocumentFragment(); + + div.innerHTML = 'xxx

    xxxxx

    xxxxxxxxxxxxxxxxx|xxx

    bbbbb

    xx'; + var length = div.childNodes.length; + range.setStart(div, 1).setEnd(div, div.childNodes.length); + var new_div = document.createElement('div'); + frag.appendChild(new_div); + frag.appendChild(document.createTextNode('text')); + frag.appendChild(document.createElement('span')); + range.insertNode(frag); + ua.checkResult(range, div, div, 1, length + 3, false, '插入fragment为endContainer的孩子'); + equal(ua.getHTML(div), '
    xxx
    text

    xxxxx

    xxxxxxxxxxxxxxxxx|xxx

    bbbbb

    xx
    ', '比较innerHTML'); +}); + +test('createBookmark/moveToBookmark--元素不闭合', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'first_texti_textxxxxxxxspan_text

    em_textp_text

    '; + var bookmark = range.selectNode(div).createBookmark(); + ua.checkResult(range, document.body, document.body, ua.getIndex(div), ua.getIndex(div) + 1, false, "元素不闭合,创建书签"); + ok(/_baidu_bookmark_start_/.test(div.previousSibling.id), '检查div的前一个兄弟'); + ok(/_baidu_bookmark_end_/.test(div.nextSibling.id), '检查div的后一个兄弟'); + /*moveToBookmark*/ + range.moveToBookmark(bookmark); + ua.checkResult(range, document.body, document.body, ua.getIndex(div), ua.getIndex(div) + 1, false, "元素不闭合,删除书签"); + ok(!/_baidu_bookmark_start_/.test(div.previousSibling.id), '检查div的前面书签是否被删除'); + + range.setStart(div, 2).setEnd(div, 3); + var bookmark = range.createBookmark(true); + ua.checkResult(range, div, div, 3, 4, false, "元素不闭合,插入span"); + var preId = document.getElementById('span').previousSibling.id; + var latterId = document.getElementById('span').nextSibling.id; + var reg = /_baidu_bookmark_start_/; + ok(/_baidu_bookmark_start_/.test(preId), '检查前面span的id'); + ok(/_baidu_bookmark_end_/.test(latterId), '检查后面span的id'); + checkBookmark(bookmark, preId, latterId, true); + + range.moveToBookmark(bookmark); + ua.checkResult(range, div, div, 2, 3, false, 'moveToBookmark'); + equal(ua.getHTML(div), '
    first_texti_textxxxxxxxspan_text

    em_textp_text

    '); + +}); + +test('createBookmark/moveToBookmark--span嵌套', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'first_texti_textxxxxxxxspan_text

    em_textp_text

    '; + var span = document.getElementById('span'); + range.setStart(span, 0).setEnd(span, 1); + var bookmark = range.createBookmark(); + var pre = span.firstChild; + var latter = span.lastChild; + ua.checkResult(range, span, span, 1, 2, false, 'span嵌套'); + ok(/_baidu_bookmark_start_/.test(pre.id), '检查前面span的id'); + ok(/_baidu_bookmark_end_/.test(latter.id), '检查后面span的id'); + checkBookmark(bookmark, pre, latter, undefined); +}); + +test('createBookmark/moveToBookmark--元素闭合', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'first_texti_textxxxxxxxspan_text

    em_textp_text

    '; + var em_text = document.getElementById('em').firstChild; + var em = em_text.parentNode; + range.setStart(em_text, 1).setEnd(em_text, 1); + var bookmark = range.createBookmark(true, true); + ua.checkResult(range, em, em, 2, 2, true, '元素闭合'); + var pre = em.firstChild.nextSibling; + checkBookmark(bookmark, pre.id, null, true); + equal('_baidu_bookmark_start_', pre.id, '检查前面span的id'); + +}); + + +test('getClosedNode', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'xxxxxxxxxx'; + range.setStart(div, 2).setEnd(div, 3); + same(range.getClosedNode(), div.lastChild.previousSibling, 'check result is img'); + + range.setStart(div, 2).collapse(true); + equal(range.getClosedNode(), null, 'check null return result'); + + range.setStart(div, 0).setEnd(div, 1); + equal(range.getClosedNode(), null, 'get null result'); + +}); + +test('applyInlineStyle--strong', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'div_text'; + range.setStart(div, 0).setEnd(div, 1); + + range.applyInlineStyle('strong'); + equals(ua.getHTML(div), '
    div_text
    '); +}); + +test('applyInlineStyle--双重strong', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'div_text'; + + div.innerHTML = 'div_textstrong_text'; + range.setStart(div.firstChild, 3); + range.setEnd(div.firstChild.nextSibling.firstChild, 3); + + range.applyInlineStyle('strong'); + equals(ua.getHTML(div), '
    div_textstrong_text
    ', '同一个块元素父标签双重加粗'); + + div.innerHTML = 'xx

    xxbbbbxxx

    xx

    aaaaaaa

    '; + range.setStartBefore(div.firstChild.nextSibling.firstChild); + range.setEndAfter(div.lastChild.firstChild.firstChild); + + range.applyInlineStyle('strong'); + equals(ua.getHTML(div), '
    xx

    xxbbbbxxx

    xx

    aaaaaaa

    ', '跨块元素的加粗'); +}); + +test('applyInlineStyle--span放在em外面', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '
    div_text
    '; + range.setStart(div, 0).setEnd(div, 1); + range.applyInlineStyle('span', {style:'font-size:12px'}); + var span = div.firstChild.firstChild; + equal($(span.firstChild).css('font-size'), '12px', 'check style'); +}); + +test('applyInlineStyle--span', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'div_text'; + range.setStart(div, 0).setEnd(div, 1); + range.applyInlineStyle('span', {style:'font-size:12px'}); + var span = div.firstChild; + equal($(span).css('font-size'), '12px', 'check style'); + equal(span.firstChild.data, 'div_text', 'check innerHTML'); +}); + +test('applyInlineStyle--span元素闭合', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'div_text'; + range.setStart(div, 0).setEnd(div, 0); + range.applyInlineStyle('span', {style:'font-size:12px'}); + equal(ua.getHTML(div), '
    div_text
    '); +}); + +//TODO +test('applyInlineStyle-双重span', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + + div.innerHTML = 'div_text'; + var span = div.firstChild; + range.setStart(span.firstChild, 0).setEnd(span.firstChild, 4); + range.applyInlineStyle('span', {style:'color:red'}); + + var div_new = document.createElement('div'); + div_new.id = 'test'; + //1.2.6.1开启span套 span,调整 +// div_new.innerHTML = 'div_text'; + div_new.innerHTML = 'div_text'; + ok(ua.haveSameAllChildAttribs(div, div_new), 'check style'); +}); + + +test('applyInlineStyle--b', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '
    • li_text
    • bbbb
    '; + var li_text = div.firstChild.firstChild; + range.setStart(li_text, 0).setEnd(div, 1); + range.applyInlineStyle('b'); + equals(ua.getHTML(div), '
    • li_text
    • bbbb
    '); + + div.innerHTML = '
    • li_text
    • bbbb
    '; + li_text = div.firstChild.firstChild.firstChild; + range.setStart(li_text, 1).setEnd(li_text, 3); + range.applyInlineStyle('b'); + equal(ua.getHTML(div), '
    • li_text
    • bbbb
    '); + +}); + +test('applyInlineStyle-b元素闭合', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '
    • li_text
    • bbbb
    '; + var li_text = div.firstChild.firstChild; + range.setStart(li_text, 1).setEnd(li_text, 1); + range.applyInlineStyle('b'); + equals(ua.getHTML(div), '
    • li_text
    • bbbb
    '); + +}); + +test('applyInlineStyle-b有属性', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '

    1234

    '; + range.setStart(div, 0).setEnd(div.firstChild, 4); + range.applyInlineStyle('b', {title:'b_title', id:'b_id'}); + var b = div.firstChild.firstChild; + same(b, document.getElementById('b_id'), '插入带有属性的b'); + equal($(b).attr('title'), 'b_title', 'check title'); + equal(b.innerHTML, '1234', 'check innerHTML'); + equal(div.childNodes.length, 1, 'check child count'); +}); + +test('applyInlineStyle--b放在Inline元素外面', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '

    123456789

    123456789

    '; + + range.setStart(div, 0).setEnd(div, 2); + range.applyInlineStyle('b'); + equals(ua.getHTML(div), '

    123456789

    123456789

    ', 'Inline element on multiple selected elements with various childnodes'); + + div.innerHTML = '

    x1234y

    '; + var span = document.getElementById('span'); + range.setStart(span.firstChild, 0).setEnd(span.firstChild, 4); + range.applyInlineStyle('b'); + equals(ua.getHTML(div), '

    x1234y

    ', '多个嵌套Inline element'); +}); + +test('applyInlinestyle--b没有文字', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '



    '; + range.setStart(div, 0).setEnd(div, 1); + range.applyInlineStyle('b'); + equals(ua.getHTML(div), '



    ', '空表格'); + ua.checkResult(range, div, div, 0, 1, false, '对空表格进行b'); + //todo ie6下不知道为啥strong用不上去 +// div.innerHTML = ''; +// var ie6 = (baidu.editor.browser.ie == 6); +// if ( ie6 ) { +// div.appendChild( document.createTextNode( '\u200B' ) ); +// div.appendChild( document.createTextNode( '\u200B' ) ); +// } +// else { +// div.appendChild( document.createTextNode( '\ufeff' ) ); +// div.appendChild( document.createTextNode( '\ufeff' ) ); +// } +// range.setStart(div,0).setEnd( div, 1 ); +// range.applyInlineStyle( 'strong' ); +// equals( div.getElementsByTagName( 'strong' ).length, 1 ); +// if ( ie6 ) +// equal( div.innerHTML.toLowerCase(), '\u200B\u200B', 'div has no text' ); +// else +// equal( div.innerHTML.toLowerCase(), '\ufeff\ufeff', 'div has no text' ); +}); + +test('applyInlineStyle-双重b', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '

    b_text

    '; + var b_text = div.firstChild.firstChild.firstChild; + range.setStart(b_text, 1).setEnd(b_text, 2); + range.applyInlineStyle('b'); + equals(div.innerHTML.toLowerCase(), '

    b_text

    ', '文本双重b'); + + + div.innerHTML = '

    a1234b

    '; + range.setStart(div.getElementsByTagName('em')[0].firstChild, 0); + range.setEnd(div.getElementsByTagName('em')[0].firstChild, 4); + + range.applyInlineStyle('b'); + equals(div.innerHTML.toLowerCase(), '

    a1234b

    ', '双重b+多个inline元素'); + + // Inline element merged with parent and child + div.innerHTML = '

    a123456b

    '; + + range.setStart(div.getElementsByTagName('b')[0].firstChild, 1); + range.setEnd(div.getElementsByTagName('b')[0].lastChild, 1); + range.applyInlineStyle('b'); + equals(div.innerHTML.toLowerCase(), '

    a123456b

    ', '去掉嵌套的b'); +}); + +test('applyInlineStyle--多个style', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'xxxx'; + range.setStart(div, 0).setEnd(div, 1); + + range.applyInlineStyle('i').applyInlineStyle('span', {style:'color:red'}).applyInlineStyle('span', {style:'font-size:12px'}); + //1.2.6.1 span能套i +// var span = div.firstChild.firstChild; + var span = div.firstChild; + equal(span.style['color'], 'red', 'check color'); + equal($(span).css('font-size'), '12px', 'check font size'); + //1.2.6.1 span能套i + equal(span.innerHTML.toLowerCase(), 'xxxx', 'check innerHTML including u'); + +}); + +test('applyInlineStyle--MergeToParent', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '1234568910'; + range.setStart(div.firstChild, 0).setEnd(div.childNodes[1], 1).select(); + range.applyInlineStyle('strong', {style:'font-size:24px'}); + var html = '1234568910'; + ua.checkSameHtml(div.innerHTML, html); +}); +test('trace1583:applyInlineStyle--MergeToChild', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = '​123456789'; + + var span = div.getElementsByTagName('span')[1]; + range.setStart(span.firstChild, 2).setEnd(span.firstChild, 4).select(); + range.applyInlineStyle('span', {style:'font-size:24px'}); + var html = '123456789'; + ua.checkHTMLSameStyle(html, document, div, 'MergeToChild'); +}); + +test('applyInlineStyle--选区包含部分兄弟', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'xxxxspan_text'; + range.setStart(div, 0).setEnd(div.firstChild.nextSibling, 0); + range.applyInlineStyle('u'); + equal(div.innerHTML.toLowerCase(), 'xxxxspan_text', 'check innerHTML including u'); + +}); + +test('removeInlineStyle--删除父节点b', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'xxxx'; + range.setStart(div, 0).setEnd(div, 1); + range.removeInlineStyle('b'); + equals(div.innerHTML, 'xxxx', '删除b'); +}); + +test('removeInlineStyle--删除祖先b', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = "xxxx"; + var i = div.firstChild.firstChild; + range.setStart(i, 0).setEnd(i, 1); + range.removeInlineStyle('b'); + equals(div.innerHTML.toLowerCase(), 'xxxx'); + ua.checkResult(range, div, div, 0, 1, false, '删除祖先b'); +}); + +test('removeInlineStyle--删除部分b', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = "i_textspan_text"; + var b = div.firstChild; + range.setStart(b, 0).setEnd(b.firstChild.firstChild, 3); + range.removeInlineStyle('b'); + equals(div.innerHTML.toLowerCase(), 'i_textspan_text', '检查html'); + ua.checkResult(range, div, div, 0, 1, false, '删除部分b'); +}); + + +test('removeInlineStyle--删除多个b', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = "
     
    xxxxxx
    xxxxxx
    "; + range.setStart(div, 0).setEnd(div, 1); + range.removeInlineStyle('b'); + equals(ua.getHTML(div), '
     
    xxxxxx
    xxxxxx
    '); + + div.innerHTML = 'xxxxxbbbbbbccccc'; + range.setStart(div.getElementsByTagName('b')[0], 0); + range.setEndAfter(div.getElementsByTagName('b')[2].firstChild); + range.removeInlineStyle('b'); + equals(div.innerHTML.toLowerCase(), 'xxxxxbbbbbbccccc'); + +}); + +test('removeInlineStyle--删除不同层文本的样式', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = "xxxb_textb2_text"; + range.setStart(div, 0).setEnd(div, 1); + var b1 = div.firstChild.nextSibling; + var b2 = b1.nextSibling.firstChild; + range.setStart(b1.firstChild, 2).setEnd(b2.firstChild, 2); + range.removeInlineStyle('b'); + equals(div.innerHTML.toLowerCase(), 'xxxb_textb2_text'); + + ua.checkResult(range, div, div.lastChild, 2, 1, false, 'check startContainer等'); +}); + +test('removeInlineStyle--删除部分文本样式,需要切分文本节点', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = 'xxxu_text'; + range.setStart(div.firstChild, 2).setEnd(div.getElementsByTagName('u')[0].firstChild, 2); + range.removeInlineStyle('u'); + equals(ua.getHTML(div), '
    xxxu_text
    ', 'u为父亲节点'); + ua.checkResult(range, div, document.getElementById('i'), 1, 1, false, '检查startOffset等'); + + div.innerHTML = 'xxxu_text'; + range.setStart(div.firstChild, 2).setEnd(div.getElementsByTagName('u')[0].firstChild, 2); + range.removeInlineStyle('i'); + /*不能避免产生相同id元素。。。*/ + equals(ua.getHTML(div), '
    xxxu_text
    ', 'i为祖先节点'); + ua.checkResult(range, div, div.getElementsByTagName('b')[0], 1, 1, false, ''); + + div.innerHTML = "xxxxbbbbbxxxx"; + range.setStart(div.getElementsByTagName('u')[0].firstChild, 2).setEnd(div.getElementsByTagName('u')[1].firstChild, 2); + range.removeInlineStyle('u'); + equals(div.innerHTML.toLowerCase(), 'xxxxbbbbbxxxx', '开始和结束位置都有u'); + + div.innerHTML = "xxxxbbbbbxxxx"; + range.setStart(div.getElementsByTagName('u')[0].firstChild, 2).setEnd(div.getElementsByTagName('u')[1].firstChild, 2); + range.removeInlineStyle('b'); + equals(div.innerHTML.toLowerCase(), 'xxxxbbbbbxxxx', '删除部分文本节点的祖先节点的样式'); + ua.checkResult(range, div, div, 1, 4, false, '删除部分节点的祖先样式后'); + +}); + +/*闭合情况挪到basestyle中去做了,在这里不做任何处理*/ +test('removeInlineStyle--删除闭合元素的样式', function () { + var div = te.dom[2]; + var range = new baidu.editor.dom.Range(document); + div.innerHTML = "b_text"; + range.setStart(div.firstChild.firstChild.firstChild, 2).collapse(true); + range.removeInlineStyle('b'); + equals(div.innerHTML.toLowerCase(), 'b_text'); +}); + + +test('b节点取range', function () { + var div = te.dom[2]; + var editor = new baidu.editor.Editor({'autoFloatEnabled':false}); + stop(); + editor.render(div); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + editor.setContent('

    hellohello1hello2

    '); + range.setStart(editor.body.firstChild.lastChild, 0).collapse(1).select(); + range = editor.selection.getRange(); + if ((ua.browser.ie &&ua.browser.ie < 9) || ua.browser.webkit) + ua.checkResult(range, editor.body.firstChild.lastChild.previousSibling, editor.body.firstChild.lastChild.previousSibling, 1, 1, true, '节点后--check range'); + else if(ua.browser.ie &&ua.browser.ie > 8) + ua.checkResult(range, editor.body.firstChild, editor.body.firstChild, 3, 3, true, '节点后--check range'); + else + ua.checkResult(range, editor.body.firstChild.lastChild.previousSibling, editor.body.firstChild.lastChild.previousSibling, 0, 0, true, '节点后--check range'); + + range.setStart(editor.body.firstChild.firstChild.nextSibling, 0).collapse(1); + range.select(); + range = editor.selection.getRange(); + if (ua.browser.webkit) + ua.checkResult(range, editor.body.firstChild.firstChild.nextSibling.firstChild, editor.body.firstChild.firstChild.nextSibling.firstChild, 1, 1, true, '节点内文本节点前--check range'); + else if (ua.browser.ie&&ua.browser.ie < 9) + ua.checkResult(range, editor.body.firstChild.childNodes[1].childNodes[1], editor.body.firstChild.childNodes[1].childNodes[1], 0, 0, true, '节点内文本节点前--check range'); + else if(ua.browser.ie &&ua.browser.ie > 8) + ua.checkResult(range, editor.body.firstChild.childNodes[1], editor.body.firstChild.childNodes[1], 1, 1, true, '节点后--check range'); + else + ua.checkResult(range, editor.body.firstChild.firstChild.nextSibling.firstChild, editor.body.firstChild.firstChild.nextSibling.firstChild, 0, 0, true, '节点内文本节点前--check range'); + + range.setStart(editor.body.firstChild.childNodes[1], 0).collapse(1).select(); + range = editor.selection.getRange(); + if (ua.browser.webkit) + ua.checkResult(range, editor.body.firstChild.childNodes[1].firstChild, editor.body.firstChild.childNodes[1].firstChild, 1, 1, true, 'b节点--check range'); + else if (ua.browser.ie&&ua.browser.ie < 9) + ua.checkResult(range, editor.body.firstChild.childNodes[1].childNodes[1], editor.body.firstChild.childNodes[1].childNodes[1], 0, 0, true, '节点内文本节点前--check range'); + else if(ua.browser.ie &&ua.browser.ie > 8) + ua.checkResult(range, editor.body.firstChild.childNodes[1], editor.body.firstChild.childNodes[1], 1, 1, true, '节点后--check range'); + else + ua.checkResult(range, editor.body.firstChild.childNodes[1].firstChild, editor.body.firstChild.childNodes[1].firstChild, 0, 0, true, 'b节点--check range'); + start(); + }); +}); + +test('文本节点中间取range', function () { + var div = te.dom[2]; + var editor = new baidu.editor.Editor({'autoFloatEnabled':false}); + stop(); + editor.render(div); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + editor.setContent('

    hello2

    '); + range.setStart(editor.body.firstChild.firstChild, 2).collapse(1).select(); + range = editor.selection.getRange(); + if (ua.browser.ie&&ua.browser.ie < 9) + ua.checkResult(range, editor.body.firstChild.lastChild, editor.body.firstChild.lastChild, 0, 0, true, 'check range'); + else if(ua.browser.ie &&ua.browser.ie > 8) + ua.checkResult(range, editor.body.firstChild, editor.body.firstChild, 2, 2, true, 'check range'); + else + ua.checkResult(range, editor.body.firstChild.lastChild, editor.body.firstChild.lastChild, 2, 2, true, 'check range'); + start(); + }); +}); + +//test( 'select--closedNode', function() { +// var div = te.dom[2]; +// var range = new baidu.editor.dom.Range( document ); +// div.innerHTML = 'div_textspan_textdiv2_textem_text'; +//// range.setStart(div.getElementsBytagName('img'),0).setEnd(div.) +//// var span = div.firstChild.nextSibling; +//// range.setStart(span,1).setEnd(div,4); +//// range.select(); +//// +//// ua.checkResult(range,span,div,1,4,false,'check range'); +//// range.insertNode(document.createTextNode('aa')); +//// var selection = new baidu.editor.dom.Selection( document ); +//// var nativeRange = selection.getRange(); +// //TODO +//} ); + +test('range.createAddress,range.moveAddress', function () { + function equalRange(rngA, rngB) { + return rngA.startContainer === rngB.startContainer && rngA.startOffset === rngB.startOffset + && rngA.endContainer === rngB.endContainer && rngA.endOffset === rngB.endOffset + + } + + var div = te.dom[0]; + var rng = new UE.dom.Range(document); + div.innerHTML = 'xxxx'; + var addr = rng.setStart(div.firstChild, 0).collapse(true).createAddress(true); + var rng1 = new UE.dom.Range(document); + rng1.moveToAddress(addr); + ok(equalRange(rng, rng1)); + div.innerHTML = 'aaa'; + div.appendChild(document.createTextNode('aaa')); + div.appendChild(document.createTextNode('aaa')); + addr = rng.setStart(div.lastChild, 0).setEnd(div.lastChild, div.lastChild.nodeValue.length).createAddress(); + rng1.moveToAddress(addr); + ok(equalRange(rng, rng1)); + addr = rng.setStart(div.lastChild, 0).setEnd(div.lastChild, div.lastChild.nodeValue.length).createAddress(false, true); + div.innerHTML = 'aaaaaabbb'; + rng1.moveToAddress(addr); + equal(rng1.cloneContents().firstChild.nodeValue, 'bbb'); + div.innerHTML = 'aaaaaabbbsss'; + addr = rng.setStartAfter(div.firstChild.nextSibling.firstChild).collapse(true).createAddress(false); + rng1.moveToAddress(addr); + ok(equalRange(rng, rng1)) + div.innerHTML = ''; + div.appendChild(document.createTextNode(domUtils.fillChar)); + div.appendChild(document.createTextNode('aaa')); + addr = rng.setStartAtLast(div).collapse(true).createAddress(false, true); + div.innerHTML = 'aaa'; + rng1.moveToAddress(addr); + rng.setStartAtLast(div).collapse(true); + ok(equalRange(rng, rng1)); + div.innerHTML = 'aaasss'; + div.appendChild(document.createTextNode(domUtils.fillChar)); + addr = rng.setStartAtLast(div).collapse(true).createAddress(false, true); + div.innerHTML = 'aaasss'; + rng1.moveToAddress(addr); + rng.setStartAtLast(div).collapse(true); + ok(equalRange(rng, rng1)); + div.innerHTML = 'aaa'; + div.appendChild(document.createTextNode(domUtils.fillChar)); + div.appendChild(document.createTextNode('aaa')); + //空节点有占位 + addr = rng.setStart(div.firstChild.nextSibling, 0).collapse(true).createAddress(false, true); + div.innerHTML = 'aaaaaa'; + rng1.moveToAddress(addr); + rng.setStart(div.firstChild, 3).collapse(true); + ok(equalRange(rng, rng1)); +}); + +test('equals', function () { + var div = te.dom[2]; + var rng = new UE.dom.Range(document); + div.innerHTML = 'xxxx'; + rng.setStart(div.firstChild, 0).collapse(true); + var rng2 = rng.cloneRange(); + ok(rng.equals(rng2)) +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/core/Selection.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/Selection.js new file mode 100644 index 000000000..472522517 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/Selection.js @@ -0,0 +1,199 @@ +module("core.Selection"); + +/* + * 因为编辑器是必定会放在一个iframe中,所以在测试的过程中我们也放在iframe中测试,以防一些他们没有做容错处理导致的问题出现 + * */ + +//test( 'getRange--简单', function() { +// stop(); +// /*防止frame没有加载好导致无法取到document*/ +// setTimeout( function() { +// var doc = te.dom[1].contentWindow.document; +// var range = new baidu.editor.dom.Range( doc ); +// var div = doc.createElement( 'div' ); +// doc.body.appendChild( div ); +// div.innerHTML = 'firstsecond'; +// /*必须调用select函数,否则这个选择不会映射到浏览器上,导致selection得到的rangeCount为0 +// * select后会把文本节点切开 +// * */ +// range.setStart( div.firstChild, 0 ).setEnd( div.lastChild, 1 ).select(); +// var selection = new baidu.editor.dom.Selection( doc ); +// var nativeRange = selection.getRange(); +// var sc = nativeRange.startContainer; +// var so = nativeRange.startOffset; +// var ec = nativeRange.endContainer; +// var eo = nativeRange.endOffset; +// /*sc和ec的位置有多个,只能无奈地穷举*/ +// // ok( (sc === div) && so == 0 , 'check startContainer/offset' ); (ec === div) && eo == 2 ||好像这种情况在浏览器中不会遇到 +// ok( (sc === div.firstChild.firstChild) && so == 0 || (sc === div) && so == 0 || (sc === div.firstChild) && so == 0, 'check startContainer/offset' ); +// ok( (ec === div.firstChild.nextSibling) && eo == 1 || (ec === div.lastChild) && eo == 0, 'check endContainer/offset' ); +// equal( nativeRange.collapsed, false, 'check collapse status' ); +// start(); +// }, 20 ); +//} ); +// +//test( 'getText', function() { +// stop(); +// setTimeout( function() { +// var doc = te.dom[1].contentWindow.document; +// var range = new baidu.editor.dom.Range( doc ); +// var div = doc.createElement( 'div' ); +// doc.body.appendChild( div ); +// div.innerHTML = 'spanTextfirstsecond'; +// +// range.setStart( div.firstChild, 0 ).setEnd( div.lastChild, 1 ).select(); +// var selection = new baidu.editor.dom.Selection( doc ); +// +// var text = selection.getText(); +// equal( text, 'spanTextfirsts', 'check getText function' ); +// start(); +// }, 20 ); +//} ); +// +// +//test( 'getstart--文本', function() { +// stop(); +// setTimeout( function() { +// var doc = te.dom[1].contentWindow.document; +// var range = new baidu.editor.dom.Range( doc ); +// var div = doc.createElement( 'div' ); +// doc.body.appendChild( div ); +// div.innerHTML = 'emspanTextfirstsecond'; +// +// range.setStart( div.firstChild.lastChild.lastChild.firstChild, 0 ).setEnd( div.lastChild, 1 ).select(); +// var selection = new baidu.editor.dom.Selection( doc ); +// var startNode = selection.getStart(); +// /*textNode*/ +// ok( startNode === div.firstChild.lastChild.lastChild, 'check startNode' ); +// start(); +// }, 20 ); +//} ); +// +//test( 'getstart--边界情况', function() { +// stop(); +// setTimeout( function() { +// var doc = te.dom[1].contentWindow.document; +// var range = new baidu.editor.dom.Range( doc ); +// var div = doc.createElement( 'div' ); +// doc.body.appendChild( div ); +// div.innerHTML = 'emspanTextfirstsecond'; +// +// range.setStart( div.firstChild.lastChild, 0 ).collapse().select(); +// var selection = new baidu.editor.dom.Selection( doc ); +// var startNode = selection.getStart(); +// /*边界情况,ie下好像会尽量贴文本,因此startNode为em*/ +// ok( startNode === div.firstChild.lastChild || startNode === div.firstChild, 'check startNode' ); +// start(); +// }, 20 ); +//} ); + +test('getRange--闭合选区的边界情况', function () { + var div_new = document.createElement('div'); + document.body.appendChild(div_new); + var editor = new baidu.editor.Editor({'autoFloatEnabled': false}); + stop(); + setTimeout(function () { + editor.render(div_new); + editor.ready(function () { + setTimeout(function () { + var range = new baidu.editor.dom.Range(editor.document); + editor.setContent('

    xxx

    '); + range.setStart(editor.body.firstChild.firstChild, 0).collapse(true).select(); + range = editor.selection.getRange(); + var strong = editor.body.firstChild.firstChild; + /*startContainer:ie is xxx,others are strong.firstChild*/ + if(ua.browser.ie>8){ + ok(( range.startContainer === strong) && range.startOffset === 1, 'startContainer是xxx左边的占位符或者xxx'); + } + + else{ + ok(range.startContainer.nodeType == 3, 'startContainer是文本节点'); + + ok(( range.startContainer === strong.firstChild) && strong.firstChild.length == 1 || (range.startContainer.nodeValue.length == 3 && range.startContainer === strong.lastChild), 'startContainer是xxx左边的占位符或者xxx'); + } + + ua.manualDeleteFillData(editor.body); + range.setStart(editor.body.firstChild.firstChild, 1).collapse(true).select(); + /*去掉占位符*/ + range = editor.selection.getRange(); + /*可能为(strong,1)或者(xxx,3)*/ + ok(( range.startContainer === strong) || ( range.startContainer === strong.lastChild) && strong.lastChild.length == 1 || (range.startContainer.nodeValue.length == 3 && range.startContainer === strong.firstChild), 'startContainer是xxx或者xxx右边的占位符'); +// ok( range.startContainer.nodeType == 1 ? range.startContainer.tagName.toLowerCase() == 'strong' && range.startOffset == 1 : range.startContainer.data == 'xxx' && range.startOffset == 3, 'strong,1或xxx,3' ); + + ua.manualDeleteFillData(editor.body); + /*p,0*/ + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + range = editor.selection.getRange(); + /*startContainer:ie is xxx,ff is p, chrome is strong*/ +// ok( ( range.startContainer === strong.parentNode.firstChild)&& strong.parentNode.firstChild.length == 1 || (range.startContainer.nodeValue.length == 3 && range.startContainer === strong.firstChild.nextSibling), 'startContainer是第一个占位符或者xxx' ); +// ua.manualDeleteFillData( editor.body ); +// range.setStart( editor.body.firstChild, 1 ).collapse( true ).select(); +// equal( range.startContainer.tagName.toLowerCase(), 'p', 'p,1' ); + + + te.dom.push(div_new); + te.obj.push(editor); + start(); + }, 50); + }); + }, 50); +}); + +//test( '不闭合选区的边界情况', function () { +// +//} ); +// +test('trace 1742 isFocus', function () { + if (!ua.browser.opera) { + var div1 = document.createElement('div'); + var div2 = document.createElement('div'); + document.body.appendChild(div1); + document.body.appendChild(div2); + var editor1 = new UE.Editor({'initialContent': 'hello', 'autoFloatEnabled': false}); + var editor2 = new UE.Editor({'initialContent': 'hello', 'autoFloatEnabled': false}); + editor1.render(div1); + stop(); + editor1.ready(function () { + editor2.render(div2); + editor2.ready(function () { + editor1.focus(); + ok(editor1.selection.isFocus(), '设editor内容是 editor1 is focused'); + ok(!editor2.selection.isFocus(), '设editor内容是 editor2 is not focused'); + editor2.focus(); + ok(editor2.selection.isFocus(), '设editor内容是 editor2 is focused'); + ok(!editor1.selection.isFocus(), '设editor内容是 editor1 is not focused'); + div1.parentNode.removeChild(div1); + div2.parentNode.removeChild(div2); + + var div3 = document.createElement('div'); + var div4 = document.createElement('div'); + document.body.appendChild(div3); + document.body.appendChild(div4); + var editor3 = new UE.Editor({'initialContent': '

    hello

    ', 'autoFloatEnabled': false}); + var editor4 = new UE.Editor({'initialContent': '

    hello

    ', 'autoFloatEnabled': false}); + editor3.render(div3); + editor3.ready(function () { + editor4.render(div4); + editor4.ready(function () { + editor3.focus(); + ok(editor3.selection.isFocus(), '设editor内容是

    editor1 is focused'); + ok(!editor4.selection.isFocus(), '设editor内容是

    editor2 is not focused'); + editor4.focus(); + ok(editor4.selection.isFocus(), '设editor内容是

    editor2 is focused'); + ok(!editor3.selection.isFocus(), '设editor内容是

    editor1 is not focused'); + setTimeout(function () { + div3.parentNode.removeChild(div3); + div4.parentNode.removeChild(div4); + start(); + }, 50); + }); + }); + }); + }); + } +}); + + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/core/ajax.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/ajax.js new file mode 100644 index 000000000..3f79b316a --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/ajax.js @@ -0,0 +1,271 @@ +module('core.ajax'); +var ajax_request_baseurl = upath + 'ajax.php'; + + +test("post请求,无数据", function () { + UE.ajax.request(ajax_request_baseurl, { + onsuccess: function (xhr) { + equals(xhr.responseText, "", "post请求,无数据"); + start(); + }, + onerror: function () { + ok(false, 'fail to send ajax request'); + start(); + } + }); + stop(); +}); + +test("get请求,无数据,url中有数据", function () { + UE.ajax.request(ajax_request_baseurl + "?get1=ueditor&get2=baidu", { + method: 'GET', + onsuccess: function (xhr) { + equals(xhr.responseText, "get1='ueditor'&get2='baidu'", "post请求,数据放在url中传递"); + start(); + }, + onerror: function () { + ok(false, 'fail to send ajax request'); + start(); + } + }); + stop(); +}); + + +test("get请求,有数据,url中有数据", function () { + UE.ajax.request(ajax_request_baseurl + "?get1=ueditor&get2=baidu", { + method: 'GET', + content: "img1=http://www.baidu.com&img2=http://ueditor.baidu.com", + onsuccess: function (xhr) { + equals(xhr.responseText, "get1='ueditor'&get2='baidu'&img1=http://www.baidu.com&img2=http://ueditor.baidu.com", "post请求,数据放在url中传递"); + start(); + }, + onerror: function () { + ok(false, 'fail to send ajax request'); + start(); + } + }); + stop(); +}); + +test("get请求,有data字段,无数据,url中有数据", function () { + UE.ajax.request(ajax_request_baseurl + "?get1=ueditor&get2=baidu", { + method: 'GET', + data: { + img1: 'http://www.baidu.com', img2: 'http://www.google.com' + }, + onsuccess: function (xhr) { + equals(xhr.responseText, "get1='ueditor'&get2='baidu'&img1='http://www.baidu.com'&img2='http://www.google.com'", "post请求,数据放在url中传递"); + start(); + }, + onerror: function () { + ok(false, 'fail to send ajax request'); + start(); + } + }); + stop(); +}); + +test("post请求,有data字段", function () { + UE.ajax.request(ajax_request_baseurl, { + data: { + img1: 'http://www.baidu.com', img2: 'http://www.google.com' + }, + onsuccess: function (xhr) { + equals(xhr.responseText, "img1='http://www.baidu.com'&img2='http://www.google.com'", "post请求,有data字段"); + start(); + }, + onerror: function () { + ok(false, 'fail to send ajax request'); + start(); + } + }); + stop(); +}); + +test("post请求,没有data字段,有其他数据", function () { + UE.ajax.request(ajax_request_baseurl, { + content: "img1=http://www.baidu.com&img2=http://ueditor.baidu.com", + onsuccess: function (xhr) { + equals(xhr.responseText, "img1=http://www.baidu.com&img2=http://ueditor.baidu.com", "没有data字段,有其他数据"); + start(); + }, + onerror: function () { + ok(false, 'fail to send ajax request'); + start(); + } + }); + stop(); +}); + +test("post请求,有data字段,有其他数据", function () { + UE.ajax.request(ajax_request_baseurl, { + data: { + img1: 'http://www.baidu.com', img2: 'http://www.google.com' + }, + content: "i1=http://www.baidu.com&i2=http://ueditor.baidu.com", + onsuccess: function (xhr) { + equals(xhr.responseText, "img1='http://www.baidu.com'&img2='http://www.google.com'&i1=http://www.baidu.com&i2=http://ueditor.baidu.com", "有data字段,有其他数据"); + start(); + }, + onerror: function () { + ok(false, 'fail to send ajax request'); + start(); + } + }); + stop(); +}); + +test("get请求,有data字段,有其他数据", function () { + UE.ajax.request(ajax_request_baseurl, { + method: 'GET', + data: { + get1: 'http://www.baidu.com', get2: 'http://www.google.com' + }, + content: "i1=http://www.baidu.com&i2=http://ueditor.baidu.com", + onsuccess: function (xhr) { + equals(xhr.responseText, "get1='http://www.baidu.com'&get2='http://www.google.com'&i1=http://www.baidu.com&i2=http://ueditor.baidu.com", "有data字段,有其他数据"); + start(); + }, + onerror: function () { + ok(false, 'fail to send ajax request'); + start(); + } + }); + stop(); +}); + + +test("并发多个post请求", function () { + + UE.ajax.request(ajax_request_baseurl, { + data: { + img1: 'http://ueditor.baidu.com', img2: 'http://www.google.com' + }, + content: "i1=http://www.baidu.com&i2=http://ueditor.baidu.com", + onsuccess: function (xhr) { + equals(xhr.responseText, "img1='http://ueditor.baidu.com'&img2='http://www.google.com'&i1=http://www.baidu.com&i2=http://ueditor.baidu.com", "有data字段,有其他数据"); + }, + onerror: function () { + ok(false, 'fail to send ajax request'); + } + }); + + UE.ajax.request(ajax_request_baseurl, { + data: { + img1: 'http://map.baidu.com', img2: 'http://www.google.com' + }, + content: "p1=http://www.baidu.com&p2=http://ueditor.baidu.com", + onsuccess: function (xhr) { + equals(xhr.responseText, "img1='http://map.baidu.com'&img2='http://www.google.com'&p1=http://www.baidu.com&p2=http://ueditor.baidu.com", "有data字段,有其他数据"); + start(); + }, + onerror: function () { + ok(false, 'fail to send ajax request'); + start(); + } + }); + stop(); +}); + +test("jsonp请求,无数据", function () { + + UE.ajax.request(ajax_request_baseurl, { + dataType: 'jsonp', + onsuccess: function (r) { + notDeepEqual(r, null, '返回内容不为空'); + notEqual(r.callback, null, '返回内容有callback参数'); + start(); + }, + onerror: function () { + ok(false, 'fail to send jsonp request'); + start(); + } + }); + stop(); + +}); + +test("jsonp请求,无数据,url上有数据", function () { + + UE.ajax.request(ajax_request_baseurl + '?get1=getcontent1&get2=getcontent2', { + dataType: 'jsonp', + onsuccess: function (r) { + equal(r.get1, 'getcontent1', 'url上的参数1正常'); + equal(r.get2, 'getcontent2', 'url上的参数2正常'); + start(); + }, + onerror: function () { + ok(false, 'fail to send jsonp request'); + start(); + } + }); + stop(); + +}); + +test("jsonp请求,有数据,url上有数据", function () { + + UE.ajax.request(ajax_request_baseurl + '?get1=getcontent1&get2=getcontent2', { + key1: 'keycontent1', + key2: 'keycontent2', + dataType: 'jsonp', + onsuccess: function (r) { + equal(r.get1, 'getcontent1', 'url上的参数1正常'); + equal(r.get2, 'getcontent2', 'url上的参数2正常'); + equal(r.key1, 'keycontent1', '数据上的参数1正常'); + equal(r.key2, 'keycontent2', '数据上的参数2正常'); + start(); + }, + onerror: function () { + ok(false, 'fail to send jsonp request'); + start(); + } + }); + stop(); + +}); + +test("jsonp请求,有数据,data上有数据,url上有数据", function () { + + UE.ajax.request(ajax_request_baseurl + '?get1=getcontent1&get2=getcontent2', { + key1: 'keycontent1', + key2: 'keycontent2', + data: { + 'datakey1': 'datakeycontent1', + 'datakey2': 'datakeycontent2' + }, + dataType: 'jsonp', + onsuccess: function (r) { + equal(r.get1, 'getcontent1', 'url上的参数1正常'); + equal(r.get2, 'getcontent2', 'url上的参数2正常'); + equal(r.key1, 'keycontent1', '数据上的参数1正常'); + equal(r.key2, 'keycontent2', '数据上的参数2正常'); + equal(r.datakey1, 'datakeycontent1', 'data数据上的参数1正常'); + equal(r.datakey2, 'datakeycontent2', 'data数据上的参数2正常'); + start(); + }, + onerror: function () { + ok(false, 'fail to send jsonp request'); + start(); + } + }); + stop(); + +}); + +test("通过getJSONP方法发送jsonp请求", function () { + + UE.ajax.getJSONP(ajax_request_baseurl + '?get1=getcontent1&get2=getcontent2', { + 'datakey1': 'datakeycontent1', + 'datakey2': 'datakeycontent2' + }, function (r) { + equal(r.get1, 'getcontent1', 'url上的参数1正常'); + equal(r.get2, 'getcontent2', 'url上的参数2正常'); + equal(r.datakey1, 'datakeycontent1', 'data数据上的参数1正常'); + equal(r.datakey2, 'datakeycontent2', 'data数据上的参数2正常'); + start(); + }); + stop(); + +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/core/ajax.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/ajax.php new file mode 100644 index 000000000..b4595d629 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/ajax.php @@ -0,0 +1,57 @@ + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/core/browser.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/browser.js new file mode 100644 index 000000000..3ef272fae --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/browser.js @@ -0,0 +1,72 @@ +module( "core.browser" ); + + +test( 'browser', function() { + var browser = baidu.editor.browser; + /*ie*/ + if ( browser.ie ) { + ok( ua.browser.ie, 'is ie' ); + var version = ua.browser.ie; + if ( browser.version < 7 ) { + ok( browser.ie6Compat, 'ie6 compat mode' ); + equal( version, browser.version, 'check ie version' ); + } + if ( browser.version == 7 ) { + ok( browser.ie7Compat, 'ie7 compat mode' ); + equal( version, browser.version, 'check ie version' ); + ok( browser.isCompatible, 'is compatible' ); + } + switch ( document.documentMode ) { + case 7: + ok( browser.ie7Compat, 'ie7 document Mode' ); + equal( version, browser.version, 'check ie version' ); + ok( browser.isCompatible, 'is compatible' ); + break; + case 8: + ok( browser.ie8Compat, 'ie8 document Mode' ); + equal( version, browser.version, 'check ie version' ); + ok( browser.isCompatible, 'is compatible' ); + break; + case 9: + ok( browser.ie9Compat, 'ie9 document Mode' ); + equal( version, browser.version, 'check ie version' ); + ok( browser.isCompatible, 'is compatible' ); + break; + case 11: + ok( browser.ie11Compat, 'ie11 document Mode' ); + equal( version, browser.version, 'check ie version' ); + ok( browser.isCompatible, 'is compatible' ); + break; + } + } + /*opera*/ + if ( browser.opera ) { + ok( ua.browser.opera, 'is opera' ); + equal( browser.version, ua.browser.opera, 'check opera version' ); + } + /*webKit*/ + if ( browser.webkit ) { + ok( ua.browser.webkit, 'is webkit' ); + equal( browser.webkit, ua.browser.webkit>0, 'check webkit version' ); + } + /*gecko*/ + if ( browser.gecko ) { + ok( ua.browser.gecko, 'is gecko' ); + equal( browser.gecko, !!ua.browser.gecko, 'check gecko version' ); + } +// /*air*/ +// if ( browser.air ) { +// ok( ua.browser.air, 'is air' ); +// equal( browser.air, ua.browser.air>0, 'check air version' ); +// } +// /*mac*/ +// if ( browser.mac ) { +// ok( ua.browser.air, 'is air' ); +// equal( ua.browser.os, 'macintosh', 'check air version' ); +// } + /*quirks*/ + if ( browser.quirks ) { + equal( document.compatMode, 'BackCompat', 'is quirks mode' ); + equal( browser.version, 6, 'ie version is 6' ); + } +} ); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/core/domUtils.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/domUtils.js new file mode 100644 index 000000000..2293e1718 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/domUtils.js @@ -0,0 +1,1718 @@ +module( 'core.domUtils' ); + +test( 'isBoundaryNode--node是firstChild',function(){ + + if(ua.browser.ie){ +// var body = te.dom[1].contentDocument.appendChild(document.createElement('body')); +// var div = body.appendChild(document.createElement('div')); + var div = te.dom[2]; + }else{ + var div = te.dom[1].contentWindow.document.firstChild.lastChild.appendChild(document.createElement('div')); + } + div.innerHTML = "sssaaa

    ppp

    "; + var node = div.firstChild.nextSibling; + equal( domUtils.isBoundaryNode(node, "firstChild"), 0 ); + equal( domUtils.isBoundaryNode(node, "lastChild"), 0 ); + node = div.firstChild.firstChild; + if(ua.browser.ie){ + equal( domUtils.isBoundaryNode(node, "firstChild"), 0 ); + }else{ + equal( domUtils.isBoundaryNode(node, "firstChild"), 1 ); + } + equal( domUtils.isBoundaryNode(node, "lastChild"), 0 ); + node = div.firstChild.nextSibling.nextSibling; + equal( domUtils.isBoundaryNode(node, "firstChild"), 0 ); + equal( domUtils.isBoundaryNode(node, "lastChild"), 1 ); +} ); + +test( 'getPosition--A和B是同一个节点', function() { + var div = te.dom[2]; + div.innerHTML = "spanbbbxxx"; + var span_text = div.firstChild.firstChild; + var domUtils = te.obj[3]; + equal( domUtils.getPosition( span_text, span_text ), 0, 'identical node' ); +} ); + + +test( 'getPosition--A和B是兄弟节点', function() { + var div = te.dom[2]; + div.innerHTML = "spanbbbxxx"; + var span_text = div.firstChild.firstChild; + var div_text = div.lastChild; + var domUtils = te.obj[3]; + /*span_text在div_text前面*/ + equal( domUtils.getPosition( span_text, div_text ), domUtils.POSITION_PRECEDING, 'preceding node' ); + /*div_text在span_text后面*/ + equal( domUtils.getPosition( div_text, span_text ), domUtils.POSITION_FOLLOWING, 'following node' ); +} ); + + +test( 'getPosition--A是B的祖先', function() { + var div = te.dom[2]; + div.innerHTML = "spanbbbxxx"; + var span_text = div.firstChild.firstChild; + var domUtils = te.obj[3]; + /*A是B的祖先*/ + equal( domUtils.getPosition( div, span_text ), domUtils.POSITION_CONTAINS + domUtils.POSITION_PRECEDING, 'preceding node' ); + /*A是B的子孙*/ + equal( domUtils.getPosition( span_text, div ), domUtils.POSITION_IS_CONTAINED + domUtils.POSITION_FOLLOWING, 'following node' ); +} ); + +test( 'getPosition--A和B在不同dom树上', function() { + stop(); + expect( 1 ); + var div = te.dom[2]; + div.innerHTML = "spanbbbxxx"; + var iframe = te.dom[1]; + setTimeout( function() { + var frame_doc = iframe.contentWindow.document || iframe.contentDocument; + var frame_div = frame_doc.createElement( 'div' ); + frame_doc.body.appendChild( frame_div ); + var domUtils = te.obj[3]; + /*A和B在不同dom树上*/ + equal( domUtils.getPosition( div, frame_div ) & 1, 1, 'A和B不在同一个dom树上' ); + start(); + }, 50 ); + +} ); + +test( 'getNodeIndex', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + div.innerHTML = 'dddddxxxxx


    dddd

    '; + var comment = div.firstChild.nextSibling.nextSibling; + equal( domUtils.getNodeIndex( comment ), 2, 'check commnet index' ); + var td_text = document.getElementById( 'table' ).firstChild.firstChild.firstChild; + equal( domUtils.getNodeIndex( td_text ), 0, 'check textNode index' ); + equal( domUtils.getNodeIndex( div.firstChild ), 0, 'check strong label index' ); + equal( domUtils.getNodeIndex( (document.getElementById( 'p' )) ), 5, 'check p label index' ); +} ); + +test( 'findParent--body', function() { + var domUtils = te.obj[3]; + equal( domUtils.findParent( document.body ), null, 'find parent for body' ); +} ); + +/*找符合条件的上一个节点,如果条件为空则找父节点*/ +test( 'findParent--tester为空', function() { + var domUtils = te.obj[3]; + var div = te.dom[2]; + div.innerHTML = 'dddddspanxxxxx


    dddd

    '; + var span_text = document.getElementById( 'span' ).firstChild; + same( domUtils.findParent( span_text ), span_text.parentNode, 'find parent' ); +} ); + +test( 'findParent--tester不为空', function() { + var domUtils = te.obj[3]; + var div = te.dom[2]; + div.innerHTML = 'dddddspanxxxxx


    dddd

    '; + var span_text = document.getElementById( 'span' ).firstChild; + var div1 = domUtils.findParent( span_text, function( node ) { + if ( node.id == "test" ) + return true; + return false; + } ); + same( div1, div, 'find parent' ); +} ); + + +/*不考虑includeSelf的时候取body的parent的情况*/ +test( 'findParentByTagName--body', function() { + var domUtils = te.obj[3]; + var div = te.dom[2]; + same( domUtils.findParentByTagName( document.body, 'body' ), null, 'parent is self' ); +} ); + + +test( 'findParentByTagName--tagName为字符串', function() { + var domUtils = te.obj[3]; + var div = te.dom[2]; + div.innerHTML = 'dddddspanxxxxx


    dddd

    '; + var br = document.getElementById( 'p' ).firstChild; + same( domUtils.findParentByTagName( br, 'div' ), div, 'tagName为字符串' ); + same( domUtils.findParentByTagName( br, 'em' ), null, 'tagName为字符串返回null' ); +} ); + +test( 'findParentByTagName--tagName为字符串数组', function() { + var domUtils = te.obj[3]; + var div = te.dom[2]; + div.innerHTML = 'dddddspanxxxxx


    dddd

    '; + var br = document.getElementById( 'p' ).firstChild; + var tagName = ['em','p','div']; + same( domUtils.findParentByTagName( br, tagName ), document.getElementById( 'p' ), 'tagName为字符串数组,找出第一个符合条件的父节点' ); +} ); + + +test( 'findParentByTagName--文本节点', function() { + var domUtils = te.obj[3]; + var div = te.dom[2]; + div.innerHTML = 'dddddspanxxxxx


    dddd

    '; + var span_text = document.getElementById( 'span' ).firstChild; + var tagName = ['em','p','div']; + same( domUtils.findParentByTagName( span_text, tagName ), div, '文本节点' ); +} ); + +test( 'findParents', function() { + var domUtils = te.obj[3]; + var div = te.dom[2]; + div.innerHTML = 'dddddspanxxxxx


    dddd

    '; + var span_text = document.getElementById( 'span' ).firstChild; + /*includeSelf*/ + var parents = domUtils.findParents( span_text, true ); + equal( parents.length, 4, 'check parent count' ); + same( parents[0], document.body, 'first parent is body' ); + same( parents[1], div, 'second parent is div' ); + same( parents[2], span_text.parentNode, 'third parent is span' ); + same( parents[3], span_text, 'last parent is self' ); + /*不逆序存放祖先节点,closerFirst=false*/ + parents = domUtils.findParents( span_text, false, null, true ); + equal( parents.length, 3, 'check parent count' ); + same( parents[0], span_text.parentNode, 'first parent is span' ); + same( parents[1], div, 'second parent is div' ); + same( parents[2], document.body, 'last parent is body' ); +} ); + + +test( 'findParents--tester', function() { + var domUtils = te.obj[3]; + var div = te.dom[2]; + div.innerHTML = '


    dddd

    '; + var img = document.getElementById( 'img' ); + var parents = domUtils.findParents( img, false, function( node ) { + if ( node.tagName.toLowerCase() == 'div' || node.tagName.toLowerCase() == 'body' ) + return false; + return true; + } ); + equal( parents.length, 1, 'check parent count' ); + same( parents[0], div.firstChild.firstChild, 'first parent is p' ); +} ); + +test( 'insertAfter', function() { + var domUtils = te.obj[3]; + var div = te.dom[2]; + var textNode = document.createTextNode( 'text' ); + domUtils.insertAfter( div, textNode ); + te.dom.push( textNode ); + equal( textNode, div.nextSibling, 'insertAfter' ); +} ); + +test( 'remove--not keep children', function() { + var domUtils = te.obj[3]; + var div = te.dom[2]; + div.innerHTML = "

    xxxxxxxxxxx

    xxxx
    "; + var text = div.firstChild.firstChild; + var p = div.firstChild; + /*删除文本节点*/ + var node = domUtils.remove( text ); + equal( ua.getChildHTML( div ), '

    xxxxxxxx

    xxxx
    ' ); + same( text, node, 'check removed textNode' ); + /*删除有孩子的节点*/ + node = domUtils.remove( p ); + equal( ua.getChildHTML( div ), '
    xxxx
    ' ); + same( node, p, 'check removed p' ); +} ); + +test( 'remove-- keep children', function() { + var domUtils = te.obj[3]; + var div = te.dom[2]; + div.innerHTML = '

    xxxxxxxxxxx

    xxxx
    '; + var text = div.firstChild.firstChild; + var p = div.firstChild; + /*删除文本节点*/ + var node = domUtils.remove( text, true ); + equal( ua.getChildHTML( div ), '

    xxxxxxxx

    xxxx
    ' ); + same( text, node, 'check removed textNode' ); + /*删除有孩子的节点*/ + node = domUtils.remove( p, true ); + equal( ua.getChildHTML( div ), 'xxxxxxxx
    xxxx
    ' ); + same( node.id, p.id, 'check removed p' ); +} ); + +test( 'getNextDomNode--没有filter', function() { + var domUtils = te.obj[3]; + var div = te.dom[2]; + div.innerHTML = '

    p_textxxxxxxxx

    xxxx
    '; + var p = div.firstChild; + /*直接查找兄弟节点*/ + same( domUtils.getNextDomNode( p ), div.lastChild, '后兄弟节点' ); +// same( domUtils.getPreviousDomNode( divChild ), p, '前一个兄弟节点' ); + /*startFromChild=true,查找孩子结点*/ + equal( domUtils.getNextDomNode( p, true ).data, 'p_text', 'text node' ); +// equal( domUtils.getPreviousDomNode( p, true ), p.lastChild, 'text node' ); +} ); + + +test( 'getNextDomNode--有filter', function() { + var domUtils = te.obj[3]; + var div = te.dom[2]; + div.innerHTML = '
    xxxxxxxx

    xx

    xxxx
    '; + document.body.insertBefore( document.createElement( 'span' ), div ); + var span = div.firstChild.firstChild; + var filter = function( node ) { + if ( $( node ).css( 'display' ) == 'block' ) + return false; + return true; + }; + same( domUtils.getNextDomNode( span, false, filter ), div.firstChild.lastChild, '找到第一个不为block元素的兄弟节点' ); +// same( domUtils.getPreviousDomNode( div, true, filter ), div.previousSibling, '孩子中没有block元素,则找父亲的previousSibling节点' ); + te.obj.push( div.previousSibling ); +} ); +test( 'getNextDomNode-没有兄弟或孩子', function() { + var domUtils = te.obj[3]; + var div = te.dom[2]; + div.innerHTML = '

    p_textxxxxxxxx

    xxxx
    '; + var p = div.firstChild; + /*直接查找兄弟节点*/ +// same( domUtils.getPreviousDomNode( p ), div.previousSibling, '前面木有兄弟' ); + same( domUtils.getNextDomNode( div.lastChild ), div.nextSibling, '后面木有兄弟' ); +} ); + +test( 'isBookmarkNode', function() { + var domUtils = te.obj[3]; + var div = te.dom[2]; + var range = te.obj[2]; + div.innerHTML = 'xxxxxxxx
    xxxx
    '; + range.setStart( div, 0 ).setEnd( div, 1 ); + range.createBookmark(); + ok( domUtils.isBookmarkNode( div.firstChild ), 'is BookmarkNode' ); + ok( !domUtils.isBookmarkNode( div.firstChild.nextSibling ), 'not BookmarkNode' ); + +} ); + +test( 'getWindow', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + var w = domUtils.getWindow( div ); + ok( w === self.window, 'check window' ); +} ); + +test( 'getWindow--iframe', function() { + var f = te.dom[1]; + var domUtils = te.obj[3]; + expect( 1 ); + var frame_doc = f.contentWindow.document || f.contentDocument; + stop(); + setTimeout( function() { + var frame_div = frame_doc.createElement( 'div' ); + frame_doc.body.appendChild( frame_div ); + var w = domUtils.getWindow( frame_div ); + ok( f.contentWindow === w, 'same window' ); + start(); + } ); + +} ); + +test( 'getCommonAncestor--body', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + equal( domUtils.getCommonAncestor( div, document.body ).tagName.toLocaleLowerCase(), 'body', '第二个参数是body' ); + equal( domUtils.getCommonAncestor( document.body, div ).tagName.toLocaleLowerCase(), 'body', '第一个参数是body' ); +} ); + +test( 'getCommonAncestor--自己', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + same( domUtils.getCommonAncestor( div, div ), div, '自己和自己的公共祖先' ); + +} ); + +test( 'getCommonAncestor--兄弟节点', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + div.innerHTML = 'xxxx

    dddd

    '; + var span_text = div.firstChild.firstChild; + var td = document.getElementById( 'td' ); + same( domUtils.getCommonAncestor( span_text, td ), div, '兄弟节点' ); +} ); + +test( 'getCommonAncestor--不在一个dom树', function() { + stop(); + expect( 1 ); + var div = te.dom[2]; + var f = te.dom[1]; + setTimeout( function() { + var domUtils = te.obj[3]; + var frame_doc = f.contentWindow.document || f.contentDocument; + var frame_div = frame_doc.createElement( 'div' ); + frame_doc.body.appendChild( frame_div ); + same( domUtils.getCommonAncestor( frame_div, div ), null, '不在一个dom树' ); + start(); + }, 50 ); + +} ); + +test( 'isWhitespace', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + div.innerHTML = "aaa\ufeff\u200B\t\t\n\r"; + ok( !domUtils.isWhitespace( div.firstChild ), 'not whiteSpace' ); + div.innerHTML = baidu.editor.browser.ie && baidu.editor.browser.version == '6' ? '\ufeff' : '\u200B' + '\t\t\n\r'; + ok( domUtils.isWhitespace( div.firstChild ), 'is whiteSpace' ); +} ); + +test( 'isEmptyInlineElement', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + div.innerHTML = '\n\rxxxx'; + var b1 = div.firstChild.firstChild; + ok( !domUtils.isEmptyInlineElement( b1 ), 'not empty inline' ); + ok( domUtils.isEmptyInlineElement( b1.firstChild.firstChild ), 'is emtpy inline element' ); +} ); + +test( 'isEmptyInlineElement-nodeType!=1', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + div.innerHTML = '\n\r\ufeff\u200Bxxxx'; + ok( !domUtils.isEmptyInlineElement( div.firstChild.firstChild.firstChild ), 'textNode not inline element' ); +} ); + +test( 'isEmptyInlineElement-block element', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + div.innerHTML = '\n\rxxxx'; + ok( !domUtils.isEmptyInlineElement( div ), 'not inline element' ); +} ); + + +test( 'clearEmptySibling', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + div.innerHTML = '

    xxxxxxxx

    '; + var text = div.firstChild.firstChild; + /*没有空sibling*/ + domUtils.clearEmptySibling( text ); + equal( ua.getChildHTML( div ), '

    xxxxxxxx

    ', '没有空sibling' ); + var span = text.nextSibling; + domUtils.clearEmptySibling( span ); + equal( ua.getChildHTML( div ), '

    xxxxxxxx

    ' ); + /*左边有空sibling*/ + domUtils.clearEmptySibling( span.lastChild ); + equal( ua.getChildHTML( div ), '

    xxxxxxxx

    ', '左边有空sibling' ); + /*左右边有空sibling*/ + div.innerHTML = '

    \n\t\n\t\rxxxx

    '; + domUtils.clearEmptySibling( div.firstChild.lastChild.previousSibling ); + + //TODO 有空白文本的时候是否需要删除 + equal( div.innerHTML.toLocaleLowerCase(), '

    xxxx

    ', '左右边有空sibling' ); + /*左右多个连续的空inline sibling*/ + div.innerHTML = '\t\t
    '; + var div_new = document.getElementById( 'div' ); + domUtils.clearEmptySibling( div_new ); + equal( ua.getChildHTML( div ), '
    ', '连续空inline sibling' ); + /*左右边有空块元素*/ + div.innerHTML = '

    xxxx
    '; + domUtils.clearEmptySibling( div.firstChild.firstChild.nextSibling ); + equal( ua.getChildHTML( div ), '

    xxxx
    ', '左右边有空块元素' ); +} ); + +/*不能误删bookmark*/ +test( 'clearEmptySibling--bookmark', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + var r = te.obj[2]; + div.innerHTML = 'link'; + var a = div.firstChild.firstChild; + var link = a.firstChild; + r.selectNode( link ); + r.createBookmark(); + /*bookmark节点*/ + domUtils.clearEmptySibling( link ); + ok( /_baidu_bookmark_end/.test( link.nextSibling.id ), '右边的bookmark sibling没有删掉' ); + ok( /_baidu_bookmark_start/.test( link.previousSibling.id ), '左边的bookmark sibling没有删掉' ); +} ); + +test( 'clearEmptySibling--ignoreNext/ignorePrevious', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + /*ignoreNext*/ + div.innerHTML = '

    \n\t\n\t\rxxxx

    '; + domUtils.clearEmptySibling( div.firstChild.lastChild.previousSibling, true ); + equal( div.innerHTML.toLocaleLowerCase(), '

    xxxx

    ', 'ignore next' ); + /*ignorePrevious*/ + div.innerHTML = '

    \n\t\n\t\rxxxx

    '; + domUtils.clearEmptySibling( div.firstChild.lastChild.previousSibling, false, true ); + equal( ua.getChildHTML( div ), '

    xxxx

    ', 'ignore next' ); + /*ignorePrevious&&ignoreNext*/ + div.innerHTML = '

    \n\t\n\t\rxxxx

    '; + domUtils.clearEmptySibling( div.firstChild.lastChild.previousSibling, true, true ); + equal( ua.getChildHTML( div ), '

    xxxx

    ', 'ignore next&&previous' ); +} ); + +test( 'split--offset正常', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + div.innerHTML = 'span >'; + var span = div.firstChild; + domUtils.split( span.firstChild, 2 ); + equal( span.childNodes.length, 2, 'check child count' ); + equal( span.childNodes[0].data, 'sp', 'check firstChild' ); + equal( span.childNodes[1].data, 'an', 'check secondChild' ); +} ); + +test( 'split--offset=0', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + div.innerHTML = 'span >'; + var span = div.firstChild; + domUtils.split( span.firstChild, 0 ); + equal( span.childNodes.length, 2, 'check child count' ); + equal( span.childNodes[0].data, '', 'check firstChild' ); + equal( span.childNodes[1].data, 'span', 'check secondChild' ); +} ); + +test( 'split--offset=data.length', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + div.innerHTML = 'span >'; + var span = div.firstChild; + domUtils.split( span.firstChild, 4 ); + equal( span.childNodes.length, 2, 'check child count' ); + equal( span.childNodes[0].data, 'span', 'check firstChild' ); + equal( span.childNodes[1].data, '', 'check secondChild' ); +} ); + +/*求相对视窗的位置而不是实际位置*/ +//test( 'getXY', function() { +// var div = te.dom[2]; +// var domUtils = te.obj[3]; +// equal( domUtils.getXY( div )['x'], ua.findPosition( div )[0] - document.documentElement.scrollLeft, 'check X' ); +// equal( domUtils.getXY( div )['y'], ua.findPosition( div )[1] - document.documentElement.scrollTop, 'check Y' ); +// +//} ); + + +test( 'on--跨iframe加载', function() { + expect( 1 ); + var domUtils = te.obj[3]; + var op = { + onafterstart : function( f ) { + domUtils.on( f, 'load', function() { + ok( true, 'on load of iframe success' ); + } ); + }, + ontest : function() { + this.finish(); + } + }; + ua.frameExt( op ); +} ); + + +test( 'on- 给不同的dom元素绑定相同的事件', function() { + var domUtils = te.obj[3]; + expect( 2 ); + var div2 = document.body.appendChild( document.createElement( 'div' ) ); + div2.id = 'test2'; + te.dom.push( div2 ); + var handle = function( e ) { + ok( true, e.type + ' event triggered' ); + }; + domUtils.on( te.dom[2], 'mouseover', handle); + domUtils.on( te.dom[1], 'mouseover', handle ); + + ua.mouseover( te.dom[2] ); + ua.mouseover( te.dom[1] ); +} ); +test( 'on-多事件的字符串参数', function() { + var domUtils = te.obj[3]; + expect( 2 ); + var div2 = document.body.appendChild( document.createElement( 'div' ) ); + div2.id = 'test2'; + te.dom.push( div2 ); + var handle = function( e ) { + ok( true, e.type + ' event triggered' ); + }; + domUtils.on( te.dom[2], 'mouseover mousedown', handle); + + + ua.mouseover( te.dom[2] ); + ua.mousedown( te.dom[2] ); +} ); +test( 'un- 给不同的dom元素绑定相同的事件,解除一个,另一个仍然有效', function() { + var domUtils = te.obj[3]; + expect( 1 ); + var div2 = document.body.appendChild( document.createElement( 'div' ) ); + div2.id = 'test2'; + te.dom.push( div2 ); + var handle = function( e ) { + ok( true, e.type + ' event triggered' ); + }; + domUtils.on( te.dom[2], 'mouseover', handle); + domUtils.on( te.dom[1], 'mouseover', handle ); + domUtils.un( te.dom[2],'mouseover', handle ); + ua.mouseover( te.dom[2] ); + ua.mouseover( te.dom[1] ); +} ); +test( 'un-多事件的字符串参数', function() { + var domUtils = te.obj[3]; + expect( 0 ); + var div2 = document.body.appendChild( document.createElement( 'div' ) ); + div2.id = 'test2'; + te.dom.push( div2 ); + var handle = function( e ) { + ok( false, e.type + ' 没有注销' ); + }; + domUtils.on( te.dom[2], 'mouseover mousedown', handle); + + domUtils.un(te.dom[2],'mouseover mousedown',handle); + ua.mouseover( te.dom[2] ); + ua.mousedown( te.dom[2] ); + stop(); + setTimeout(function(){start()},2000) +} ); + +/*绑定多个事件*/ +test( 'on', function() { + var domUtils = te.obj[3]; + expect( 2 ); + domUtils.on( te.dom[2], ['mouseover','keypress'], function( e ) { + ok( true, e.type + ' event triggered' ); + } ); + ua.mouseover( te.dom[2] ); + ua.keypress( te.dom[2] ); +} ); +test( "test case sensitive", function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + if ( ua.browser.ie ) { + ok( true, 'IE下不支持诸如DOMNodeInserted等mutation事件' ); + return; + } + // ok(false, 'TODO: 添加大小写敏感事件的on绑定和un取消用例,比如DOMMouseScroll'); + expect( 2 ); + domUtils.on( div, 'DOMNodeInserted', function() { + ok( true, '用DOMNodeInserted测试大小写敏感事件的on绑定' ); + domUtils.un( div, 'DOMNodeInserted' ); + } ); + div.appendChild( document.createElement( 'div' ) ); + div.appendChild( document.createElement( 'div' ) ); +} ); + +test( "un--取消注册unload事件", function() { + expect( 1 ); + var domUtils = te.obj[3]; + var div = te.dom[2]; + var handle_a = function() { + ok( true, "check unload" ); + }; + domUtils.on( div, "click", handle_a ); + /* 直接调用ua提供的接口跨浏览器接口,屏蔽浏览器之间的差异 */ + ua.click( div ); + domUtils.un( div, "click", handle_a ); + ua.click( div ); +} ); + + +test( "un--同一个回调注册多个事件,后面事件会将第一个事件dhandler覆盖掉", function() { + expect( 1 ); + var domUtils = te.obj[3]; + var div = te.dom[2]; + var handle_a = function() { + ok( true, "应当只会执行一次" ); + }; + /* 直接调用ua提供的接口跨浏览器接口,屏蔽浏览器之间的差异 */ + domUtils.on( div, "click", handle_a ); + domUtils.on(div,'dbclick',handle_a); + ua.click( div ); + domUtils.un( div, "click", handle_a ); + ua.click( div ); +} ); + +test( "un--同一个回调同一个事件注册2次", function() { + expect( 1 ); + var domUtils = te.obj[3]; + var div = te.dom[2]; + var handle_a = function() { + ok( true, "check unload" ); + }; + /* 直接调用ua提供的接口跨浏览器接口,屏蔽浏览器之间的差异 */ + domUtils.on( div, "click", handle_a ); + domUtils.on(div,'click',handle_a); + ua.click( div ); + domUtils.un( div, "click", handle_a ); + ua.click( div ); +} ); + +test( "un--同一个事件取消注册三次", function() { + expect( 1 ); + var domUtils = te.obj[3]; + var div = te.dom[2]; + var handle_a = function() { + ok( true, "check unload" ); + }; + /* 直接调用ua提供的接口跨浏览器接口,屏蔽浏览器之间的差异 */ + domUtils.on( div, "click", handle_a ); + ua.click( div ); + domUtils.un( div, "click", handle_a ); + domUtils.un( div, "click", handle_a ); + domUtils.un( div, "click", handle_a ); + ua.click( div ); +} ); + +/** * 跨frame on然后un */ +test( "window resize", function() { + expect( 1 ); + var domUtils = te.obj[3]; + ua.frameExt( { + onafterstart : function( f ) { + $( f ).css( 'width', 200 ); + }, + ontest : function( w, f ) { + var op = this; + var fn = function() { + ok( true ); + }; + domUtils.on( w, 'resize', fn ); + $( f ).css( 'width', 220 ); + /* 貌似通过jquery触发窗体变化会存在延时 */ + setTimeout( function() { + domUtils.un( w, 'resize', fn ); + $( f ).css( 'width', 240 ); + setTimeout( op.finish, 100 ); + }, 500 ); + } } ); +} ); + + +test( 'isSameElement--compare with self', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + $( div ).attr( 'name', 'div_name' ).attr( 'class', 'div_class' ).css( 'background-color', 'red' ).css( 'border', '1px' ).css( 'font-size', '12px' ).css( 'height', '12px' ).css( 'width', '20px' ); + ok( domUtils.isSameElement( div, div ), 'compare with self' ); +} ); + +test( 'isSameElement--tagName不一样', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + div.appendChild( document.createElement( 'span' ) ); + $( div ).attr( 'name', 'div_name' ).attr( 'class', 'div_class' ).css( 'background-color', 'red' ).css( 'border', '1px' ).css( 'font-size', '12px' ).css( 'height', '12px' ).css( 'width', '20px' ); + ok( !domUtils.isSameElement( div, div.firstChild ), 'different tagName' ); +} ); + +//TODO 目前的判断有问题,ie下手动创建的img会自动添加一个complete属性,导致比较结果为false,因此不对img进行比较 +test( 'isSameElement--img的src和宽高比较', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + div.innerHTML = ''; + + var span = document.createElement( 'span' ); + span.setAttribute( 'src', 'http://img.baidu.com/hi/jx2/j_0001.gif' ); + span.setAttribute( 'height', '51' ); + span.setAttribute( 'width', '50' ); + div.appendChild( span ); + ok( domUtils.isSameElement( div.firstChild, div.lastChild ), '手动创建的img的src和宽高比较' ); +} ); + +test( 'isSameElement--两种元素的样式通过不同方式设置', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + $( div ).attr( 'name', 'div_name' ).attr( 'class', 'div_class' ).css( 'background-color', 'red' ).css( 'border', '1px' ).css( 'font-size', '12px' ).css( 'height', '12px' ).css( 'width', '20px' ); + var div_new = document.createElement( 'div' ); + document.body.appendChild( div_new ); + te.dom.push( div_new ); + div_new.innerHTML = '
    '; + ok( domUtils.isSameElement( div_new.firstChild, div ), 'is sameElement' ); + /*防止前后顺序引起的问题*/ + ok( domUtils.isSameElement( div, div_new.firstChild ), 'is sameElement' ); +} ); + +test( 'isSameElement--A比B多一个属性', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + div.innerHTML = ''; + var div_new = document.createElement( 'div' ); + document.body.appendChild( div_new ); + te.dom.push( div_new ); + div_new.innerHTML = ''; + ok( !domUtils.isSameElement( div_new.firstChild, div ), 'A and B is not sameElement' ); + ok( ! domUtils.isSameElement( div, div_new.firstChild ), 'B and A is not sameElement' ); +} ); + +test( 'isSameElement--img的属性比较', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; +// var editor = new baidu.editor.Editor(); +// editor.render(div); + div.innerHTML = 'hello'; + var div1 = document.createElement( 'div' ); + var html = ''; + div1.innerHTML = html; + ok( domUtils.isSameElement( div.firstChild, div1.firstChild ), '属性一致' ) +} ); + +/*暂时不会对颜色不同表达方式做转换*/ +//test( 'isSameElement--style描述方式不同', function() { +// var div = te.dom[2]; +// var domUtils = te.obj[3]; +// $( div ).attr( 'name', 'div_name' ).attr( 'class', 'div_class' ).css( 'background-color', 'red' ).css( 'border', '1px' ).css( 'font-size', '12px' ).css( 'height', '12px' ).css( 'width', '20px' ); +// var div_new = document.createElement( 'div' ); +// document.body.appendChild( div_new ); +// te.dom.push( div_new ); +// div_new.innerHTML = '
    '; +// ok( domUtils.isSameElement( div_new.firstChild, div ), 'A and B are sameElement' ); +// div_new.innerHTML = '
    '; +// ok( domUtils.isSameElement( div, div_new.firstChild ), 'B and A sameElement' ); +//} ); + +test( 'isSameElement--A比B多一个style属性', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + $( div ).attr( 'name', 'div_name' ).attr( 'class', 'div_class' ).css( 'background-color', 'red' ).css( 'border', '1px' ).css( 'font-size', '12px' ).css( 'height', '12px' ).css( 'width', '20px' ); + var div_new = document.createElement( 'div' ); + document.body.appendChild( div_new ); + te.dom.push( div_new ); + div_new.innerHTML = '
    '; + ok( !domUtils.isSameElement( div_new.firstChild, div ), 'A and B is not sameElement' ); + ok( ! domUtils.isSameElement( div, div_new.firstChild ), 'B and A is not sameElement' ); +} ); + +//test( 'isRedundantSpan--非span', function() { +// var div = te.dom[2]; +// var domUtils = te.obj[3]; +// div.innerHTML = 'text'; +// ok( !domUtils.isRedundantSpan( div ), 'not span' ); +// ok( !domUtils.isRedundantSpan( div.firstChild ), 'text node is not span' ); +//} ); +// +//test( 'isRedundentSpan', function() { +// var div = te.dom[2]; +// var domUtils = te.obj[3]; +// div.innerHTML = ''; +// ok( domUtils.isRedundantSpan( div.firstChild ), 'is redundentSapn' ); +// ok( !domUtils.isRedundantSpan( div.lastChild ), 'is not redundentSpan' ); +// var span = document.createElement( 'span' ); +// div.appendChild( span ); +// ok( domUtils.isRedundantSpan( span ), 'is redundent span' ); +//} ); + +/*rd说实际应用情况会按照固定的方式设置样式,因此不考虑兼容rgb(255,0,0),#ff0000,red这三者的差别*/ +test( 'isSameStyle', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + /*分号,空格*/ + div.innerHTML = ''; + ok( domUtils.isSameStyle( div.firstChild, div.lastChild ), 'have same style' ); +} ); + +test( 'isSameStyle--float', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + /*分号,空格*/ + div.innerHTML = ''; + ok( domUtils.isSameStyle( div.firstChild, div.lastChild ), 'have same style' ); + div.firstChild.style.cssText = "float:left;font-size:12px;background-color:red"; + ok( ! domUtils.isSameStyle( div.firstChild, div.lastChild ), 'have differtnt style' ); +} ); + + +test( 'isBlockElm', function() { + var div = te.dom[2]; + var domUtils = te.obj[3]; + /*isindex,noframes是特例,在这里不做验证*/ + var blockElms = ['address','blockquote','center','dir','div','dl','fieldset','form','h1','h2','h3','h4','h5','h6','hr','menu','ol','p','pre','table','ul']; + var k = blockElms.length; + while ( k ) { + var elm = document.createElement( blockElms[k - 1] ); + div.appendChild( elm ); + ok( domUtils.isBlockElm( elm ), elm.tagName + ' is block elm' ); + k--; + } + blockElms = ['a','abbr','acronym','b','bdo','big','br','cite','code','dfn','em','font','i','img','input','kbd','label','q','s','samp','select','small','span','strike','strong','sub','sp','textarea','tt','u','noscript' ]; + k = blockElms.length; + while ( k ) { + var elm = document.createElement( blockElms[k - 1] ); + div.appendChild( elm ); + ok( !domUtils.isBlockElm( elm ), elm.tagName + ' is not block elm' ); + k--; + } +} ); + +test( 'isbody', function() { + var domUtils = te.obj[3]; + ok( domUtils.isBody( document.body ), 'is body' ); +} ); + +/*parent参数是 node的直接父亲*/ +test( 'breakParent--一级祖先', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '

    xxxxuitext

    xxxx
    '; + var br = div.firstChild.lastChild; + var returnNode = domUtils.breakParent( br, div.firstChild ); + equal( ua.getChildHTML( div ), '

    xxxxuitext


    xxxx
    ' ); + equal( returnNode.tagName.toLowerCase(), 'br', 'check return value' ); +} ); + +/*parent参数是 node的祖先节点*/ +test( 'breakParent--二级祖先', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '

    xxxxuitext

    xxxx
    '; + domUtils.breakParent( div.firstChild.firstChild.firstChild, div.firstChild ); + equal( ua.getChildHTML( div ), '

    xxxx

    uitext

    xxxx
    ' ); +} ); +/*bookMark已在clearEmptySibling中验证*/ +test( 'isEmptyInlineElement', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '

    xxxxuitext

    xxxx
    '; + var p = div.firstChild; + /*非空元素*/ + ok( !domUtils.isEmptyInlineElement( p ), 'is not empty' ); + /*空inline元素*/ + ok( domUtils.isEmptyInlineElement( p.firstChild ), 'u is empty' ); + ok( domUtils.isEmptyInlineElement( p.firstChild.firstChild ), 'em is empty' ); + /*块元素*/ + ok( !domUtils.isEmptyInlineElement( p.lastChild ), 'empty div is not inline' ); +} ); + +test( 'trimWhiteTextNode', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '\n\t

    xxxxuitext

    xxxx
    '; + domUtils.trimWhiteTextNode( div ); + equal( ua.getChildHTML( div ), '

    xxxxuitext

    xxxx
    ', 'trim white textnode' ); +} ); + +/*适用于inline节点*/ +test( 'mergeChild--span', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + + var div_new = document.createElement( 'div' ); + div_new.id = 'test'; + div.innerHTML = 'span_1span_2'; + domUtils.mergeChild( div.firstChild.firstChild ); + /*span套span则进行合并*/ + div_new.innerHTML = 'span_1'; + div_new.firstChild.firstChild.appendChild( document.createTextNode( 'span_2' ) ); + ok( ua.haveSameAllChildAttribs( div, div_new ), 'span套span则合并' ); + + div.innerHTML = '

    span_1span_2

    '; + domUtils.mergeChild( div.firstChild.firstChild ); + /*父节点style比子节点多,删去子节点*/ + div_new.innerHTML = '

    span_1

    ' || ua.getChildHTML( div ) == '

    span_1span_2

    '; + div_new.firstChild.firstChild.appendChild( document.createTextNode( 'dpan_2' ) ); + ok( ua.haveSameAllChildAttribs( div, div_new ), '父节点style比子节点多' ); + /*子节点style比父节点多,则不作调整*/ + div.innerHTML = '

    span_1span_2

    '; + var span = div.firstChild.firstChild; + domUtils.mergeChild( span ); + /*创建一个div,div的innerHTML与预期的结果相同,比较div_new与div的所有属性,从而判断style为预期结果*/ + var div_new = document.createElement( 'div' ); + div_new.id = 'test'; + div_new.innerHTML = '

    span_1span_2

    '; + ok( ua.haveSameAllChildAttribs( div, div_new ), '子节点style比父节点多' ); + + /*多个子节点和兄弟节点,有的子节点style比父节点多,有的少,有的不同*/ + div.innerHTML = '

    span_1span_2span_3span_4

    '; + domUtils.mergeChild( div.firstChild.firstChild ); + div_new.innerHTML = '

    span_2span_3span_4

    '; + var span1 = div_new.firstChild.firstChild; + span1.insertBefore( document.createTextNode( 'span_1' ), span1.firstChild ); + ok( ua.haveSameAllChildAttribs( div, div_new ), '多个子节点和兄弟节点,有的子节点style比父节点多,有的少,有的不同' ); +} ); + + +test( 'mergeChild--非span', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + /*父节点和子节点属性不同*/ + div.innerHTML = 'b1b2'; + var div_new = document.createElement( 'div' ); + div_new.id = 'test'; + div_new.innerHTML = 'b1b2'; + domUtils.mergeChild( div.firstChild ); + ok( ua.haveSameAllChildAttribs( div, div_new ), '父节点和子节点属性不同,则不操作' ); + /*父节点和子节点属性相同*/ + div.innerHTML = 'b1b2'; + var div_new = document.createElement( 'div' ); + div_new.id = 'test'; + div_new.innerHTML = 'b1'; + domUtils.mergeChild( div.firstChild ); + div_new.firstChild.appendChild( document.createTextNode( 'b2' ) ); + ok( ua.haveSameAllChildAttribs( div, div_new ), '父节点和子节点属性相同,则删子节点' ); +} ); +test( 'mergeChild--span--attrs', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + var div_new = document.createElement( 'div' ); + div_new.id = 'test'; + div.innerHTML = 'span_1span_2'; + var html = 'span_1span_2'; + domUtils.mergeChild( div.firstChild ,'span',{style:'background-color:red'}); + ua.checkSameHtml(div.innerHTML,html,'mergeChild-给子节点中的span添加样式'); +} ); +test( 'getElementsByTagName', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '

    xxxxuitext

    xxxx

    xxxx

    '; + var elms = domUtils.getElementsByTagName( div, 'p' ); + equal( elms.length, 2, 'check elem count' ); + equal( elms[0].innerHTML.toLowerCase(), 'xxxxuitext
    ', 'check first p' ); + equal( elms[1].innerHTML, 'xxxx', 'check second p' ); +} ); + +test( 'mergeToParent--一个span孩子', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = ''; + domUtils.mergeToParent( div.firstChild.firstChild ); + var div_new = document.createElement( 'div' ); + div_new.innerHTML = ''; + ok( ua.haveSameAllChildAttribs( div, div_new ), 'mergeTo parent' ); +} ); + +test( 'mergeToParent--一个span孩子,孩子css样式与父节点相同', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = 'xxxxx'; + domUtils.mergeToParent( div.firstChild.firstChild ); + var div_new = document.createElement( 'div' ); + div_new.innerHTML = 'xxxxx'; + ok( ua.haveSameAllChildAttribs( div, div_new ), 'mergeTo parent,删除样式相同的子节点' ); +} ); + +test( 'mergeToParent--多个span孩子,祖先节点不可被合并', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = ''; + domUtils.mergeToParent( div.firstChild.firstChild ); + var div_new = document.createElement( 'div' ); + div_new.innerHTML = ''; + ok( ua.haveSameAllChildAttribs( div, div_new ), 'mergeTo parent--多个span孩子,' ); +} ); + +//test( 'mergeToParent--a', function() { +// var div = te.dom[2]; +// var domUtils = baidu.editor.dom.domUtils; +// div.innerHTML = 'www.baidu.com'; +// +// +//} ); + + +test( 'mergeToParent--其他inline节点', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = 'xxxxxxxxxxxxxxxxxxx'; + var i = document.getElementById( 'secondI' ); + domUtils.mergeToParent( i.firstChild ); + ok( ua.getChildHTML( div ), 'xxxxxxxxxxxxxxxxxxx' ); + domUtils.mergeToParent( i ); + ok( ua.getChildHTML( div ), 'xxxxxxxxxxxxxxxxxxx' ); +} ); + +/*合并兄弟节点中有相同属性包括style的节点*/ +test( 'mergeSibling--左边没有兄弟', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = 'b1b2b3'; + domUtils.mergeSibling( div.firstChild ); + ok( ua.getChildHTML( div ), 'b1b2b3' ); +} ); + +test( 'mergeSibling--右边没有兄弟', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = 'b1b2b3'; + domUtils.mergeSibling( div.lastChild ); + ok( ua.getChildHTML( div ), 'b1b2b3' ); +} ); + + +test( 'mergeSibling--兄弟节点没有孩子', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = 'b2b3'; + domUtils.mergeSibling( div.firstChild.nextSibling ); + ok( ua.getChildHTML( div ), 'b2b3' ); +} ); + + +test( 'trace 3983 unselectable--检查赋值是否成功', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '

    xxxxxxxxxxx

    dddd

    aaaa

    '; + debugger + domUtils.unSelectable( div ); + if ( UE.browser.gecko || UE.browser.webkit || (UE.browser.ie &&UE.browser.version>8) ) { + equal( div.style.MozUserSelect || div.style.KhtmlUserSelect || div.style.MSUserSelect, 'none', 'webkit or gecko unselectable' ); + } else { + equal( div.unselectable, 'on', '检查unselectable属性' ); + for ( var i = 0,ci; ci = div.all[i++]; ) { + equal( ci.unselectable, 'on', '检查子节点unselectable属性' ); + } + } +} ); + +test( 'unselectable--检查是否真的不能选中', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '

    xxx

    '; + //TODO ie下如何选中文本节点需要重新想一想,用程序选择文本貌似不会考虑unselectable属性,都是可以选中的 + if ( ! ua.browser.ie && !ua.browser.opera) { +// var rng = document.body.createTextRange(); +// domUtils.unselectable( div ); +// rng.moveToElementText( div ) +// /*开始位置处向前移动一个字符,结束位置处向后移动一个字符*/ +// rng.moveEnd( 'character', 1 ); +// rng.moveStart( 'character', -1 ); +// rng.select(); +// equal( rng.text, '', 'after unselectable' ); +// } else { + var r = te.obj[2]; + r.selectNode( div.firstChild ).select(); + equal( ua.getSelectedText(), 'xxx', 'before unselectable' ); + /*禁止选中*/ + domUtils.unSelectable( div ); + r.selectNode( div.firstChild ).select(); + equal( ua.getSelectedText(), '', 'after unselectable' ); + } +} ); + +/*不支持第二个参数为字符串,必须为数组*/ +//test( 'removeAttributes--删除一个属性', function() { +// var div = te.dom[2]; +// div.innerHTML = '
    '; +// var domUtils = baidu.editor.dom.domUtils; +// domUtils.removeAttributes( div.firstChild, 'class' ); +// equal( ua.getChildHTML( div ), '
    ' ); +//} ); + +test( 'removeAttributes--删除多个属性,包括style', function() { + var div = te.dom[2]; + div.innerHTML = '
    '; + var domUtils = baidu.editor.dom.domUtils; + /*诡异模式下className可以删除,而非诡异模式下不能删除*/ + domUtils.removeAttributes( div.firstChild, ['class','name','style'] ); + equal( ua.getChildHTML( div ), '
    ' ); +} ); + +test( 'setAttributes--设置class,style', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '
    '; + domUtils.setAttributes( div.firstChild, {'class':'div_class','id':'div_id','style':'color:red;font-size:12px;'} ); + var div_new = document.createElement( 'div' ); + div_new.id = 'test'; + div_new.innerHTML = '
    '; + ok( ua.haveSameAllChildAttribs( div, div_new ), 'check attributes' ); +} ); +test( 'setAttributes--设置innerHTML,value', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '
    '; + domUtils.setAttributes( div.firstChild, {'innerHTML':'setAttributes_test','id':'div_id','value':'abcd'} ); + var div_new = document.createElement( 'div' ); + div_new.id = 'test'; + div_new.innerHTML = '
    setAttributes_test
    '; + div_new.firstChild.value="abcd"; + ok( ua.haveSameAllChildAttribs( div, div_new ), 'check attributes' ); +} ); +test( 'getComputedStyle', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '
    '; + equal( domUtils.getComputedStyle( div.firstChild, 'font-size' ), '12px' ); + equal( domUtils.getComputedStyle( div.firstChild, 'display' ), 'block' ); + equal( domUtils.getComputedStyle( div.lastChild, 'display' ), 'inline' ); + equal( domUtils.getComputedStyle( div.firstChild, 'width' ),div.firstChild.offsetWidth + 'px'); + div.innerHTML = '
    '; + equal( domUtils.getComputedStyle( div.firstChild, 'width' ),'30px'); +} ); + +test( 'getComputedStyle--获取默认的背景色', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '
    hello
    '; + /*chrome下不作特殊处理得到的结果是rgba(0,0,0,0),处理后是结果是“”*/ + var result = baidu.editor.browser.webkit ? "" : "transparent"; + equal( domUtils.getComputedStyle( div, 'background-color' ), result, '默认背景色为透明色' ); +} ); + +test( 'getComputedStyle-border', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '
    '; + equal( domUtils.getComputedStyle( div.firstChild, 'border-width' ), '5px' ); + equal( domUtils.getComputedStyle( div.lastChild, 'border-style' ), 'solid' ); + equal( domUtils.getComputedStyle( div.lastChild, 'border-color' ), 'red' ); +} ); +//修复ie下的一个bug,如果在body上强制设了字体大小,h1的字体大小就会继承body的字体,而没有办法取到真是的字体大小 +test( 'getComputedStyle-在body上设置字体大小,检查h1字体大小', function() { + var domUtils = baidu.editor.dom.domUtils; + var editor = new baidu.editor.Editor({'autoFloatEnabled':false}); + var div = document.body.appendChild( document.createElement( 'div' ) ); + editor.render( div ); + stop(); + editor.ready(function(){ + var body = editor.body; + var range = new baidu.editor.dom.Range( editor.document ); + var h1 = body.appendChild( editor.document.createElement( 'h1' ) ); +// editor.body.style['fontSize'] = '10px'; +// h1的字体大小不是10px + var fontSize = (ua.browser.ie&&ua.browser.ie<9)?'33px':'32px';//todo 1.2.7 trace 3588 + equal( domUtils.getComputedStyle( h1, 'font-size' ), fontSize, 'body的fontSize属性不应当覆盖p的fontSize属性' ); + te.dom.push(div); +// editor.setContent( '

    这是h2的文本这是一个超链接

    ' ); + start(); + }); +} ); + +/*不支持一个class的删除,必须为一个数组*/ +//test( 'removeClasses--一个class', function() { +// var div = te.dom[2]; +// var domUtils = baidu.editor.dom.domUtils; +// div.innerHTML = '
    '; +// domUtils.removeClasses( div.firstChild, 'div_class' ); +// ok( ua.getChildHTML( div ) == '
    ' || ua.getChildHTML( div ) == '
    ' ); +//} ); + +test( 'removeClasses--多个class', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '
    '; + var divChild = div.firstChild; + domUtils.removeClasses( divChild, ['div_class2' ,'div_class3','div_class'] ); + equal( $.trim( divChild.className ), "", 'check className' ); + equal( $( divChild ).attr( 'name' ), 'div_name', 'check name' ); + equal( $( divChild ).css( 'font-size' ), '12px', 'check font-size' ); + equal( $( divChild ).css( 'font-size' ), '12px', 'check font-size' ); + equal( divChild.style[ 'color'], 'red', 'check red' ); +} ); + +test( 'removeClasses--class包含”-“', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '
    '; + var divChild = div.firstChild; + domUtils.removeClasses( divChild, ['b-b'] ); + equal( $.trim( divChild.className ), "b-b-a", 'check className' ); + equal( $( divChild ).attr( 'name' ), 'div_name', 'check name' ); + equal( $( divChild ).css( 'font-size' ), '12px', 'check font-size' ); + equal( divChild.style[ 'color'], 'red', 'check red' ); + div.innerHTML = '
    '; + domUtils.removeClasses( div.firstChild, ' b-b-a b-b' ); + equal(div.firstChild.className,'') +} ); + +test( 'removeStyle--style不为空', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '
    '; + domUtils.removeStyle( div.firstChild, 'font-size' ); + var div_new = document.createElement( 'div' ); + div_new.id = 'test'; + div_new.innerHTML = '
    '; + ok( ua.haveSameAllChildAttribs( div, div_new ), 'check removed style' ); + +} ); +test( 'removeStyle--style不为空', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '
    '; + domUtils.removeStyle( div.firstChild, 'border-left' ); + var div_new = document.createElement( 'div' ); + div_new.id = 'test'; + div_new.innerHTML = '
    '; + ok( ua.haveSameAllChildAttribs( div, div_new ), 'check removed style' ); + +} ); +test( 'removeStyle--style为空', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '
    '; + domUtils.removeStyle( div.firstChild, 'color' ); + equal( ua.getChildHTML( div ), '
    ', ' style为空' ); +} ); + +test( 'hasClass', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '
    '; + var divChild = div.firstChild; + ok( domUtils.hasClass( divChild, 'div_class3' ), '有这个class' ); + ok( !domUtils.hasClass( divChild, 'div' ), '木有这个class' ); + div.firstChild.className = 'a b c'; + ok(domUtils.hasClass(div.firstChild,'b c a')) +} ); + +test( 'addClass', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '
    '; + domUtils.addClass(div.firstChild,'div_class div_class2 div_class3'); + equal(utils.trim(div.firstChild.className),div.firstChild.className,'判断是否有前后空格'); + domUtils.addClass(div.firstChild,'div_class4'); + equal(div.firstChild.className,'div_class div_class2 div_class3 div_class4','增加class4'); + domUtils.addClass(div.firstChild,'div_class4'); + equal(div.firstChild.className,'div_class div_class2 div_class3 div_class4','再增加class4'); +} ); + +test( "preventDefault", function() { + expect( 1 ); + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + /*img用来撑大页面*/ + var img = document.createElement( 'img' ); + img.src = upath + 'test.jpg'; + img.style.height = "2000px"; + div.appendChild( img ); + document.body.appendChild( div ); + var a = document.createElement( 'a' ); + a.setAttribute( "href", "#" ); + a.innerHTML = 'ToTop'; + a.target = '_self'; + document.body.appendChild( a ); + window.scrollTo( 0, document.body.scrollHeight ); + +// UserAction.beforedispatch = function( e ) { +// e = e || window.event; +// domUtils.preventDefault( e ); +// }; + a.onclick = function( e ) { + domUtils.preventDefault( e ); + } + UserAction.click( a ); + var top = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; + ok( top != 0, "preventDefault" ); + document.body.removeChild( a ); +} ); + +test( 'getStyle--color is red', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '
    '; + equal( domUtils.getStyle( div.firstChild, 'color' ), 'red', 'check color' ); + equal( domUtils.getStyle( div.firstChild, 'font-size' ), '12px', 'check font size' ); + equal( domUtils.getStyle( div.firstChild, 'top' ), '13px', 'check top' ); +} ); + +test( 'getStyle--color is rgb', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '
    '; + equal( domUtils.getStyle( div.firstChild, 'color' ), '#FF0000', 'check color' ); + equal( domUtils.getStyle( div.firstChild, 'font-size' ), '12px', 'check font size' ); + equal( domUtils.getStyle( div.firstChild, 'top' ), '13px', 'check top' ); +} ); + +test( 'getStyle--color is #ff0000', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '
    '; + equal( domUtils.getStyle( div.firstChild, 'color' ).toUpperCase(), '#FF0000', 'check color' ); + equal( domUtils.getStyle( div.firstChild, 'font-size' ), '12px', 'check font size' ); + equal( domUtils.getStyle( div.firstChild, 'top' ), '13px', 'check top' ); +} ); + + +//test( 'getStyle--border', function() { +// var div = te.dom[2]; +// div.innerHTML = '
    '; +//} ); +test( 'removeDirtyAttr', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '
    xxx
    xx'; + $( div ).attr( '_moz_dirty', 'xxxx' ); + for ( var i = 0,ci,nodes = div.getElementsByTagName( '*' ); ci = nodes[i++]; ) { + $( ci ).attr( '_moz_dirty', 'xxx' ); + } + domUtils.removeDirtyAttr( div ); + + for ( var i = 0,ci,nodes = div.getElementsByTagName( '*' ); ci = nodes[i++]; ) { + equal( $( ci ).attr( '_moz_dirty' ), undefined, 'check dirty attr ' ); + } + equal( $( div ).attr( '_moz_dirty' ), undefined, 'check dirty attr' ); +} ); + +test( 'getChildCount', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '

    xxx

    xxxxxxxxxx
    '; + var divChild = div.firstChild; + equal( domUtils.getChildCount( div ), 1, 'one childNode' ); + equal( domUtils.getChildCount( divChild ), 5, '5 childs' ); + equal( domUtils.getChildCount( divChild.firstChild.firstChild ), 2, 'inline span' ); + equal( domUtils.getChildCount( divChild.lastChild ), 0, 'text node have no child' ); + equal( domUtils.getChildCount( divChild.lastChild.previousSibling ), 0, 'img have no child' ); + +} ); + +test( 'setStyle', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '

    '; + /*修改float值*/ + domUtils.setStyle( div.firstChild, 'float', 'right' ); + equal( $( div.firstChild ).css( 'float' ), 'right', '浮动方式改为了right' ); + domUtils.setStyle( div.firstChild.firstChild, 'text-indent', '10px' ); + equal( $( div.firstChild.lastChild ).css( 'text-indent' ), '10px', '设置了缩进样式' ); +} ); + +test( 'setStyles', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = '

    '; + /*修改float值*/ + domUtils.setStyles( div.firstChild, {'float':'right','text-align':'center'} ); + equal( $( div.firstChild ).css( 'float' ), 'right', '浮动方式改为了right' ); + equal( $( div.firstChild.lastChild ).css( 'text-align' ), 'center', '设置了对齐方式样式' ); +} ); + +//zhuwenxuan add +//test( 'clearReduent', function() { +// var div = te.dom[2]; +// var domUtils = baidu.editor.dom.domUtils; +// //没有内容 +// div.innerHTML = '
    '; +// document.body.appendChild(div); +// domUtils.clearReduent(div,["i","b"]); +// ok( "
    ",div.innerHTML ); +// //有内容 +// div.innerHTML = '
    ddd
    '; +// domUtils.clearReduent(div,["i","b"]); +// ok( "
    ddd
    ",div.innerHTML ); +// div.innerHTML = '
    ddd
    '; +// domUtils.clearReduent(div,["i","b"]); +// ok( "
    ddd
    ",div.innerHTML ); +//} ); + + +//zhuwenxuan add +test( 'isEmptyNode', function() { + var div = te.dom[2]; + var domUtils = baidu.editor.dom.domUtils; + div.innerHTML = " \t\t\n\r"; + ok(domUtils.isEmptyNode(div)); + div.innerHTML = '
    dasdf
    '; + equal(false,domUtils.isEmptyNode(div)); +} ); + +//zhuwenxuan add +test( 'clearSelectedArr', function() { + var domUtils = baidu.editor.dom.domUtils; + var div = te.dom[2]; + var span = document.createElement("span"); + div.className = "aaa"; + span.className = "span"; + document.body.appendChild(div); + document.body.appendChild(span); + var arr = []; + arr.push(div); + arr.push(span); + domUtils.clearSelectedArr(arr); + equal("",div.className); + equal("",span.className); +} ); + + +//zhuwenxuan add +test( 'isBr', function() { + var domUtils = baidu.editor.dom.domUtils; + var div = te.dom[2]; + div.innerHTML = "
    "; + equal(true,domUtils.isBr(div.firstChild)); +} ); + +//zhuwenxuan add +test( 'isFillChar', function() { + var domUtils = baidu.editor.dom.domUtils; + var div = te.dom[2]; + domUtils.fillNode(document,div); + if(ua.browser.ie){ + ok(domUtils.isFillChar(div.lastChild)); + } + var node = document.createTextNode(domUtils.fillChar + 'sdfsdf'); + ok(domUtils.isFillChar(node,true)); + ok(!domUtils.isFillChar(node)); + node = document.createTextNode(domUtils.fillChar +domUtils.fillChar); + ok(domUtils.isFillChar(node,true)); + ok(domUtils.isFillChar(node)) +} ); + + +//zhuwenxuan add +test( 'isStartInblock', function() { + var domUtils = baidu.editor.dom.domUtils; + var div = te.dom[2]; + var range = new baidu.editor.dom.Range( document ); + domUtils.fillNode(document,div); + range.setStart(div,0); + ok(domUtils.isStartInblock(range)); + div.innerHTML = "asdfasdf"; + range.setStart(div,2); + equal(0,domUtils.isStartInblock(range)) +} ); + +//zhuwenxuan add +test( 'isEmptyBlock', function() { + var domUtils = baidu.editor.dom.domUtils; + var div = te.dom[2]; + domUtils.fillNode(document,div); + ok(domUtils.isEmptyBlock(div)); + var span = document.createElement("span"); + equal(1,domUtils.isEmptyBlock(span)); + span.innerHTML = "asdf"; + equal(0,domUtils.isEmptyBlock(span)); +} ); + +//zhuwenxuan add +test( 'fillNode', function() { + var domUtils = baidu.editor.dom.domUtils; + var div = te.dom[2]; + domUtils.fillNode(document,div); + ok(div.innerHTML.length>0); +} ); + +//zhuwenxuan add +test( 'moveChild', function() { + var domUtils = baidu.editor.dom.domUtils; + var div = te.dom[2]; + div.innerHTML = "div child"; + var p = document.createElement("p"); + domUtils.moveChild(div,p); + equal("div child",p.innerHTML); + p.innerHTML = ""; + div.innerHTML = "asdf"; + domUtils.moveChild(div,p); + equal("asdf",p.innerHTML.toLowerCase()); +} ); + +test( 'hasNoAttributes', function() { + var domUtils = baidu.editor.dom.domUtils; + var div = te.dom[2]; + div.innerHTML = "sdf"; + + ok(domUtils.hasNoAttributes(div.firstChild)); + div.firstChild.style.cssText = 'font-size:12px'; + ok(!domUtils.hasNoAttributes(div.firstChild)); + domUtils.removeAttributes(div.firstChild,['style']); + ok(domUtils.hasNoAttributes(div.firstChild)); + div.innerHTML = 'sf'; + ok(!domUtils.hasNoAttributes(div.firstChild)); + +} ); +test( 'isTagNode', function() { + var domUtils = baidu.editor.dom.domUtils; + var div = te.dom[2]; + div.innerHTML = "

    sdf

    "; + ok(domUtils.isTagNode(div.firstChild,"p")); + ok(domUtils.isTagNode(div.firstChild.firstChild,"span")); +} ); +test( 'filterNodelist', function() { + var div = te.dom[2]; + div.innerHTML = ''; + var arr = domUtils.filterNodeList(div.getElementsByTagName('*'),'i span'); + equals(arr.tagName,"SPAN"); + arr = domUtils.filterNodeList(div.getElementsByTagName('*'),'i'); + equals(arr.tagName,'I'); + arr = domUtils.filterNodeList(div.getElementsByTagName('*'),function(n){ + return n.tagName == 'SPAN' + }); + equals(arr.tagName,'SPAN'); + arr = domUtils.filterNodeList(div.getElementsByTagName('*'),function(n){ + return n.tagName == 'SPAN' + },true); + equals(arr.length,2) +} ); + +test('inNodeEndBoundary',function(){ + var div = te.dom[2]; + div.innerHTML = "spanaasp"; + var range = te.obj[2]; + range.setStart(div.firstChild.lastChild.firstChild,2).collapse(1).select(); + range.createBookmark(); + ok(domUtils.isInNodeEndBoundary(range,div.firstChild),'firstchild.lastchild边界'); + range.setStart(div.firstChild.firstChild.firstChild,4).collapse(1).select(); + range.createBookmark(); + ok(!domUtils.isInNodeEndBoundary(range,div.firstChild),'firstchild.firstchild边界'); + range.setStart(div.lastChild.firstChild,2).collapse(1).select(); + range.createBookmark(); + ok(domUtils.isInNodeEndBoundary(range,div),'lastchild边界'); +}); + +//test( '闭合选区,标签边界', function() { +// var domUtils = baidu.editor.dom.domUtils; +// var div = te.dom[2]; +// var editor = new baidu.editor.ui.Editor({autoFloatEnabled:true}); +// editor.render( div ); +// var range = new baidu.editor.dom.Range( editor.document ); +// editor.setContent( 'a_text1a_text2' ); +// var a = editor.body.firstChild.firstChild; +// range.setStart( a, 0 ).collapse( 1 ).select(); +// same( domUtils.findTagNamesInSelection( range, ['h2','a','p'] ), a, '选区位置为(a,0)' ); +// range.setStart( a, 1 ).collapse( 1 ).select(); +// same( domUtils.findTagNamesInSelection( range, ['h2','a','p'] ), a, '选区位置为(a,1)' ); +// +// range.setStart( a.parentNode, 1 ).collapse( 1 ).select(); +// same( domUtils.findTagNamesInSelection( range, ['h2','a','p'] ), a.parentNode, '选区位置为(p,1)' ); +// same( domUtils.findTagNamesInSelection( range, ['h2','a'] ), null, '选区位置为(p,1),但是不符合查找的条件' ); +//} ); + +//test( '文本闭合选区中查找是否包含特定的标签列表', function() { +// var domUtils = baidu.editor.dom.domUtils; +// var editor = new baidu.editor.ui.Editor({autoFloatEnabled:true}); +// var div = te.dom[2]; +// editor.render( div ); +// var range = new baidu.editor.dom.Range( editor.document ); +// var body = editor.body; +// +// editor.setContent( '

    我是测试的header:h2

    xx乐乐乐乐x我是标签

    ' ); +// var expectH2 = editor.document.getElementById( 'tt-h2' ), +// expectA = editor.document.getElementById( 'tt-a' ); +// +// //闭合情况下,文本节点里 +// var textH2 = body.firstChild.firstChild; +// range.setStart( textH2, 2 ).collapse( true ).select(); +// ok( expectH2 === domUtils.findTagNamesInSelection( range, ['h2', 'a', 'h3'] ), '闭合情况下,cursor在h2中,tag顺序:[h2, a, h3]' ); +// range.setStart( textH2, 0 ).collapse( true ).select(); +// ok( expectH2 === domUtils.findTagNamesInSelection( range, ['h2', 'a', 'h3'] ), '闭合情况下,cursor在h2的左边界,tag顺序:[h2, a, h3]' ); +// range.setStart( textH2, 14 ).collapse( true ).select(); +// ok( expectH2 === domUtils.findTagNamesInSelection( range, ['h2', 'a', 'h3'] ), '闭合情况下,cursor在h2的右边界,tag顺序:[h2, a, h3]' ); +// +// var p = editor.document.getElementsByTagName('p')[0]; +// var textA = p.lastChild.firstChild; +// range.setStart( textA, 2 ).collapse( true ).select(); +// ok( expectA === domUtils.findTagNamesInSelection( range, ['h2', 'a', 'h3'] ), '闭合情况下,cursor在a中,tag顺序:[h2, a, h3]' ); +// range.setStart( textA, 0 ).collapse( true ).select(); +// ok( expectA === domUtils.findTagNamesInSelection( range, ['h2', 'a', 'h3'] ), '闭合情况下,cursor在a的左边界,tag顺序:[h2, a, h3]' ); +// range.setStart( textA, 4 ).collapse( true ).select(); +// ok( expectA === domUtils.findTagNamesInSelection( range, ['h2', 'a', 'h3'] ), '闭合情况下,cursor在a的右边界,tag顺序:[h2, a, h3]' ); +// +// var textStrong = p.firstChild.firstChild; +// range.setStart( textStrong, 2 ).collapse( true ).select(); +// ok( null == domUtils.findTagNamesInSelection( range, ['h2', 'a', 'h3'] ), '闭合情况下,cursor在p中,tag顺序:[h2, a, h3]' ); +// range.setStart( textStrong, 0 ).collapse( true ).select(); +// ok( null == domUtils.findTagNamesInSelection( range, ['h2', 'a', 'h3'] ), '闭合情况下,cursor在p的左边界,tag顺序:[h2, a, h3]' ); +// range.setStart( textStrong, 7 ).collapse( true ).select(); +// ok( null == domUtils.findTagNamesInSelection( range, ['h2', 'a', 'h3'] ), '闭合情况下,cursor在p的右边界,tag顺序:[h2, a, h3]' ); +//} ); + + +//test( '不闭合选区中查找,如果包含,则返回第一个dom节点', function() { +// var domUtils = baidu.editor.dom.domUtils; +// var editor = new baidu.editor.ui.Editor({autoFloatEnabled:true}); +// var div = te.dom[2]; +// editor.render( div ); +// var range = new baidu.editor.dom.Range( editor.document ); +// var body = editor.body; +// +// editor.setContent( '

    我是测试的header:h2

    xx乐乐乐乐x我是标签

    ' ); +// var expectH2 = editor.document.getElementById( 'tt-h2' ), +// expectA = editor.document.getElementById( 'tt-a' ); +// var textH2 = body.firstChild.firstChild; +// range.setStart( textH2, 3 ).setEnd( textH2, 9 ).select(); +// ok( expectH2 === domUtils.findTagNamesInSelection( range, ['h2', 'a', 'h3'] ), '选中单个节点的一部分:tag顺序:[h2, a, h3]' ); +// ok( expectH2 === domUtils.findTagNamesInSelection( range, ['a', 'h2', 'h3'] ), '选中单个节点的一部分:tag顺序:[a, h2, h3]' ); +// +// range.setStart( textH2, 0 ).setEnd( textH2, 14 ).select(); +// ok( expectH2 === domUtils.findTagNamesInSelection( range, ['h2', 'a', 'h3'] ), '选中单个节点的全部:tag顺序:[h2, a, h3]' ); +// ok( expectH2 === domUtils.findTagNamesInSelection( range, ['a', 'h2', 'h3'] ), '选中单个节点的全部:tag顺序:[a, h2, h3]' ); +// +// var p = editor.document.getElementsByTagName('p')[0]; +// range.setStart( textH2, 0 ).setEnd(p.lastChild.firstChild, 3 ).select(); +// ok( expectH2 === domUtils.findTagNamesInSelection( range, ['h2', 'a', 'h3'] ), '跨节点选中:tag顺序:[h2, a, h3]' ); +// ok( expectA === domUtils.findTagNamesInSelection( range, ['a', 'h2', 'h3'] ), '跨节点选中:tag顺序:[a, h2, h3]' ); +//} ); + +//test( '不闭合选区,选区包含前半个半个标签', function() { +// var domUtils = baidu.editor.dom.domUtils; +// var editor = new baidu.editor.ui.Editor({autoFloatEnabled:true}); +// var div = te.dom[2]; +// editor.render( div ); +// var body = editor.body; +// var range = new baidu.editor.dom.Range( editor.document ); +// editor.setContent( '

    这是h2的文本这是一个超链接

    ' ); +// var a = body.firstChild.lastChild; +// range.setStart( body, 0 ).setEnd( a.firstChild, 3 ).select(); +// same( domUtils.findTagNamesInSelection( range, ['a','h2','body','p'] ), a, '选择h2和a的前半部分标签,找到第一个为a' ); +// /*调换查找的数组中元素的顺序*/ +// same( domUtils.findTagNamesInSelection( range, ['h2','a','body','p'] ), body.firstChild, '选择h2和a的前半部分标签,找到第一个为h2' ); +//} ); + +//test( '不闭合选区,选区包含后半个标签', function() { +// var domUtils = baidu.editor.dom.domUtils; +// var editor = new baidu.editor.ui.Editor({autoFloatEnabled:true}); +// var div = te.dom[2]; +// editor.render( div ); +// var body = editor.body; +// var range = new baidu.editor.dom.Range( editor.document ); +// editor.setContent( '

    这是h2的文本这是一个超链接

    ' ); +// var a = body.firstChild.lastChild; +// range.setStart( a.firstChild, 3 ).setEnd( body, 1 ).select(); +// same( domUtils.findTagNamesInSelection( range, ['a','h2','body','p'] ), a, '选择h2和a的后部分标签,找到第一个为a' ); +// /*调换查找的数组中元素的顺序*/ +// same( domUtils.findTagNamesInSelection( range, ['h2','a','body','p'] ), body.firstChild, '选择h2和a的后部分标签,找到第一个为h2' ); +//} ); + +//test( '不闭合选区,选区包含2个相同的标签', function() { +// var domUtils = baidu.editor.dom.domUtils; +// var editor = new baidu.editor.ui.Editor({autoFloatEnabled:true}); +// var div = te.dom[2]; +// editor.render( div ); +// var body = editor.body; +// var range = new baidu.editor.dom.Range( editor.document ); +// editor.setContent( '

    a_text1a_tex2

    ' ); +// var a = body.firstChild.firstChild; +// range.setStart( body.firstChild, 0 ).setEnd( body.firstChild, 2 ).select(); +// same( domUtils.findTagNamesInSelection( range, ['a'] ), a, '选区包含2个完整的a,选择第一个a' ); +// +// range.setStart( body.firstChild, 0 ).setEnd( body.firstChild, 2 ).select(); +// same( domUtils.findTagNamesInSelection( range, ['p','a'] ), body.firstChild, '选区包含2个完整的a,选择p' ); +// +// range.setStart( a, 0 ).setEnd( a.nextSibling, 1 ).select(); +// same( domUtils.findTagNamesInSelection( range, ['a'] ), a, '选区包含2个不完整的a,选择第一个a' ); +//} ); + +//test( '不闭合选区,选区紧挨着标签边界', function() { +// var domUtils = baidu.editor.dom.domUtils; +// var editor = new baidu.editor.ui.Editor({autoFloatEnabled:true}); +// var div = te.dom[2]; +// editor.render( div ); +// var body = editor.body; +// var range = new baidu.editor.dom.Range( editor.document ); +// editor.setContent( '

    a_text1a_text3a_tex2

    ' ); +// range.selectNode( body.firstChild.childNodes[1] ).select(); +// same( domUtils.findTagNamesInSelection( range, ['a'] ), null, '选区紧挨着a边缘,找a返回null' ); +// +// same( domUtils.findTagNamesInSelection( range, ['a','p'] ), body.firstChild, '选区紧挨着a边缘,找p返回p' ); +//} ); + +//test( '不闭合选区,多节点,压力测试', function() { +// var domUtils = baidu.editor.dom.domUtils; +// var editor = new baidu.editor.ui.Editor({autoFloatEnabled:true}); +// var div = te.dom[2]; +// editor.render( div ); +// var body = editor.body; +// var range = new baidu.editor.dom.Range( editor.document ); +// editor.setContent( '

    我是p里的文本textTD2

    textTD1
    1. 我是列表1

      我是p里的文本textTD2

    2. 我是li 2里的文本textTD2

      TextEM1我是列表2里的文本

    ' ); +// var span = editor.document.getElementById( 'spanID' ); +// range.selectNode( span.firstChild ).select(); +// same(domUtils.findTagNamesInSelection(range,['div','pre','a','h1','h2','h3','h4','h5','h6','h7','table']),body.getElementsByTagName('table')[0],'深节点'); +//} ); + +//test( 'control range中查找是否包含特定的标签列表', function() { +// var domUtils = baidu.editor.dom.domUtils; +// var editor = new baidu.editor.ui.Editor({autoFloatEnabled:true}); +// var div = te.dom[2]; +// editor.render( div ); +// var range = new baidu.editor.dom.Range( editor.document ); +// +// editor.setContent( 'test_

    xx乐乐乐乐x我是标签

    ' ); +// var expectH2 = editor.document.getElementById( 'tt-h2' ), +// expectA = editor.document.getElementById( 'tt-a' ), +// expectSpan = editor.document.getElementById( 'tt-span' ); +// +// +// range.setStart(expectH2, 0).setEnd(expectA, 0).select(); +// ok( expectA === domUtils.findTagNamesInSelection( range, ['a', 'img', 'h3'] ), 'tag顺序:[a, img, h3]' ); +// ok( expectH2 === domUtils.findTagNamesInSelection( range, ['img', 'a', 'h3'] ), 'tag顺序:[img, a, h3]' ); +// +// +// range.setStart(expectSpan, 0).setEnd(expectH2, 1).select(); +// ok( expectH2 === domUtils.findTagNamesInSelection( range, ['a', 'img', 'h3'] ), 'tag顺序:[a, img, h3]' ); +// ok( expectH2 === domUtils.findTagNamesInSelection( range, ['img', 'a', 'h3'] ), 'tag顺序:[img, a, h3]' ); +//} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/core/filternode.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/filternode.js new file mode 100644 index 000000000..18f620dc3 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/filternode.js @@ -0,0 +1,178 @@ +module( 'core.filternode' ); + +test( '过滤掉整个标签', function() { + var uNode = UE.uNode; + var node = uNode.createElement('

    sdfsdf

    sdf
    '); + UE.filterNode(node,{ + 'p':{}, + 'b':'-' + }); + equals(node.toHtml().replace(/[ ]+>/g,'>'),'

    sdf

    sdf
    ','保留p,过滤b'); + + node.innerHTML('

    sdfs





    '); + UE.filterNode(node,{ + 'p':{}, + 'br':'-' + }); + equals(node.toHtml().replace(/[ ]+>/g,'>'),'

    sdfs

    ','保留p,过滤br'); +}); + +test( '过滤标签全部属性', function() { + var uNode = UE.uNode; + var node = uNode.createElement('

    sdfsdf

    sdf
    '); + node.innerHTML('

    sdfssdfs

    sdfasdf
    '); + UE.filterNode(node,{ + 'p':{$:{}} + }); + equals(node.toHtml().replace(/[ ]+>/g,'>'),'

    sdfssdfs

    sdfasdf
    ','过滤p全部属性'); + + node.innerHTML('
    asdlkfj
    '); + UE.filterNode(node,{ + 'h6':function(node){ + node.tagName = 'p'; + node.setAttr(); + }, + '-':'b i', + 'p':{} + }); + equals(node.toHtml().replace(/[ ]+>/g,'>'),'

    asd

    ','同时过滤多个标签属性'); +}); + +test( '过滤标签部分属性', function() { + var uNode = UE.uNode; + var node = uNode.createElement('

    sdfsdf

    sdf
    '); + node.innerHTML('

    sdfasdf
    '); + UE.filterNode(node,{ + 'p':{$:{ + style:['color'] + }}, + 'td':{} + }); + equals(node.toHtml().replace(/[ ]+>/g,'>'),'

    sdfasdf
    ','保留p的color属性'); + + node.innerHTML('

    sdfssdfs

    '); + UE.filterNode(node,{ + 'p':{$:{ + style:['line-height'] + }}, + 'span':{$:{}}, + 'strong':'-' + }); + equals(node.toHtml().replace(/[ ]+>/g,'>'),'

    sdfs

    ','过滤span全部属性,保留p部分属性,过滤strong标签'); + + node.innerHTML('

    sdfssdfssdfssdfs

    '); + UE.filterNode(node,{ + 'p':{}, + 'u':{$:{ + 'class':['ad'] + }}, + 'sub':{$:{}}, + 'i':'-' + }); + equals(node.toHtml().replace(/[ ]+>/g,'>'),'

    sdfssdfs

    ','过滤sub全部属性,保留u部分属性,过滤i标签'); +}); + +test( '标签替换过滤', function() { + var uNode = UE.uNode; + var node = uNode.createElement('

    sdfsdf

    sdf
    '); + node.innerHTML('

    sdfssdfs

    sdfasdf
    '); + UE.filterNode(node,{ + 'p':{$:{ + style:['color'] + }}, + 'tr':function(node){ + node.tagName = 'p'; + node.setAttr(); + }, + 'td':function(node){ + node.parentNode.removeChild(node,true) + } + }); + equals(node.toHtml().replace(/[ ]+>/g,'>'),'

    sdfssdfs

    sdfasdf
    ','tr替换为p,过滤掉td'); + + node.innerHTML('
    aldkfj
    adf
    lkj
    '); + UE.filterNode(node,{ + 'img':{$:{ + src:[''] + }}, + 'table':{}, + 'tbody':{}, + 'tr':{$:{}}, + 'td':{$:{}}, + 'th':function(node){ + var txt = !!node.innerText(); + if(txt){ + node.parentNode.insertAfter(UE.uNode.createText('    '),node); + } + node.parentNode.removeChild(node,node.innerText()) + } + }); + ua.checkSameHtml(node.toHtml().replace(/[ ]+>/g,'>'),'
    aldkfjadf    
    lkj
    ','th按文本内容替换,保留img部分属性'); +}); + +test( '保留标签全部属性', function() { + var uNode = UE.uNode; + var node = uNode.createElement('

    sdfsdf

    sdf
    '); + node.innerHTML('
    1. sdf
      • a
      • b
      • c
    2. jkl
    '); + UE.filterNode(node,{ + 'ol':{}, + 'ul':{$:{}}, + 'li':{} + }); + equals(node.toHtml().replace(/[ ]+>/g,'>'),'
    1. sdf
      • a
      • b
      • c
    2. jkl
    ','保留ol、li全部属性,过滤ul全部属性'); +}); + +test( '过滤规则为空', function() { + var uNode = UE.uNode; + var node = uNode.createElement('

    sdfsdf

    sdf
    '); + node.innerHTML('

    asd

    sdfasdf
    '); + UE.filterNode(node,{}); + equals(node.toHtml().replace(/[ ]+>/g,'>'),'

    asd

    sdfasdf
    ','过滤规则为空'); +}); + +test( '特殊规则过滤', function() { + var uNode = UE.uNode; + var node = uNode.createElement('

    sdf

    sdf
    '); + node.innerHTML(''); + UE.filterNode(node,{ + 'b':'-' + }); + equals(node.toHtml().replace(/[ ]+>/g,'>'),'
    ','过滤规则中包含html中不存在的标签'); + + node.innerHTML('

    '); + UE.filterNode(node,{ + 'p':{} + }); + equals(node.toHtml().replace(/[ ]+>/g,'>'),'

    ','innerHTML中包含注释'); +}); + +test( '只有white list--滤除属性', function () { + var uNode = UE.uNode; + var node = uNode.createElement('

    sdf

    sdf
    '); + node.innerHTML('
    hellotable

    hellodiv

    hellospan'); + UE.filterNode(node,{ + div:{ + $:{ + id:{}, + 'class':{} + } + }, + table:{}, + span:{} + }); + ua.checkSameHtml(node.toHtml().replace(/[ ]+>/g,'>'), '
    hellotable
    hellodiv
    hellospan
    ', '滤除属性'); +} ); + +test( '只有black list', function () { + var uNode = UE.uNode; + var node = uNode.createElement('

    sdf

    sdf
    '); + node.innerHTML('
    hello1hello2
    '); + UE.filterNode(node,{ + span:'-', + em:'-', + '#comment':'-', + script:'-', + style:'-' + }); + equals(node.toHtml().replace(/[ ]+>/g,'>'),'
    hello2
    ','过滤规则中包含html中不存在的标签'); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/core/filterword.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/filterword.js new file mode 100644 index 000000000..f9395bfcd --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/filterword.js @@ -0,0 +1,41 @@ +module( "core.filterword" ); + + +test( "office2010 word", function () { + stop(); + ua.readTxt('test1_1.txt',function(str){ + var txt = '

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    1. 欢迎使用ueditor!

    2. 欢迎使用ueditor!

    l 欢迎使用ueditor!

    l 欢迎使用ueditor!

    '; + equal(UE.filterWord(str),txt,'字体、字号、颜色、基本样式、列表'); + ua.readTxt('test1_2.txt',function(str){ + txt ='

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    '; + equal(UE.filterWord(str),txt,'段落样式、word样式、缩进'); + ua.readTxt('test1_3.txt',function(str){ + txt = '

    欢迎使用ueditor!

     

     

     

     

    欢迎使用ueditor!

    www.baidu.com

    '; + equal(UE.filterWord(str),txt,'表格、图片、超链接'); + start(); + }); + }); + }); +} ); + +test( "wps word", function () { + stop(); + ua.readTxt('test2_1.txt',function(str){ + var txt='

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    一、欢迎使用ueditor!

    二、欢迎使用ueditor!

    l 欢迎使用ueditor!

    l 欢迎使用ueditor!

    '; + equal(UE.filterWord(str),txt,'字体、字号、颜色、基本样式、列表'); + ua.readTxt('test2_2.txt',function(str){ + txt= '

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    欢迎使用ueditor!

    '; + equal(UE.filterWord(str),txt,'缩进、段落样式、word样式'); + ua.readTxt('test2_3.txt',function(str){ + txt='

    欢迎使用ueditor!

    欢迎使用ueditor!

    www.baidu.com

    '; + equal(UE.filterWord(str),txt,'表格、图片、超链接'); + start(); + }); + }); + }); +} ); +test( "word 补充 ", function () { + var str = '

    '; + var txt = '

    '; + ua.checkSameHtml(UE.filterWord(str),txt,'word 补充'); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/core/htmlparser.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/htmlparser.js new file mode 100644 index 000000000..5840f5815 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/htmlparser.js @@ -0,0 +1,209 @@ +/** + * Created with JetBrains PhpStorm. + * User: luqiong + * Date: 13-3-14 + * Time: 下午2:31 + * To change this template use File | Settings | File Templates. + */ +module( 'core.htmlparser' ); + +test( '普通标签处理', function() { + var root = UE.htmlparser('sdfsdfsdfsf'); + equals(root.toHtml(),'sdfsdfsdfsf','单个普通标签'); + root = UE.htmlparser('sdfsdfsdsdfsdfsf'); + equals(root.toHtml(),'sdfsdfsdsdfsdfsf','多个普通标签'); + root = UE.htmlparser('sdf'); + ua.checkSameHtml(root.toHtml(),'sdf','添加属性的标签'); + root = UE.htmlparser(''); + ua.checkSameHtml(root.toHtml(),'','img标签'); +}); + +test( '特殊标签处理', function() { + var root = UE.htmlparser('sdf'); + ua.checkSameHtml(root.toHtml(),'sdf','包含注释'); + root = UE.htmlparser(''); + equals(root.toHtml().replace(/[ ]+>/g,'>'),'','script标签'); + root = UE.htmlparser('


    '); + equals(root.toHtml().replace(/[ ]+>/g,'>'),'


    ','br标签'); + root = UE.htmlparser('
  • sdfsdfsdf
  • sdfsdfsdfsdf'); + equals(root.toHtml(),'
    • sdfsdfsdf
    • sdfsdfsdfsdf
    ','以文本结束的html'); +}); + +//test( '补全不完整table', function() {//TODO 1.2.6 +// var root = UE.htmlparser('

    '); +// equals(root.toHtml(),'

    ','td完整,补全table'); +// root = UE.htmlparser('

    sdfsdfsdf

    '); +// equals(root.toHtml(),'

    sdfsdfsdf

    ','td不完整,补全table'); +// root = UE.htmlparser('' + '\n\r' + ''); +// equals(root.toHtml(),'
    ','包含\n,补全table'); +// root = UE.htmlparser(''); +// equals( root.toHtml().toLowerCase(), '
    ', '--不补孩子' ); +// /*补parent*/ +// root = UE.htmlparser('hello'); +// equals( root.toHtml().toLowerCase(), '
    '); +// equals( root.toHtml().toLowerCase(), '
    ', '
    --补父亲' ); +// /*补parent和child*/ +// root = UE.htmlparser('
    hello
    ', 'hello--补父亲不补孩子' ); +// +// root = UE.htmlparser('123'); +// equals( root.toHtml().toLowerCase(), '
    123
    ', '123--文本放在table里' ); +// +// root = UE.htmlparser('123'); +// equals( root.toHtml().toLowerCase(), '123
    ', '123' ); +// +// root = UE.htmlparser('123'); +// equals( root.toHtml().toLowerCase(), '
    123
    ', '123' ); +// +// root = UE.htmlparser('123'); +// equals( root.toHtml().toLowerCase(), '
    123
    ', '123' ); +// +// /*补充为2个td*/ +//// root = UE.htmlparser('123'); +//// equals( root.toHtml().toLowerCase(), '
    123
    ', '123--tr和td之间有文字' );//TODO 1.2.6 +// +// root = UE.htmlparser('123'); +// equals( root.toHtml().toLowerCase(), '
    123
    ', '123' ); +// +// root = UE.htmlparser('123'); +// equals( root.toHtml().toLowerCase(), '
    123
    ', '123' ); +// +// /*补2个table*/ +//// root = UE.htmlparser('123132'); +//// equals( root.toHtml().toLowerCase(), '
    123
    132
    ', '123132--补全2个table' );//TODO 1.2.6 +// +// /*开标签、文本与闭标签混合*/ +//// root = UE.htmlparser('123'); +//// equals( root.toHtml().toLowerCase(), '
    123', '123--tr和td之间有文字' );//TODO 1.2.6 +// +//// root = UE.htmlparser('123'); +//// equals( root.toHtml().toLowerCase(), '
    123', '123--td闭标签后面有文字' );//TODO 1.2.6 +// +// root = UE.htmlparser('123'); +// equals( root.toHtml().toLowerCase(), '123
    ', '123' ); +// +// root = UE.htmlparser('123'); +// equals( root.toHtml().toLowerCase(), '
    123
    ', '123' ); +// +// root = UE.htmlparser('123'); +// equals( root.toHtml().toLowerCase(), '123
    ', '123' ); +// /*闭标签、文本与闭标签混合*/ +// root = UE.htmlparser('123'); +// equals( root.toHtml().toLowerCase(), '123', '123' ); +// +// root = UE.htmlparser('123'); +// equals( root.toHtml().toLowerCase(), '123', '123' ); +// +// root = UE.htmlparser('123'); +// equals( root.toHtml().toLowerCase(), '123
    ', '123', '123' ); +// +// /*补前面的标签*/ +// root = UE.htmlparser('123'); +// equals( root.toHtml().toLowerCase(), '123', '123' ); +// +// root = UE.htmlparser('123'); +// equals( root.toHtml().toLowerCase(), '123', '123' ); +// /*补全tr前面的标签*/ +// root = UE.htmlparser('123'); +// equals( root.toHtml().toLowerCase(), '123', '123--删除tr前后的标签,前面有文本' ); +// /*补全table前面的标签*/ +// root = UE.htmlparser('123'); +// equals( root.toHtml().toLowerCase(), '123', '123--删除table前后的标签,前面有文本' ); +// /*复杂结构*/ +// root = UE.htmlparser('456'); +// equals( root.toHtml().toLowerCase(), '
    123
    123
    456
    ', '456' ); +// +// root = UE.htmlparser(''); +// equals( root.toHtml().toLowerCase(), '
    123
    hello1hello2
    hello1hello2
    ', '解析hello1hello2' ); +// +// root = UE.htmlparser(''); +// equals( root.toHtml().toLowerCase(), '
    hello1hello2
    hello1hello2
    ', '解析' ); +// +// root = UE.htmlparser('
    hello1hello2
    123'); +// equals( root.toHtml().toLowerCase(), '
    123', '123' ); +//}); + +test( '补全不完整li', function() { + var root = UE.htmlparser('
    1. sdf
    2. sdfsdf
    '); + equals(root.toHtml().replace(/[ ]+>/g,'>'),'
    1. sdf
    2. sdfsdf
    ','补全u,em'); + root = UE.htmlparser('
    1. sdf
      • a
      • b
      • c
    2. jkl
    '); + equals(root.toHtml().replace(/[ ]+>/g,'>'),'
    1. sdf
      • a
      • b
      • c
    2. jkl
    ','补全li'); + root = UE.htmlparser('
  • 123'); + equals(root.toHtml().replace(/[ ]+>/g,'>'), '
    • 123
    ', '
  • 123--补全li的parent--ul,前面有文本' ); + /*补ul的child*/ + root = UE.htmlparser('
      123'); + equals(root.toHtml().replace(/[ ]+>/g,'>'), '
      • 123
      ', '
        123--补全ul的child--li,前面有文本' ); + /*补li开始标签*/ + root = UE.htmlparser('123'); + equals(root.toHtml().replace(/[ ]+>/g,'>'), '123', '123--删掉标签' ); +}); + +test( '属性引号问题', function() { + var root = UE.htmlparser(''); + equals(root.toHtml().replace(/[ ]+>/g,'>'),''); + root = UE.htmlparser(""); + equals(root.toHtml().replace(/[ ]+>/g,'>'),''); + root = UE.htmlparser(''); + equals(root.toHtml().replace(/[ ]+>/g,'>'),''); +}); + +test( '大小写', function() { + var root = UE.htmlparser('

  • '); + equals(root.toHtml().replace(/[ ]+>/g,'>'),'

    '); + root = UE.htmlparser('
    1. sdf
    2. sdfsdf
    '); + equals(root.toHtml().replace(/[ ]+>/g,'>'),'
    1. sdf
    2. sdfsdf
    ','补全u,em'); + root = UE.htmlparser(''); + equals(root.toHtml().replace(/[ ]+>/g,'>'),''); +}); + +test( '裸字', function() { + var root = UE.htmlparser('sdfasdfasdf'); + equals(root.toHtml().replace(/[ ]+>/g,'>'),'sdfasdfasdf'); +}); + +test( '只有结束标签的情况', function() { + var root = UE.htmlparser('

    hello1

    hello2

    '); + equals(root.toHtml().replace(/[ ]+>/g,'>'),'

    hello1

    hello2

    '); +}); + +test( '开始标签与后面文本的空格过滤,其他不过滤inline节点之间的空格,过滤block节点之间的空格', function () { + /*inline节点之间的空格要留着*/ + var root = UE.htmlparser('baidu hello '); + equals(root.toHtml().replace(/[ ]+>/g,'>'),'baidu hello '); + root = UE.htmlparser(' hello he llo2 hello '); + equals(root.toHtml().replace(/[ ]+>/g,'>'),' hello he llo2 hello ' ); + /*block节点之间的空格不要留着 这个太纠结,不必了。会把ol拆开,后面的变成ul*/ +// html = '
    1. li_test
    2. li test2
    '; +// node = serialize.parseHTML( html ); +// node = serialize.filter( node ); +// equal( serialize.toHTML( node ), '
    1. li_test 
    2. li test2 
     ' ); +} ); + +/*特殊字符需要转义*/ +test( '文本包含特殊字符,如尖括号', function () { + var root = UE.htmlparser(''); + equals(root.toHtml().replace(/[ ]+>/g,'>'),'<td  hello', '字符转义' ); +} ); + +test( 'br', function () { + var root = UE.htmlparser('
    '); + equals(root.toHtml().replace(/[ ]+>/g,'>'),'
    ', '对br不操作'); + root = UE.htmlparser('
    '); + equals(root.toHtml().replace(/[ ]+>/g,'>'),'
    ', '补充br后面的斜杠'); +} ); + +/*考察标签之间嵌套关系*/ +test( '复杂标签嵌套', function() { + var root = UE.htmlparser('hello1

    hello2

    hello3

    hello4'); + equals(root.toHtml().replace(/[ ]+>/g,'>'),'hello1

    hello2

    hello3

    hello4

    '); +} ); + +test( 'trace 1727:过滤超链接后面的空格', function () { + var root = UE.htmlparser('baidu ddd'); + equals(root.toHtml().replace(/[ ]+>/g,'>'),'baidu  ddd','过滤超链接后面的空格'); +} ); + +//test( '转换img标签', function () { +// var root = UE.htmlparser(''); +// var spa=ua.browser.ie==6?' orgSrc="'+te.obj[1].options.UEDITOR_HOME_URL+'themes/default/images/spacer.gif"':''; +// equals(root.toHtml().replace(/[ ]+>/g,'>'), '' , '转换img标签'); +//} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/core/localstorage.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/localstorage.js new file mode 100644 index 000000000..000dc7e97 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/localstorage.js @@ -0,0 +1,46 @@ +module("core.localstorage"); + +test('用 UE.LocalStorage 对字符串做保存/读取/删除操作', function () { + + var str = '1234567890-=!@#$%^&*()_+qwertyuiopasdfghjklzxcvbnm,./<>?;\':"[]\\{}|'; + UE.LocalStorage.saveLocalData('test_string1', str); + equal(UE.LocalStorage.getLocalData('test_string1'), str, "保存内容,并读取内容"); + + UE.LocalStorage.saveLocalData('test_string2', str); + UE.LocalStorage.removeItem('test_string2'); + equal(UE.LocalStorage.getLocalData('test_string2'), undefined, "保存内容,并删除内容"); + +}); + +test('偏好设置相关方法setPreferencesue、getPreferences、removePreferences', function () { + + var editor = te.obj[1]; + + var str = '1234567890-=!@#$%^&*()_+qwertyuiopasdfghjklzxcvbnm,./<>?;\':"[]\\{}|'; + editor.setPreferences('test_string', str); + equal(editor.getPreferences('test_string'), str, "保存字符串,并读取内容"); + + var obj = { + nul: null, + boo1: true, + boo2: false, + str: 'aaa', + arr: [1, '2', 'a'], + obj: {k1:1, k2:'2', k3:'a'} + }; + editor.setPreferences('test_object', obj); + same(editor.getPreferences('test_object'), obj, "保存键值对象,并读取内容"); + + editor.setPreferences('test_boolean', true); + equal(editor.getPreferences('test_boolean'), true, "保存布尔值,并读取内容"); + + var arr = [1, '2', 'a']; + editor.setPreferences('test_string', arr); + same(editor.getPreferences('test_string'), arr, "保存数组,并读取内容"); + + var tmpStr = 'string_content'; + editor.setPreferences('test_delete', tmpStr); + editor.removePreferences('test_delete'); + equal(editor.getPreferences('test_delete'), undefined, "保存字符串,并删除内容"); + +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/core/node.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/node.js new file mode 100644 index 000000000..a77e2f8ed --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/node.js @@ -0,0 +1,218 @@ +module( 'core.node' ); + +test( 'createElement', function() { + var uNode = UE.uNode; + var node = uNode.createElement('div'); + equals(node.tagName,'div','空div ——tagname'); + equals(node.type,'element','空div ——节点类型'); + node = uNode.createElement('
    sdfadf
    '); + equals(node.tagName,'div','非空div——tagname'); + equals(node.children[0].data,'sdfadf','非空div——数据内容'); +}); + +test( 'getNodeById', function() { + var uNode = UE.uNode; + var node = uNode.createElement('
    sdfadf
    '); + node = node.getNodeById('bb'); + equals(node.getAttr('id'),'bb','获取标签id'); + node = uNode.createElement('
    sdfadf
    '); + node = node.getNodeById('cc'); + equals(node.getAttr('id'),'cc','获取标签id'); +}); + +test( 'getNodesByTagName', function() { + var uNode = UE.uNode; + var node = uNode.createElement('
    sdfadf
    '); + var nodelist = node.getNodesByTagName('div'); + equals(nodelist.length,2,'div节点列表长度'); + equals(node.innerHTML().replace(/[ ]+>/g,'>'),'
    sdfadf','innerHTML内容'); +}); + +test( 'innerHTML', function() { + var uNode = UE.uNode; + var node = uNode.createElement('
    sdfadf
    '); + node.innerHTML('
    '); + var nodelist =node.getNodesByTagName('div'); + equals(nodelist.length,3,'div节点列表长度'); + for(var i= 0,ci;ci=nodelist[i++];){ + ci.tagName = 'p'; + } + equals(node.innerHTML(),'

    ','innerHTML内容'); + node = uNode.createElement('
    '); + node.innerHTML('asdf'); + equals(node.innerHTML(),'asdf','innerHTML内容'); +}); + +test( 'innerText', function() { + var tmp = new UE.uNode.createElement('area'); + tmp.innerHTML('

    '); + equals(tmp.innerText(),tmp,'标签类型特殊'); + tmp = new UE.uNode.createText(''); + tmp.innerHTML('

    '); + equals(tmp.innerText(),tmp,'对象类型不为element'); + var uNode = UE.uNode; + var node = uNode.createElement('
    sdfadf
    '); + node.innerHTML('

    dfsdfsdfeeesdf

    '); + equals(node.innerText(),'dfsdfsdfeeesdf','获取标签中纯文本'); + node.innerText('sdf'); + equals(node.innerHTML(),'sdf','设置文本节点'); +}); + +test( 'getData', function() { + var tmp = new UE.uNode.createElement('div'); + equals(tmp.getData(),'','element元素'); + tmp = new UE.uNode.createText('askdj'); + equals(tmp.getData(),"askdj",'其他类型'); +}); + +test( 'appendChild && insertBefore', function() { + var uNode = UE.uNode; + var node = uNode.createElement('
    sdfadf
    '); + node.innerHTML('

    '); + equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','补全html标签'); + var tmp = uNode.createElement('div'); + node.appendChild(tmp); + equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','appendChild'); + node.insertBefore(tmp,node.firstChild()); + equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','insertBefore'); + node.appendChild(tmp); + equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','appendChild'); +}); + +test( 'replaceChild && setAttr', function() { + var uNode = UE.uNode; + var node = uNode.createElement('
    sdfadf
    '); + node.innerHTML('

    '); + var tmp = uNode.createElement('p'); + tmp.setAttr({'class':'test','id':'aa'}); + node.insertBefore(tmp,node.lastChild()); + equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','setAttr不为空'); + node.replaceChild(uNode.createElement('div'),tmp); + equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','replaceChild'); + + node.removeChild(node.lastChild(),true); + tmp = uNode.createElement('p'); + tmp.setAttr(); + node.insertAfter(tmp,node.lastChild()); + equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','setAttr为空'); + node.innerHTML('

    '); + tmp = uNode.createElement('div'); + node.appendChild(tmp); + node.replaceChild(node.firstChild(),tmp); + equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','replaceChild'); +}); + +test( 'insertAfter', function() { + var uNode = UE.uNode; + var node = uNode.createElement('
    sdfadf
    '); + node.innerHTML('

    '); + var tmp = uNode.createElement('div'); + node.appendChild(tmp); + node.insertAfter(tmp,node.firstChild()); + equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','在第一个子节点后插入'); +}); + +test( 'getStyle', function() { + var uNode = UE.uNode; + var node = uNode.createElement('div'); + node.innerHTML('
    '); + node = node.firstChild(); + equals(node.getStyle(''),'','空cssStyle'); + node.innerHTML('
    '); + node = node.firstChild(); + equals(node.getStyle('border'),'1px solid #ccc','有border,取border样式'); + node.innerHTML('
    '); + node = node.firstChild(); + equals(node.getStyle('color'),'','无color样式,取color样式'); + node.innerHTML('
    '); + node = node.firstChild(); + equals(node.getStyle('color'),'#ccc','有2个样式,取其一'); +}); + +test( 'setStyle', function() { + var uNode = UE.uNode; + var node = uNode.createElement('div'); + node.innerHTML('
    '); + node = node.firstChild(); + node.setStyle('border','2px solid #ccc'); + equals(node.getAttr('style'),'border:2px solid #ccc;color:#ccc','修改样式中的一个'); + node.setStyle({ + 'font':'12px', + 'background':'#ccc' + }); + equals(node.getAttr('style'),'background:#ccc;font:12px;border:2px solid #ccc;color:#ccc','添加新样式'); + node.setStyle({ + 'font':'', + 'background':'', + 'border':'', + 'color':'' + }); + equals(node.getAttr('style'),undefined,'清空样式'); + node.setStyle('border',''); + equals(node.getAttr('style'),"border:<script>alert("")</script>;",'脚本'); + equals(node.toHtml(),'
    ','脚本转html'); + node.innerHTML('
    asdfasdfsdf
    '); + node.removeChild(node.firstChild(),true); + equals(node.toHtml(),'
    asdfasdfsdf
    ','移除子节点'); + node.innerHTML('
    '); + node.firstChild().setStyle('border'); + equals(node.firstChild().toHtml(),'
    ','删除分号'); + node.innerHTML('
    '); + equals(node.firstChild().toHtml(),'
    '); + + node.innerHTML('
    '); + node.firstChild().setStyle('border'); + + equals(node.firstChild().toHtml(),'
    '); + node.innerHTML('
    '); + node.firstChild().setStyle('border'); + equals(node.firstChild().toHtml(),'
    '); + node.firstChild().setStyle('color'); + equals(node.firstChild().toHtml(),'
    '); + node.firstChild().setStyle('background-color'); + equals(node.firstChild().toHtml(),'
    '); +}); + +test( 'getIndex', function() { + var uNode = UE.uNode; + var node = uNode.createElement('div'); + node.innerHTML('
    asdfasdfsdf
    ') + node.removeChild(node.firstChild(),true); + var tmp = new UE.uNode.createElement('div'); + node.appendChild(tmp); + equals(tmp.getIndex(),2,'节点索引'); +}); + +test( 'traversal', function() { + var uNode = UE.uNode; + var node = uNode.createElement('div'); + node.innerHTML('
    asdfasdfsdf
    ') + var count = 0; + node.traversal(function(node){ + count++; + }); + equals(count,4); + count = 0; + node.traversal(function(node){ + if(node.type == 'text'){ + count++ + } + }); + equals(count,2); + node.traversal(function(node){ + if(node.type == 'text'){ + + node.parentNode.removeChild(node) + } + }); + equals(node.toHtml(),'
    '); + node.innerHTML('
    asdfasdfsdf
    '); + node.traversal(function(node){ + if(node.type == 'text'){ + var span = uNode.createElement('span'); + node.parentNode.insertBefore(span,node); + span.appendChild(node); + } + }); + equals(node.toHtml(),'
    asdfasdfsdf
    '); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/core/plugin.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/plugin.js new file mode 100644 index 000000000..e10ba98fc --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/plugin.js @@ -0,0 +1,30 @@ +module( 'core.plugin' ); + +test( 'register', function() { + UE.plugin.register('test',function(){ + this.testplugin = true; + }); + $('
    ').appendTo(document.body); + var editor = UE.getEditor('ue'); + stop(); + editor.ready(function () { + ok(this.testplugin); + editor.destroy(); + $('#ue').remove() + start(); + }); +}); +test( 'load', function() { + UE.plugin.register('test',function(){ + this.testplugin = true; + }); + $('
    ').appendTo(document.body); + var editor = UE.getEditor('ue',{ + test:false + }); + stop(); + editor.ready(function () { +// ok(!this.testplugin); todo + start(); + }); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/core/tools.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/tools.js new file mode 100644 index 000000000..3be2d871b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/tools.js @@ -0,0 +1,50 @@ +(function () { + function mySetup() { + for (var config in window.UEDITOR_CONFIG) { + if (typeof(window.UEDITOR_CONFIG[config]) == 'string') + window.UEDITOR_CONFIG[config] = window.UEDITOR_CONFIG[config].replace('_test/tools/br/', ''); + } + + var div = document.body.appendChild(document.createElement('div')); + div.id = 'test1'; + var utils = baidu.editor.utils; + var editor = new baidu.editor.Editor({'UEDITOR_HOME_URL':'../../../', 'autoFloatEnabled':false,initialContent:'tool'}); + var iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + iframe.id = 'iframe'; + var range = new baidu.editor.dom.Range(document); + var domUtils = baidu.editor.dom.domUtils; + var div_dom = document.body.appendChild(document.createElement('div')); + div_dom.id = 'test'; + te.dom.push(div); + te.dom.push(iframe); + te.dom.push(div_dom); + te.obj.push(utils); + te.obj.push(editor); + te.obj.push(range); + te.obj.push(domUtils); + } + var _d = function () { + + if (te) { + if (te.dom && te.dom.length) { + for (var i = 0; i < te.dom.length; i++) { + if (te.dom[i] && te.dom[i].parentNode) + te.dom[i].parentNode.removeChild(te.dom[i]); + } + + } + } + te.dom = []; + te.obj = []; + }; + var s = QUnit.testStart, d = QUnit.testDone; + QUnit.testStart = function () { + s.apply(this, arguments); + mySetup(); + }; + QUnit.testDone = function () { + _d(); + d.apply(this, arguments); + }; +})() \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/core/utils.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/utils.js new file mode 100644 index 000000000..5d98adba1 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/core/utils.js @@ -0,0 +1,547 @@ +module("core.utils"); + +test('cssRule', function () { + var utils = te.obj[0]; + utils.cssRule('test1', '.test{width:300px;}'); + var style = utils.cssRule('test1'); + ok(/^\.test/.test(style)); + utils.cssRule('test1', ''); + style = utils.cssRule('test1'); + ok(!style); + var div = te.dom[2]; + div.innerHTML = 'sdfsdf'; + utils.cssRule('style_test', '.test{display:block}'); + utils.cssRule('style_test', '.test{font-size:48px}'); + var block = UE.dom.domUtils.getComputedStyle(div.firstChild, 'display'); + equals(block, 'inline'); + //删除样式 + utils.cssRule('style_test', ''); + equals(UE.dom.domUtils.getComputedStyle(div.firstChild, 'font-size'), '16px'); +}); + +test("makeInstance", function () { + var utils = te.obj[0]; + var obj = { + s: 1, + str: "makeInstance" + }, str = "makeInstance"; + var ins = utils.makeInstance(obj); + var ins1 = utils.makeInstance(str); + equals(ins.s, 1, "ins.s"); + equals(ins.str, "makeInstance", "ins.str"); + same(ins1, {}, "null"); + same(utils.makeInstance(null), {}, "null"); +}); +test("isArray--普通对象", function () { + var utils = te.obj[0]; + var arr = [ '1', '2' ], ob = {}, str = "array", fun = function () { + }; + var div = te.dom[0]; + ok(utils.isArray(arr), 'arr is a array'); + ok(!utils.isArray(ob), 'ob is not a array'); + ok(!utils.isArray(str), 'str is not a array'); + ok(!utils.isArray(fun), 'fun is not a array'); + ok(!utils.isArray(null), 'null is not a array'); + ok(!utils.isArray(div), 'dom element is not a array'); +}); + +test("isArray--类数组对象", function () { + var utils = te.obj[0]; + var arrayLike = { + 0: '0', + 1: '1', + 2: '2', + length: 3 + }; + var div = te.dom[0]; + div.innerHTML = 'xxxxx

    '; + ok(!utils.isArray(arrayLike), '类数组对象不是数组'); + ok(!utils.isArray(div.childNodes), 'nodeList 不是数组'); + +}); + +test("inherits", function () { + var utils = te.obj[0]; + var superClass = function () { + }; + var subClass = function () { + }; + expect(4); + var index = 0; + superClass.prototype.name = "superClass"; + superClass.prototype.methodSuper = function () { + ok(true, "method in superClass is called"); + }; + superClass.prototype.method = function () { + ok(false, "I am in superClass"); + }; + subClass.prototype.name = "subClass"; + subClass.prototype.methodSub = function () { + ok(true, "method in subClass is called"); + }; + subClass.prototype.method = function () { + ok(true, "I am in subClass"); + }; + utils.inherits(subClass, superClass); + var sub = new subClass(); + /*子类自己的名字,父类的被覆盖*/ + equal(sub.name, "subClass", "the name of subClass"); + /*从父类中继承的方法*/ + sub.methodSuper(); + /*子类自己的方法*/ + sub.methodSub(); + /*覆盖父类中的method方法*/ + sub.method(); +}); + + +test("bind", function () { + var utils = te.obj[0]; + var first_object = { num: 4 }; + var second_object = { num: 2 }; + + function multiply(mult) { + return this.num * mult; + } + + var first_multiply = utils.bind(multiply, first_object); + equal(first_multiply(5), 20, "first_object"); // returns 4 * 5 + var second_multiply = utils.bind(multiply, second_object); + equal(second_multiply(5), 10, "second_object"); +}); + +test('defer--一个defer', function () { + var utils = te.obj[0]; + var delay = 100; + expect(1); + stop(); + /*defer返回一个闭包,算defer不准,chrome下会 相差300多ms,没办法判断延时是否准确*/ + var stime = +new Date(); + utils.defer(function () { + ok(1, '检查回调函数是否触发'); + start(); + }, delay)(); +}); + +test('defer--多个defer', function () { + var utils = te.obj[0]; + var delay = 40; + stop(); + expect(2); + utils.defer(function () { + ok(true, '第一个触发'); + }, delay)(); + + utils.defer(function () { + ok(true, '第二个触发'); + start(); + }, delay)(); +}); + +/*若互斥,则前一个注册的setTimeout事件被删除*/ +test('defer--考虑互斥', function () { + var utils = te.obj[0]; + var delay = 20; + stop(); + expect(1); + /*exclusion=true*/ + var defer = utils.defer(function () { + ok(1, '检查回调函数是否在规定的时间内触发'); + }, delay, true); + defer(); + //第一个defer会被删掉 + defer(); + setTimeout(function () { + start(); + }, 100); +}); + +test("extend--true", function () { + var utils = te.obj[0]; + var obj1 = {a: 3, b: "str", fun: function () { + ok(true, "fun"); + }, n: null}; + var obj2 = {a: 2, c: 1}; + utils.extend(obj2, obj1, true); + equal(obj2.a, 2, "obj2 a"); + equal(obj2.b, "str", "obj2 str"); + equal(obj2.c, 1, "obj2 c"); + obj2.fun(); + equal(obj2.n, null, "obj2 n null"); +}); +test("extend--false", function () { + var utils = te.obj[0]; + var obj1 = {a: 3, b: "str", fun: function () { + ok(true, "fun"); + }, n: null}; + var obj2 = {a: 2, c: 1}; + utils.extend(obj2, obj1, false); + equal(obj2.a, 3, "obj2 a"); + equal(obj2.b, "str", "obj2 str"); + equal(obj2.c, 1, "obj2 c"); + obj2.fun(); + equal(obj2.n, null, "obj2 n null"); +}); +test('indexOf', function () { + var utils = te.obj[0]; + var s = [ 1, 2, 3, 4, 5 ]; + equals(utils.indexOf(s, 3), 2); + equals(utils.indexOf(s, 6), -1); + equals(utils.indexOf(s, 5), 4); + equals(utils.indexOf(s, 3, 3), -1); + equals(utils.indexOf(s, 3, 3), -1); +}); +test('removeItem&&itemexist', function () { + var utils = te.obj[0]; + var s = [ 1, 2, 3, 4, 5 , 4, 3]; + equal(s[5], 4, "before remove 4"); + utils.removeItem(s, 4); + equal(s.length, 5, "4 be removed"); + equal(s[4], 3, "4 be removed"); +}); + +test('removeItem&&itemnotexist', function () { + var utils = te.obj[0]; + var s = [ 1, 2, 3, 4, 5 , 4]; + utils.removeItem(s, 6); + equal(s.length, 6, "itemnotexist"); +}); + +test("trim", function () { + var utils = te.obj[0]; + var s = ' sss '; + equals(utils.trim(s), 'sss', "两端有空格"); + s = " xxx "; + equal(utils.trim(s), ' xxx', "包含 ");// 不能被捕获 + s = "string"; + equal(utils.trim(s), "string", '没有 和空格'); +}); +test('listToMap', function () { + var utils = te.obj[0]; + var s = "listToMap"; + var re = utils.listToMap(s); + equal(re.listToMap, 1, "listToMap"); +}); +test('list,To,Map', function () { + var utils = te.obj[0]; + var s = "list,To,Map"; + var re = utils.listToMap(s); + equal(re.list, 1, "list"); + equal(re.To, 1, "list"); + equal(re.Map, 1, "Map"); +}); +test('listToMap ""', function () { + var utils = te.obj[0]; + var s = ""; + var re = utils.listToMap(s); + equal(re.toString(), {}, "{}"); +}); +test('listToMap null', function () { + var utils = te.obj[0]; + var s = null; + var re = utils.listToMap(s); + equal(re.toString(), {}, "{}"); +}); +test('listToMap numstring', function () { + var utils = te.obj[0]; + var s = "123333"; + var re = utils.listToMap(s); + equal(re[123333], 1, "num"); +}); +test('unhtml 字符转义', function () { + var utils = te.obj[0]; + var str = '

    "as&cd"

    '; + var str_html = utils.unhtml(str); + equal(str_html, '<p>"as&cd"</p>', '转义字符成功'); + str = 'border:<script>alert("")</script>"' + equal(utils.unhtml(str), 'border:<script>alert("")</script>"', '转义字符成功'); + str = "'"; + equal(utils.unhtml('比如小这个汉字的unicode编码'), '比如小这个汉字的unicode编码'); + equal(utils.unhtml('比如&#<23567;这个汉字的unicode编码<>'), '比如&#<23567;这个汉字的unicode编码<>') +}); +test('html 反转义', function () { + var utils = te.obj[0]; + var str_html = '<p>"as&cd"</p>'; + var str = utils.html(str_html); + equal(str, '

    "as&cd"

    ', '反转义成功'); +}); +test('unhtml null ""', function () { + var utils = te.obj[0]; + var s = null; + equal(utils.unhtml(s), "", "unhtml null"); + s = ''; + equal(utils.unhtml(s), "", "unhtml null"); +}); +test('cssStyleToDomStyle', function () { + var utils = te.obj[0]; + equal(utils.cssStyleToDomStyle("cssFloat").toLowerCase(), "cssfloat", "cssFloat"); + if (ua.browser.ie && ua.browser.ie < 9) { + equal(utils.cssStyleToDomStyle("float").toLowerCase(), "stylefloat", "float"); + } else { + equal(utils.cssStyleToDomStyle("float").toLowerCase(), "cssfloat", "float"); + } + equal(utils.cssStyleToDomStyle("styleFloat").toLowerCase(), "stylefloat", "styleFloat"); +}); + +//zhuwenxuan add +test("isEmptyObject", function () { + var utils = te.obj[0]; + var obj = { + n: 1 + }; + equal(false, utils.isEmptyObject(obj)); + equal(true, utils.isEmptyObject([])); + equal(true, utils.isEmptyObject("")); +}); +//dong +test("fixColor", function () { + var utils = te.obj[0]; + equal('#953734', utils.fixColor("color", 'rgb(149, 55, 52)'), 'fixColor'); +}); +test("sort", function () { + var utils = te.obj[0]; + same(["a", "df", "sdf", "asdf"], utils.sort(['a', 'asdf', 'df', 'sdf'], function (a, b) { + if (a.length > b.length) + return 1; + else return 0; + }), 'sort'); +}); +test("domReady", function () { + var utils = te.obj[0]; + expect(1); + utils.domReady(function () { + ok(1, 'domReady') + }); +}); +test('4个padding属性', function () { +// var css = 'padding-bottom:0px; margin:0px 0px 20px; padding-left:0px; padding-right:4px; padding-top:0px'; + /*上下相同,左右相同*/ + var css = 'padding-bottom:3px;padding-left:2px;padding-right:2px;padding-top:3px'; + var result = UE.utils.optCss(css); + equal(result, 'padding:3px 2px;', '上下相同,左右相同'); + /*上下不同,左右相同*/ + css = 'padding-bottom:2px;padding-left:2px;padding-right:2px;padding-top:3px'; + result = UE.utils.optCss(css); + equal(result, 'padding:3px 2px 2px;', '上下不同,左右相同'); + /*只有2个属性*/ + css = 'padding-bottom:2px;padding-left:2px;'; + result = UE.utils.optCss(css); + equal(result, 'padding-bottom:2px;padding-left:2px;', '2个属性就不合'); +}); + +test('4个margin属性', function () { + /*上下相同,左右相同*/ + var css = 'margin-bottom:3px;margin-left:2px;margin-right:2px;margin-top:3px'; + var result = UE.utils.optCss(css); + equal(result, 'margin:3px 2px;', '上下相同,左右相同'); + css = 'margin-bottom:2px;margin-left:2px;margin-right:2px;margin-top:2px'; + result = UE.utils.optCss(css); + equal(result, 'margin:2px;', '全相同'); + /*上下不同,左右相同*/ + css = 'margin-bottom:2px;margin-left:2px;margin-right:2px;margin-top:3px'; + result = UE.utils.optCss(css); + equal(result, 'margin:3px 2px 2px;', '上下不同,左右相同'); + /*只有1个属性*/ + css = 'margin-top:2px;'; + result = UE.utils.optCss(css); + equal(result, 'margin-top:2px;', '1个属性就不合'); +}); + +test('合并;的问题', function () { + equal(UE.utils.optCss('font-size:12px;";<dssdfs>;;'), 'font-size:12px;";<dssdfs>;', ''); +}); +//test( '合并border相关属性', function () { +//// var css = 'border-width:thin medium;' + //只有border-width +//// 'border-top-color:red;border-bottom-color:red;border-left-color:red;' + //3个分属性相同,不应当合 +//// 'border-right-style:hidden;border-bottom-style:hidden;border-left-style:hidden;border-top-style:hidden'; //4个分属性相同,应当合 +//// var result = UE.utils.optCss( css ); +//// equal( result, 'border-width:thin medium;border-top-color:red;border-bottom-color:red;border-left-color:red;border-style:hidden' ); +//// /*border属性, border不能分别定义4个边框的宽度,颜色和样式, +//// 只能统一定义,不可以对四个边设置不同的值,和margin与padding是不同的(后两者可以分别定义四个边的值).*/ +//// css = 'border-top:2px hidden red;border-right:2px hidden red'; +//// result = UE.utils.optCss(css ); +//// equal(result,css,'border2个属性不合'); +//// /*4个属性都相同,合*/ +//// css = 'border-top:2px hidden red;border-right:2px hidden red;border-left:2px hidden red;border-bottom:2px hidden red'; +//// result = UE.utils.optCss(css ); +//// equal(result,'border:2px hidden red;','4个属性都相同,合'); +//// /*4个属性不同,不合*/ +//// css = 'border-top:2px hidden red;border-right:3px hidden red;border-left:2px hidden red;border-bottom:2px hidden red'; +//// result = UE.utils.optCss(css ); +//// equal(result,'border:2px hidden red;','4个属性不同,不合'); +// var css = 'border-image:initial;' +//} ) ; +// +test('margin,border,padding属性混杂', function () { + var css = 'margin-bottom:3px;margin-left:2px;margin-right:2px;margin-top:3px;padding:4px;border-image:initial;border-top-color:red;'; + var result = UE.utils.optCss(css); + equal(result, 'padding:4px;border-top-color:red;margin:3px 2px;', 'margin,border,padding属性混同'); + +}); + +test('each 遍历方法', function () { + var div = te.dom[0]; + div.innerHTML = ''; + UE.utils.each(div.getElementsByTagName('span'), function (node, i) { + equal(node.tagName, 'SPAN', '遍历nodelist'); + }); + var count = 0; + UE.utils.each(div.getElementsByTagName('span'), function (node, i) { + count++; + if (node.id == 'a') + return false + }); + equal(count, 3); + UE.utils.each(['a', 'b'], function (v, i) { + equal(v, ['a', 'b'][i], '遍历数组'); + }); + UE.utils.each({a: 1, b: 2}, function (v, k) { + equal(v, {a: 1, b: 2}[k], '遍历对象'); + }); +}); +test('clone 转换', function () { + var obj = {a: 1}; + var obj1 = UE.utils.clone({a: 1}); + obj.a = 2; + equal(obj1.a, 1); + obj = { + a: { + b: 1 + }, + c: [1, 2] + } + obj1 = UE.utils.clone(obj); + obj.a.b = 2; + equal(obj1.a.b, 1); + obj.c[1] = 3; + equal(obj1.c[1], 2); + + +}); +test('transUnitToPx 转换', function () { + equal(UE.utils.transUnitToPx('20pt'), '27px'); + equal(UE.utils.transUnitToPx('0pt'), '0'); +}); + +test('RegExp', function () { + var reg = new RegExp(".*"); + equal(ok(utils.isRegExp(reg), 'reg is a RegExp')); +}); + +test('isDate', function () { + var date = new Date(); + equal(ok(utils.isDate(date), 'date is a Date')); +}); + +test('isCrossDomainUrl', function () { + + var l = location; + + ok(!utils.isCrossDomainUrl(location.href), 'location.href 不跨域'); + + if (l.port == '') { + ok(!utils.isCrossDomainUrl(l.protocol + '//' + l.hostname + ':80/ueditor/'), '本地没端口,80端口不跨域'); + } + + if (l.port == '80') { + ok(!utils.isCrossDomainUrl(l.protocol + '//' + l.hostname + '/ueditor/'), '本地没80端口,无端口不跨域'); + } + + if (l.protocol == 'http:') { + ok(utils.isCrossDomainUrl('https://' + l.host + '/ueditor/'), '本地http协议,https协议跨域'); + } else { + ok(utils.isCrossDomainUrl('http://' + l.host + '/ueditor/'), '本地不是http协议,http协议跨域'); + } + + ok(utils.isCrossDomainUrl(l.protocol + '//www.baidu.com' + ':' + l.port), '域名不一致跨域'); + +}); + +test('formatUrl', function () { + + var url1 = 'http://localhost/a.html?&key1=value1&&key2=value2&&&&&&&&&key3=value3&#hash'; + var url2 = 'http://localhost/a.html?&key1=value1&&key2=value2&&&&&&&&&key3=value3&'; + + equal(utils.formatUrl(url1), 'http://localhost/a.html?key1=value1&key2=value2&key3=value3#hash', '格式化url'); + equal(utils.formatUrl(url2), 'http://localhost/a.html?key1=value1&key2=value2&key3=value3', '格式化url'); + +}); + +test('str2json', function () { + + same(utils.str2json('{"a":11,"b":"22","c":"cc","d":[1,"2","a",{"a":"aa"}],"e":{"k1":1,"k2":"2","k3":"a","k4":{"a":"aa"}}}'), + {"a": 11, "b": "22", "c": "cc", "d": [1, "2", "a", {"a": "aa"}], "e": {"k1": 1, "k2": "2", "k3": "a", "k4": {"a": "aa"}}}, + '字符串转json对象'); + +}); + +test('json2str', function () { + + equal(utils.json2str({"a": 11, "b": "22", "c": "cc", "d": [1, "2", "a", {"a": "aa"}], "e": {"k1": 1, "k2": "2", "k3": "a", "k4": {"a": "aa"}}}), + '{"a":11,"b":"22","c":"cc","d":[1,"2","a",{"a":"aa"}],"e":{"k1":1,"k2":"2","k3":"a","k4":{"a":"aa"}}}', + 'json对象转字符串'); + +}); +test('json2str 不使用原生方法', function () { + stop(); + var j = window.JSON; + var flag = 0; + ua.readFile("../../../_test/coverage/core/utils.js", function (s) { + if(s===null)flag = 1; + window.JSON = null; + eval(s); + equal(utils.json2str({"a": 11, "b": "22", "c": "cc", "d": [1, "2", "a", {"a": "aa"}], "e": {"k1": 1, "k2": "2", "k3": "a", "k4": {"a": "aa"}}}), + '{"a":11,"b":"22","c":"cc","d":[1,"2","a",{"a":"aa"}],"e":{"k1":1,"k2":"2","k3":"a","k4":{"a":"aa"}}}', + 'json对象转字符串'); + + window.JSON = j; + + }); + if(flag){ + ua.readFile("../../../_src/core/utils.js", function (s) { + window.JSON = null; + eval(s); + equal(utils.json2str({"a": 11, "b": "22", "c": "cc", "d": [1, "2", "a", {"a": "aa"}], "e": {"k1": 1, "k2": "2", "k3": "a", "k4": {"a": "aa"}}}), + '{"a":11,"b":"22","c":"cc","d":[1,"2","a",{"a":"aa"}],"e":{"k1":1,"k2":"2","k3":"a","k4":{"a":"aa"}}}', + 'json对象转字符串'); + + window.JSON = j; + + }); + } + + setTimeout(function(){start();},50); +}); + +test('clearEmptyAttrs', function () { + var utils = te.obj[0]; + var ob = utils.clearEmptyAttrs({a: 1, b: ''}); + ok(!ob.hasOwnProperty('b'), 'clearEmptyAttrs'); +}); +test('serializeParam', function () { + + equal(utils.serializeParam({ + key1: 'value1', + key2: 'value2', + key3: 33, + key4: '44', + key5: true, + key6: null, + key7: undefined, + key8: [11, 22, '33', 'aa', true, null] + }), + 'key1=value1&' + + 'key2=value2&' + + 'key3=33&' + + 'key4=44&' + + 'key5=true&' + + 'key7=undefined&' + + 'key8[]=11&' + + 'key8[]=22&' + + 'key8[]=33&' + + 'key8[]=aa&' + + 'key8[]=true&' + + 'key8[]=null', + '序列化obj对象为GET请求字符串'); + +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/api.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/api.js new file mode 100644 index 000000000..a1593ffd2 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/api.js @@ -0,0 +1,43 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['api.js']) { + _$jscoverage['api.js'] = []; +} +_$jscoverage['api.js'].source = ["/**"," * 该文件定义了API文档所使用到的本地函数的说明"," * @file"," * @module Native"," */","","/**"," * 辅助接口说明"," * @module Native"," * @unfile"," */","","/**"," * 原生String对象, 字符串"," * @class String"," */","","/**"," * 原生Function对象, 函数"," * @class Function"," */","","/**"," * 原生Object对象, 普通对象"," * @class Object"," */","","/**"," * 原生Boolean对象, 布尔值"," * @class Boolean"," */","","/**"," * 原生Number对象, 数值"," * @class Number"," */","","/**"," * 原生NULL对象, 空"," * @class NULL"," */","","/**"," * 原生Array对象, 数组"," * @class Array"," */","","/**"," * 浏览器DOMNode, dom节点"," * @class Node"," */","","/**"," * 浏览器DOMElement, dom元素"," * @class Element"," */"]; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/commands.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/commands.js new file mode 100644 index 000000000..9bd1f4b23 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/commands.js @@ -0,0 +1,43 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['commands.js']) { + _$jscoverage['commands.js'] = []; +} +_$jscoverage['commands.js'].source = ["//本文件非编辑器核心文件,仅适用于生成对应的命令接口文档","/**"," * @file"," * @name 编辑器命令接口"," * @short Commands"," * @desc"," *"," * UEditor中执行命令的统一调用格式为"," * <code>editor.execCommand(\"cmdName\"[,opt]);</code>"," *"," *"," * 检测当前命令是否可用的方法是"," * <code>editor.queryCommandState(\"cmdName\");</code>"," *"," *"," * 部分命令可以返回命令值,其格式为"," * <code>editor.queryCommandValue(\"cmdName\");</code>"," */","/**"," * 插入锚点"," * @name anchor"," * @grammar editor.execCommand(\"anchor\",\"name\"); //锚点的名字"," */","/**"," * 为当前选中文字添加粗体效果"," * @name bold"," * @grammar editor.execCommand(\"bold\");"," */","/**"," * 为当前选中文字添加斜体效果"," * @name italic"," * @grammar editor.execCommand(\"italic\");"," */","/**"," * 为当前选中文字添加下划线效果"," * @name underline"," * @grammar editor.execCommand(\"underline\");"," */","","","/**"," * 为当前选中文字添加删除线效果"," * @name strikethrough"," * @grammar editor.execCommand(\"strikethrough\");"," */","/**"," * 将当前选中文字转换成上标"," * @name superscript"," * @grammar editor.execCommand(\"superscript\");"," */","/**"," * 将当前选中文字转换成下标"," * @name subscript"," * @grammar editor.execCommand(\"subscript\");"," */","/**"," * 为当前选中文字添加颜色"," * @name foreColor"," * @grammar editor.execCommand(\"foreColor\",\"#ffffff\");"," */","/**"," * 为当前选中文字添加背景颜色"," * @name backColor"," * @grammar editor.execCommand(\"backColor\",\"#dddddd\");"," */","/**"," * 设置当前选中文字的字体"," * @name fontFamily"," * @grammar editor.execCommand(\"fontFamily\",\"微软雅黑,Microsoft YaHei\");"," */","/**"," * 设置当前选中文字的字号"," * @name fontSize"," * @grammar editor.execCommand(\"fontSize\",\"32px\");"," */","/**"," * 设置当前选区的段落格式,如p,h1,h2,h3,..."," * @name paragraph"," * @grammar editor.execCommand(\"paragraph\",\"h1\");"," */","/**"," * 将当前选区变换成有序或者无序列表"," * @name insert(Un)OrderedList"," * @grammar editor.execCommand(\"insertOrderedList\");"," */","/**"," * 设置当前选区的行间距"," * @name lineHeight"," * @grammar editor.execCommand(\"lineHeight\");"," */","/**"," * 设置当前选区中的字体对齐方式"," * @name justify"," * @grammar editor.execCommand(\"justify\",align); //align可为Left,Right,Center,Justify"," */","/**"," * 将当前选中文字中的字母转换成大写"," * @name toUppercase"," * @grammar editor.execCommand(\"toUppercase\");"," */","/**"," * 将当前选中文字中的字母转换成小写"," * @name toLowercase"," * @grammar editor.execCommand(\"toLowercase\");"," */","/**"," * 为当前选区所在的块级元素添加引用标记"," * @name blockquote"," * @grammar editor.execCommand(\"blockquote\");"," */","/**"," * 设置当前选区所在块级元素的文字输入方向"," * @name directionality"," * @grammar editor.execCommand(\"directionality\",dir); //dir可为LTR,RTL"," */","/**"," * 清除当前选中文字上的所有样式或者指定样式"," * @name removeFormat"," * @grammar editor.execCommand(\"removeFormat\") //根据ueditor.config.js里的removeFormatTags,removeFormatAttributes两个属性作为规则"," * @grammar editor.execCommand(\"removeFormat\",tags,style); //清除指定tags上的指定style"," * @example"," * editor.execCommand(\"removeFormat\",'span,a','color,background-color')"," */","/**"," * 切换纯文本粘贴模式"," * @name pastePlain"," * @grammar ue.execCommand(\"pastePlain\");"," */","/**"," * 开启格式刷功能"," * @name formatMatch"," * @grammar editor.execCommand(\"formatMatch\");"," */","/**"," * 清空文档"," * @name clearDoc"," * @grammar editor.execCommand(\"clearDoc\");"," */","/**"," * 删除当前选中文本"," * @name delete"," * @grammar editor.execCommand(\"delete\");"," */","/**"," * 全部选择"," * @name selectAll"," * @grammar editor.execCommand(\"selectAll\");"," */","/**"," * 撤销操作"," * @name undo"," * @grammar editor.execCommand(\"undo\");"," */","/**"," * 恢复操作"," * @name redo"," * @grammar editor.execCommand(\"redo\");"," */","/**"," * 对整个编辑文档进行自动排版"," * @name autoTypeset"," * @grammar editor.execCommand(\"autoTypeset\");"," */","/**"," * 在当前选区位置插入一段html代码,最基本功能。大部分其他插入命令都会调用此命令完成最后的插入"," * @name insertHtml"," * @grammar editor.execCommand(\"insertHtml\",\"欢迎使用UEditor!\")"," */","/**"," * 在当前选区位置插入一个超链接"," * @name link"," * @grammar editor.execCommand(\"link\",linkObj);"," * @example"," * editor.execCommand(\"link\",{"," * href: \"http://ueditor.baidu.com\", //超链地址,必选"," * _src: \"http://ueditor.baidu.com\", //UE内部使用参数,与href保持一致即可,可选"," * target: \"_self\", //目标窗口,可选"," * textValue: \"UEditor\", //链接显示文本,可选"," * title: \"百度开源富文本编辑器UEditor官网\" //标题,可选"," * })"," */","/**"," * 在当前选区位置插入一个图片"," * @name insertImage"," * @grammar editor.execCommand(\"insertImage\",imageObj);"," * @example"," * editor.execCommand(\"insertImage\",{"," * src: \"http://ueditor.baidu.com/logo.jpg\", //图片链接地址,必选"," * _src: \"http://ueditor.baidu.com/logo.jpg\", //UE内部使用参数,与src保持一致即可,可选"," * width: 300, //图片显示宽度,可选"," * height: 400, //图片显示高度,可选"," * border: 2, //图片边框,可选"," * hspace: 5, //图片左右边距,可选"," * vspace: 2, //图片上下边距,可选"," * alt: 'UEditor-logo', //图片替换文字,可选"," * title: \"百度开源富文本编辑器UEditor官网\" //图片标题,可选"," * })"," */","/**"," * 在当前选区位置插入一个视频"," * @name insertVideo"," * @grammar editor.execCommand(\"insertVideo\",videoObj);"," * @example"," * editor.execCommand(\"insertVideo\",{"," * url: \"http://youku.com/id?id=1233122\", //视频地址,必选"," * width: 420, //视频宽度,可选"," * height: 280, //视频高度,可选"," * align: \"none\" //对齐方式,支持right,left,center,none ,可选"," * })"," */","/**"," * 在当前选区位置插入一个日期或者时间"," * @name date|time"," * @grammar editor.execCommand(\"date\");"," */","/**"," * 在当前选区位置插入一个分页符标记"," * @name pageBreak"," * @grammar editor.execCommand(\"pageBreak\");"," */","/**"," * 切换源码编辑模式和富文本编辑模式"," * @name source"," * @grammar editor.execCommand(\"source\");"," */","/**"," * IE下进入截屏模式"," * @name snapScreen"," * @grammar editor.execCommand(\"snapScreen\");"," */","/**"," * 插入表格"," * @name insertTable"," * @grammar editor.execCommand(\"insertTable\",rows,cols);"," */","","/**"," * 查找替换"," * @name searchreplace"," * @grammar editor.execCommand(\"searchreplace\",opt);"," * @desc"," * opt是个json对象,属性如下"," * * ''all'' true表示查找整个文档,false表示从上次的位置开始查找,默认是false"," * * ''casesensitive'' 大小写铭感,true是铭感,默认是false"," * * ''dir'' 1表示从前往后查,-1表示从后往前"," * * ''searchStr'' 查找的字符串"," * * ''replaceStr'' 替换用的字符串"," */","","","","","","","","",""]; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/Editor.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/Editor.js new file mode 100644 index 000000000..524c2e45b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/Editor.js @@ -0,0 +1,1492 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['core/Editor.js']) { + _$jscoverage['core/Editor.js'] = []; + _$jscoverage['core/Editor.js'][22] = 0; + _$jscoverage['core/Editor.js'][23] = 0; + _$jscoverage['core/Editor.js'][32] = 0; + _$jscoverage['core/Editor.js'][33] = 0; + _$jscoverage['core/Editor.js'][34] = 0; + _$jscoverage['core/Editor.js'][35] = 0; + _$jscoverage['core/Editor.js'][36] = 0; + _$jscoverage['core/Editor.js'][37] = 0; + _$jscoverage['core/Editor.js'][38] = 0; + _$jscoverage['core/Editor.js'][39] = 0; + _$jscoverage['core/Editor.js'][43] = 0; + _$jscoverage['core/Editor.js'][46] = 0; + _$jscoverage['core/Editor.js'][47] = 0; + _$jscoverage['core/Editor.js'][53] = 0; + _$jscoverage['core/Editor.js'][55] = 0; + _$jscoverage['core/Editor.js'][66] = 0; + _$jscoverage['core/Editor.js'][68] = 0; + _$jscoverage['core/Editor.js'][69] = 0; + _$jscoverage['core/Editor.js'][71] = 0; + _$jscoverage['core/Editor.js'][73] = 0; + _$jscoverage['core/Editor.js'][82] = 0; + _$jscoverage['core/Editor.js'][83] = 0; + _$jscoverage['core/Editor.js'][84] = 0; + _$jscoverage['core/Editor.js'][135] = 0; + _$jscoverage['core/Editor.js'][136] = 0; + _$jscoverage['core/Editor.js'][137] = 0; + _$jscoverage['core/Editor.js'][138] = 0; + _$jscoverage['core/Editor.js'][139] = 0; + _$jscoverage['core/Editor.js'][140] = 0; + _$jscoverage['core/Editor.js'][141] = 0; + _$jscoverage['core/Editor.js'][142] = 0; + _$jscoverage['core/Editor.js'][143] = 0; + _$jscoverage['core/Editor.js'][145] = 0; + _$jscoverage['core/Editor.js'][171] = 0; + _$jscoverage['core/Editor.js'][173] = 0; + _$jscoverage['core/Editor.js'][174] = 0; + _$jscoverage['core/Editor.js'][176] = 0; + _$jscoverage['core/Editor.js'][182] = 0; + _$jscoverage['core/Editor.js'][186] = 0; + _$jscoverage['core/Editor.js'][188] = 0; + _$jscoverage['core/Editor.js'][205] = 0; + _$jscoverage['core/Editor.js'][206] = 0; + _$jscoverage['core/Editor.js'][207] = 0; + _$jscoverage['core/Editor.js'][238] = 0; + _$jscoverage['core/Editor.js'][239] = 0; + _$jscoverage['core/Editor.js'][240] = 0; + _$jscoverage['core/Editor.js'][242] = 0; + _$jscoverage['core/Editor.js'][244] = 0; + _$jscoverage['core/Editor.js'][258] = 0; + _$jscoverage['core/Editor.js'][259] = 0; + _$jscoverage['core/Editor.js'][260] = 0; + _$jscoverage['core/Editor.js'][261] = 0; + _$jscoverage['core/Editor.js'][262] = 0; + _$jscoverage['core/Editor.js'][263] = 0; + _$jscoverage['core/Editor.js'][264] = 0; + _$jscoverage['core/Editor.js'][266] = 0; + _$jscoverage['core/Editor.js'][269] = 0; + _$jscoverage['core/Editor.js'][270] = 0; + _$jscoverage['core/Editor.js'][271] = 0; + _$jscoverage['core/Editor.js'][272] = 0; + _$jscoverage['core/Editor.js'][273] = 0; + _$jscoverage['core/Editor.js'][274] = 0; + _$jscoverage['core/Editor.js'][275] = 0; + _$jscoverage['core/Editor.js'][277] = 0; + _$jscoverage['core/Editor.js'][278] = 0; + _$jscoverage['core/Editor.js'][279] = 0; + _$jscoverage['core/Editor.js'][282] = 0; + _$jscoverage['core/Editor.js'][299] = 0; + _$jscoverage['core/Editor.js'][302] = 0; + _$jscoverage['core/Editor.js'][304] = 0; + _$jscoverage['core/Editor.js'][305] = 0; + _$jscoverage['core/Editor.js'][307] = 0; + _$jscoverage['core/Editor.js'][308] = 0; + _$jscoverage['core/Editor.js'][309] = 0; + _$jscoverage['core/Editor.js'][311] = 0; + _$jscoverage['core/Editor.js'][313] = 0; + _$jscoverage['core/Editor.js'][314] = 0; + _$jscoverage['core/Editor.js'][316] = 0; + _$jscoverage['core/Editor.js'][319] = 0; + _$jscoverage['core/Editor.js'][321] = 0; + _$jscoverage['core/Editor.js'][324] = 0; + _$jscoverage['core/Editor.js'][326] = 0; + _$jscoverage['core/Editor.js'][342] = 0; + _$jscoverage['core/Editor.js'][350] = 0; + _$jscoverage['core/Editor.js'][352] = 0; + _$jscoverage['core/Editor.js'][353] = 0; + _$jscoverage['core/Editor.js'][354] = 0; + _$jscoverage['core/Editor.js'][355] = 0; + _$jscoverage['core/Editor.js'][357] = 0; + _$jscoverage['core/Editor.js'][358] = 0; + _$jscoverage['core/Editor.js'][359] = 0; + _$jscoverage['core/Editor.js'][373] = 0; + _$jscoverage['core/Editor.js'][375] = 0; + _$jscoverage['core/Editor.js'][376] = 0; + _$jscoverage['core/Editor.js'][377] = 0; + _$jscoverage['core/Editor.js'][378] = 0; + _$jscoverage['core/Editor.js'][380] = 0; + _$jscoverage['core/Editor.js'][382] = 0; + _$jscoverage['core/Editor.js'][383] = 0; + _$jscoverage['core/Editor.js'][384] = 0; + _$jscoverage['core/Editor.js'][385] = 0; + _$jscoverage['core/Editor.js'][386] = 0; + _$jscoverage['core/Editor.js'][388] = 0; + _$jscoverage['core/Editor.js'][390] = 0; + _$jscoverage['core/Editor.js'][391] = 0; + _$jscoverage['core/Editor.js'][392] = 0; + _$jscoverage['core/Editor.js'][394] = 0; + _$jscoverage['core/Editor.js'][396] = 0; + _$jscoverage['core/Editor.js'][397] = 0; + _$jscoverage['core/Editor.js'][398] = 0; + _$jscoverage['core/Editor.js'][399] = 0; + _$jscoverage['core/Editor.js'][400] = 0; + _$jscoverage['core/Editor.js'][401] = 0; + _$jscoverage['core/Editor.js'][404] = 0; + _$jscoverage['core/Editor.js'][405] = 0; + _$jscoverage['core/Editor.js'][408] = 0; + _$jscoverage['core/Editor.js'][411] = 0; + _$jscoverage['core/Editor.js'][412] = 0; + _$jscoverage['core/Editor.js'][413] = 0; + _$jscoverage['core/Editor.js'][414] = 0; + _$jscoverage['core/Editor.js'][415] = 0; + _$jscoverage['core/Editor.js'][416] = 0; + _$jscoverage['core/Editor.js'][418] = 0; + _$jscoverage['core/Editor.js'][420] = 0; + _$jscoverage['core/Editor.js'][425] = 0; + _$jscoverage['core/Editor.js'][426] = 0; + _$jscoverage['core/Editor.js'][429] = 0; + _$jscoverage['core/Editor.js'][430] = 0; + _$jscoverage['core/Editor.js'][431] = 0; + _$jscoverage['core/Editor.js'][433] = 0; + _$jscoverage['core/Editor.js'][436] = 0; + _$jscoverage['core/Editor.js'][437] = 0; + _$jscoverage['core/Editor.js'][439] = 0; + _$jscoverage['core/Editor.js'][440] = 0; + _$jscoverage['core/Editor.js'][443] = 0; + _$jscoverage['core/Editor.js'][444] = 0; + _$jscoverage['core/Editor.js'][447] = 0; + _$jscoverage['core/Editor.js'][448] = 0; + _$jscoverage['core/Editor.js'][451] = 0; + _$jscoverage['core/Editor.js'][452] = 0; + _$jscoverage['core/Editor.js'][458] = 0; + _$jscoverage['core/Editor.js'][459] = 0; + _$jscoverage['core/Editor.js'][460] = 0; + _$jscoverage['core/Editor.js'][461] = 0; + _$jscoverage['core/Editor.js'][462] = 0; + _$jscoverage['core/Editor.js'][463] = 0; + _$jscoverage['core/Editor.js'][465] = 0; + _$jscoverage['core/Editor.js'][466] = 0; + _$jscoverage['core/Editor.js'][467] = 0; + _$jscoverage['core/Editor.js'][468] = 0; + _$jscoverage['core/Editor.js'][469] = 0; + _$jscoverage['core/Editor.js'][471] = 0; + _$jscoverage['core/Editor.js'][475] = 0; + _$jscoverage['core/Editor.js'][476] = 0; + _$jscoverage['core/Editor.js'][483] = 0; + _$jscoverage['core/Editor.js'][485] = 0; + _$jscoverage['core/Editor.js'][486] = 0; + _$jscoverage['core/Editor.js'][487] = 0; + _$jscoverage['core/Editor.js'][489] = 0; + _$jscoverage['core/Editor.js'][490] = 0; + _$jscoverage['core/Editor.js'][493] = 0; + _$jscoverage['core/Editor.js'][494] = 0; + _$jscoverage['core/Editor.js'][515] = 0; + _$jscoverage['core/Editor.js'][518] = 0; + _$jscoverage['core/Editor.js'][520] = 0; + _$jscoverage['core/Editor.js'][533] = 0; + _$jscoverage['core/Editor.js'][534] = 0; + _$jscoverage['core/Editor.js'][536] = 0; + _$jscoverage['core/Editor.js'][538] = 0; + _$jscoverage['core/Editor.js'][564] = 0; + _$jscoverage['core/Editor.js'][565] = 0; + _$jscoverage['core/Editor.js'][566] = 0; + _$jscoverage['core/Editor.js'][568] = 0; + _$jscoverage['core/Editor.js'][570] = 0; + _$jscoverage['core/Editor.js'][579] = 0; + _$jscoverage['core/Editor.js'][580] = 0; + _$jscoverage['core/Editor.js'][581] = 0; + _$jscoverage['core/Editor.js'][582] = 0; + _$jscoverage['core/Editor.js'][583] = 0; + _$jscoverage['core/Editor.js'][584] = 0; + _$jscoverage['core/Editor.js'][585] = 0; + _$jscoverage['core/Editor.js'][586] = 0; + _$jscoverage['core/Editor.js'][587] = 0; + _$jscoverage['core/Editor.js'][588] = 0; + _$jscoverage['core/Editor.js'][594] = 0; + _$jscoverage['core/Editor.js'][595] = 0; + _$jscoverage['core/Editor.js'][596] = 0; + _$jscoverage['core/Editor.js'][635] = 0; + _$jscoverage['core/Editor.js'][636] = 0; + _$jscoverage['core/Editor.js'][637] = 0; + _$jscoverage['core/Editor.js'][638] = 0; + _$jscoverage['core/Editor.js'][640] = 0; + _$jscoverage['core/Editor.js'][641] = 0; + _$jscoverage['core/Editor.js'][643] = 0; + _$jscoverage['core/Editor.js'][644] = 0; + _$jscoverage['core/Editor.js'][645] = 0; + _$jscoverage['core/Editor.js'][646] = 0; + _$jscoverage['core/Editor.js'][647] = 0; + _$jscoverage['core/Editor.js'][660] = 0; + _$jscoverage['core/Editor.js'][663] = 0; + _$jscoverage['core/Editor.js'][664] = 0; + _$jscoverage['core/Editor.js'][665] = 0; + _$jscoverage['core/Editor.js'][666] = 0; + _$jscoverage['core/Editor.js'][667] = 0; + _$jscoverage['core/Editor.js'][669] = 0; + _$jscoverage['core/Editor.js'][670] = 0; + _$jscoverage['core/Editor.js'][674] = 0; + _$jscoverage['core/Editor.js'][689] = 0; + _$jscoverage['core/Editor.js'][691] = 0; + _$jscoverage['core/Editor.js'][695] = 0; + _$jscoverage['core/Editor.js'][698] = 0; + _$jscoverage['core/Editor.js'][711] = 0; + _$jscoverage['core/Editor.js'][713] = 0; + _$jscoverage['core/Editor.js'][755] = 0; + _$jscoverage['core/Editor.js'][757] = 0; + _$jscoverage['core/Editor.js'][758] = 0; + _$jscoverage['core/Editor.js'][759] = 0; + _$jscoverage['core/Editor.js'][760] = 0; + _$jscoverage['core/Editor.js'][763] = 0; + _$jscoverage['core/Editor.js'][766] = 0; + _$jscoverage['core/Editor.js'][767] = 0; + _$jscoverage['core/Editor.js'][771] = 0; + _$jscoverage['core/Editor.js'][773] = 0; + _$jscoverage['core/Editor.js'][774] = 0; + _$jscoverage['core/Editor.js'][779] = 0; + _$jscoverage['core/Editor.js'][782] = 0; + _$jscoverage['core/Editor.js'][783] = 0; + _$jscoverage['core/Editor.js'][784] = 0; + _$jscoverage['core/Editor.js'][785] = 0; + _$jscoverage['core/Editor.js'][786] = 0; + _$jscoverage['core/Editor.js'][787] = 0; + _$jscoverage['core/Editor.js'][789] = 0; + _$jscoverage['core/Editor.js'][790] = 0; + _$jscoverage['core/Editor.js'][791] = 0; + _$jscoverage['core/Editor.js'][792] = 0; + _$jscoverage['core/Editor.js'][794] = 0; + _$jscoverage['core/Editor.js'][795] = 0; + _$jscoverage['core/Editor.js'][798] = 0; + _$jscoverage['core/Editor.js'][802] = 0; + _$jscoverage['core/Editor.js'][803] = 0; + _$jscoverage['core/Editor.js'][805] = 0; + _$jscoverage['core/Editor.js'][807] = 0; + _$jscoverage['core/Editor.js'][809] = 0; + _$jscoverage['core/Editor.js'][810] = 0; + _$jscoverage['core/Editor.js'][811] = 0; + _$jscoverage['core/Editor.js'][813] = 0; + _$jscoverage['core/Editor.js'][814] = 0; + _$jscoverage['core/Editor.js'][837] = 0; + _$jscoverage['core/Editor.js'][838] = 0; + _$jscoverage['core/Editor.js'][840] = 0; + _$jscoverage['core/Editor.js'][841] = 0; + _$jscoverage['core/Editor.js'][843] = 0; + _$jscoverage['core/Editor.js'][845] = 0; + _$jscoverage['core/Editor.js'][856] = 0; + _$jscoverage['core/Editor.js'][859] = 0; + _$jscoverage['core/Editor.js'][860] = 0; + _$jscoverage['core/Editor.js'][861] = 0; + _$jscoverage['core/Editor.js'][862] = 0; + _$jscoverage['core/Editor.js'][864] = 0; + _$jscoverage['core/Editor.js'][865] = 0; + _$jscoverage['core/Editor.js'][867] = 0; + _$jscoverage['core/Editor.js'][868] = 0; + _$jscoverage['core/Editor.js'][921] = 0; + _$jscoverage['core/Editor.js'][929] = 0; + _$jscoverage['core/Editor.js'][936] = 0; + _$jscoverage['core/Editor.js'][937] = 0; + _$jscoverage['core/Editor.js'][938] = 0; + _$jscoverage['core/Editor.js'][939] = 0; + _$jscoverage['core/Editor.js'][940] = 0; + _$jscoverage['core/Editor.js'][941] = 0; + _$jscoverage['core/Editor.js'][942] = 0; + _$jscoverage['core/Editor.js'][943] = 0; + _$jscoverage['core/Editor.js'][946] = 0; + _$jscoverage['core/Editor.js'][947] = 0; + _$jscoverage['core/Editor.js'][948] = 0; + _$jscoverage['core/Editor.js'][949] = 0; + _$jscoverage['core/Editor.js'][953] = 0; + _$jscoverage['core/Editor.js'][954] = 0; + _$jscoverage['core/Editor.js'][955] = 0; + _$jscoverage['core/Editor.js'][956] = 0; + _$jscoverage['core/Editor.js'][957] = 0; + _$jscoverage['core/Editor.js'][959] = 0; + _$jscoverage['core/Editor.js'][962] = 0; + _$jscoverage['core/Editor.js'][963] = 0; + _$jscoverage['core/Editor.js'][964] = 0; + _$jscoverage['core/Editor.js'][965] = 0; + _$jscoverage['core/Editor.js'][966] = 0; + _$jscoverage['core/Editor.js'][969] = 0; + _$jscoverage['core/Editor.js'][970] = 0; + _$jscoverage['core/Editor.js'][971] = 0; + _$jscoverage['core/Editor.js'][973] = 0; + _$jscoverage['core/Editor.js'][974] = 0; + _$jscoverage['core/Editor.js'][976] = 0; + _$jscoverage['core/Editor.js'][977] = 0; + _$jscoverage['core/Editor.js'][978] = 0; + _$jscoverage['core/Editor.js'][992] = 0; + _$jscoverage['core/Editor.js'][994] = 0; + _$jscoverage['core/Editor.js'][995] = 0; + _$jscoverage['core/Editor.js'][997] = 0; + _$jscoverage['core/Editor.js'][998] = 0; + _$jscoverage['core/Editor.js'][999] = 0; + _$jscoverage['core/Editor.js'][1000] = 0; + _$jscoverage['core/Editor.js'][1014] = 0; + _$jscoverage['core/Editor.js'][1015] = 0; + _$jscoverage['core/Editor.js'][1018] = 0; + _$jscoverage['core/Editor.js'][1019] = 0; + _$jscoverage['core/Editor.js'][1021] = 0; + _$jscoverage['core/Editor.js'][1022] = 0; + _$jscoverage['core/Editor.js'][1023] = 0; + _$jscoverage['core/Editor.js'][1024] = 0; + _$jscoverage['core/Editor.js'][1025] = 0; + _$jscoverage['core/Editor.js'][1026] = 0; + _$jscoverage['core/Editor.js'][1027] = 0; + _$jscoverage['core/Editor.js'][1029] = 0; + _$jscoverage['core/Editor.js'][1031] = 0; + _$jscoverage['core/Editor.js'][1032] = 0; + _$jscoverage['core/Editor.js'][1034] = 0; + _$jscoverage['core/Editor.js'][1035] = 0; + _$jscoverage['core/Editor.js'][1051] = 0; + _$jscoverage['core/Editor.js'][1062] = 0; + _$jscoverage['core/Editor.js'][1088] = 0; + _$jscoverage['core/Editor.js'][1089] = 0; + _$jscoverage['core/Editor.js'][1090] = 0; + _$jscoverage['core/Editor.js'][1091] = 0; + _$jscoverage['core/Editor.js'][1095] = 0; + _$jscoverage['core/Editor.js'][1096] = 0; + _$jscoverage['core/Editor.js'][1099] = 0; + _$jscoverage['core/Editor.js'][1100] = 0; + _$jscoverage['core/Editor.js'][1101] = 0; + _$jscoverage['core/Editor.js'][1102] = 0; + _$jscoverage['core/Editor.js'][1103] = 0; + _$jscoverage['core/Editor.js'][1104] = 0; + _$jscoverage['core/Editor.js'][1108] = 0; + _$jscoverage['core/Editor.js'][1121] = 0; + _$jscoverage['core/Editor.js'][1133] = 0; + _$jscoverage['core/Editor.js'][1134] = 0; + _$jscoverage['core/Editor.js'][1135] = 0; + _$jscoverage['core/Editor.js'][1136] = 0; + _$jscoverage['core/Editor.js'][1138] = 0; + _$jscoverage['core/Editor.js'][1139] = 0; + _$jscoverage['core/Editor.js'][1140] = 0; + _$jscoverage['core/Editor.js'][1142] = 0; + _$jscoverage['core/Editor.js'][1144] = 0; + _$jscoverage['core/Editor.js'][1145] = 0; + _$jscoverage['core/Editor.js'][1146] = 0; + _$jscoverage['core/Editor.js'][1147] = 0; + _$jscoverage['core/Editor.js'][1149] = 0; + _$jscoverage['core/Editor.js'][1164] = 0; + _$jscoverage['core/Editor.js'][1191] = 0; + _$jscoverage['core/Editor.js'][1192] = 0; + _$jscoverage['core/Editor.js'][1193] = 0; + _$jscoverage['core/Editor.js'][1194] = 0; + _$jscoverage['core/Editor.js'][1195] = 0; + _$jscoverage['core/Editor.js'][1197] = 0; + _$jscoverage['core/Editor.js'][1198] = 0; + _$jscoverage['core/Editor.js'][1199] = 0; + _$jscoverage['core/Editor.js'][1200] = 0; + _$jscoverage['core/Editor.js'][1201] = 0; + _$jscoverage['core/Editor.js'][1203] = 0; + _$jscoverage['core/Editor.js'][1205] = 0; + _$jscoverage['core/Editor.js'][1236] = 0; + _$jscoverage['core/Editor.js'][1246] = 0; + _$jscoverage['core/Editor.js'][1247] = 0; + _$jscoverage['core/Editor.js'][1248] = 0; + _$jscoverage['core/Editor.js'][1249] = 0; + _$jscoverage['core/Editor.js'][1250] = 0; + _$jscoverage['core/Editor.js'][1251] = 0; + _$jscoverage['core/Editor.js'][1252] = 0; + _$jscoverage['core/Editor.js'][1253] = 0; + _$jscoverage['core/Editor.js'][1258] = 0; + _$jscoverage['core/Editor.js'][1259] = 0; + _$jscoverage['core/Editor.js'][1260] = 0; + _$jscoverage['core/Editor.js'][1262] = 0; + _$jscoverage['core/Editor.js'][1272] = 0; + _$jscoverage['core/Editor.js'][1273] = 0; + _$jscoverage['core/Editor.js'][1275] = 0; + _$jscoverage['core/Editor.js'][1276] = 0; + _$jscoverage['core/Editor.js'][1277] = 0; + _$jscoverage['core/Editor.js'][1279] = 0; + _$jscoverage['core/Editor.js'][1282] = 0; + _$jscoverage['core/Editor.js'][1283] = 0; + _$jscoverage['core/Editor.js'][1285] = 0; + _$jscoverage['core/Editor.js'][1299] = 0; + _$jscoverage['core/Editor.js'][1308] = 0; + _$jscoverage['core/Editor.js'][1309] = 0; + _$jscoverage['core/Editor.js'][1310] = 0; + _$jscoverage['core/Editor.js'][1312] = 0; + _$jscoverage['core/Editor.js'][1325] = 0; + _$jscoverage['core/Editor.js'][1339] = 0; + _$jscoverage['core/Editor.js'][1340] = 0; + _$jscoverage['core/Editor.js'][1341] = 0; + _$jscoverage['core/Editor.js'][1343] = 0; + _$jscoverage['core/Editor.js'][1344] = 0; + _$jscoverage['core/Editor.js'][1345] = 0; + _$jscoverage['core/Editor.js'][1346] = 0; + _$jscoverage['core/Editor.js'][1348] = 0; + _$jscoverage['core/Editor.js'][1385] = 0; + _$jscoverage['core/Editor.js'][1386] = 0; + _$jscoverage['core/Editor.js'][1387] = 0; + _$jscoverage['core/Editor.js'][1388] = 0; + _$jscoverage['core/Editor.js'][1389] = 0; + _$jscoverage['core/Editor.js'][1390] = 0; + _$jscoverage['core/Editor.js'][1393] = 0; + _$jscoverage['core/Editor.js'][1410] = 0; + _$jscoverage['core/Editor.js'][1424] = 0; + _$jscoverage['core/Editor.js'][1425] = 0; + _$jscoverage['core/Editor.js'][1443] = 0; + _$jscoverage['core/Editor.js'][1457] = 0; + _$jscoverage['core/Editor.js'][1458] = 0; + _$jscoverage['core/Editor.js'][1462] = 0; +} +_$jscoverage['core/Editor.js'].source = ["/**"," * 编辑器主类,包含编辑器提供的大部分公用接口"," * @file"," * @module UE"," * @class Editor"," * @since 1.2.6.1"," */","","/**"," * UEditor公用空间,UEditor所有的功能都挂载在该空间下"," * @unfile"," * @module UE"," */","","/**"," * UEditor的核心类,为用户提供与编辑器交互的接口。"," * @unfile"," * @module UE"," * @class Editor"," */","","(function () {"," var uid = 0, _selectionChangeTimer;","",""," /**"," * 获取编辑器的html内容,赋值到编辑器所在表单的textarea文本域里面"," * @private"," * @method setValue"," * @param { UE.Editor } editor 编辑器事例"," */"," function setValue(form, editor) {"," var textarea;"," if (editor.textarea) {"," if (utils.isString(editor.textarea)) {"," for (var i = 0, ti, tis = domUtils.getElementsByTagName(form, 'textarea'); ti = tis[i++];) {"," if (ti.id == 'ueditor_textarea_' + editor.options.textarea) {"," textarea = ti;"," break;"," }"," }"," } else {"," textarea = editor.textarea;"," }"," }"," if (!textarea) {"," form.appendChild(textarea = domUtils.createElement(document, 'textarea', {"," 'name': editor.options.textarea,"," 'id': 'ueditor_textarea_' + editor.options.textarea,"," 'style': \"display:none\""," }));"," //不要产生多个textarea"," editor.textarea = textarea;"," }"," textarea.value = editor.hasContents() ?"," (editor.options.allHtmlEnabled ? editor.getAllHtml() : editor.getContent(null, null, true)) :"," ''"," }",""," /**"," * 初始化插件"," * @private"," * @method loadPlugins"," * @param { UE.Editor } editor 编辑器事例"," */"," function loadPlugins(me) {"," //初始化插件"," for (var pi in UE.plugins) {"," UE.plugins[pi].call(me);"," }"," me.langIsReady = true;",""," me.fireEvent(\"langReady\");"," }",""," /**"," * 获取语言包里面的第一个"," * @private"," * @method checkCurLang"," * @param { KeyValueMap } I18N 编辑器事例"," */"," function checkCurLang(I18N) {"," for (var lang in I18N) {"," return lang"," }"," }","",""," /**"," * 编辑器准备就绪后会触发该事件"," * @module UE"," * @class Editor"," * @event ready"," * @example"," * ```javascript"," * editor.addListener( 'ready', function( editor ) {"," * editor.execCommand( 'focus' );"," * } );"," * ```"," */",""," /**"," * 每当编辑器内部选区发生改变后, 将触发该事件"," * @event selectionchange"," * @warning 该事件的触发非常频繁,不建议在该事件的处理过程中做重量级的处理"," * @example"," * ```javascript"," * editor.addListener( 'selectionchange', function( editor ) {"," * console.log('选区发生改变');"," * }"," */",""," /**"," * 以默认参数构建一个编辑器实例"," * @constructor"," * @example"," * ```javascript"," * var editor = new UE.Editor();"," * editor.execCommand('blod');"," * ```"," * @see UE.Config"," */",""," /**"," * 以给定的参数集合创建一个编辑器对象,对于未指定的参数,将应用默认参数。"," * @constructor"," * @param { KeyValueMap } setting 创建编辑器的参数"," * @example"," * ```javascript"," * var editor = new UE.Editor();"," * editor.execCommand('blod');"," * ```"," * @see UE.Config"," */"," var Editor = UE.Editor = function (options) {"," var me = this;"," me.uid = uid++;"," EventBase.call(me);"," me.commands = {};"," me.options = utils.extend(utils.clone(options || {}), UEDITOR_CONFIG, true);"," me.shortcutkeys = {};"," me.inputRules = [];"," me.outputRules = [];"," //设置默认的常用属性"," me.setOpt({"," isShow: true,"," initialContent: '',"," initialStyle: '',"," autoClearinitialContent: false,"," iframeCssUrl: me.options.UEDITOR_HOME_URL + 'themes/iframe.css',"," textarea: 'editorValue',"," focus: false,"," focusInEnd: true,"," autoClearEmptyNode: true,"," fullscreen: false,"," readonly: false,"," zIndex: 999,"," imagePopup: true,"," enterTag: 'p',"," customDomain: false,"," lang: 'zh-cn',"," langPath: me.options.UEDITOR_HOME_URL + 'lang/',"," theme: 'default',"," themePath: me.options.UEDITOR_HOME_URL + 'themes/',"," allHtmlEnabled: false,"," scaleEnabled: false,"," tableNativeEditInFF: false,"," autoSyncData: true"," });",""," if (!utils.isEmptyObject(UE.I18N)) {"," //修改默认的语言类型"," me.options.lang = checkCurLang(UE.I18N);"," loadPlugins(me)"," } else {"," utils.loadFile(document, {"," src: me.options.langPath + me.options.lang + \"/\" + me.options.lang + \".js\","," tag: \"script\","," type: \"text/javascript\","," defer: \"defer\""," }, function () {"," loadPlugins(me)"," });"," }",""," UE.instants['ueditorInstant' + me.uid] = me;"," };"," Editor.prototype = {","",""," /**"," * 编辑器对外提供的监听ready事件的接口, 通过调用该方法,达到的效果与监听ready事件是一致的"," * @method ready"," * @param { Function } fn 编辑器ready之后所执行的回调, 如果在注册事件之前编辑器已经ready,将会"," * 立即触发该回调。"," * @see UE.Editor.event:ready"," * @example"," * ```javascript"," * editor.ready( function( editor ) {"," * editor.setContent('初始化完毕');"," * } );"," * ```"," */"," ready: function (fn) {"," var me = this;"," if (fn) {"," me.isReady ? fn.apply(me) : me.addListener('ready', fn);"," }"," },","",""," /**"," * 该方法是提供给插件里面使用,以key,value的方式设置插件内用到的配置项默认值"," * @method setOpt"," * @warning 在config文件里面有定义参数key或者用户实例化的时候有传入参数key,该方法设置的key参数值无效"," * @warning 该方法仅供编辑器插件内部和编辑器初始化时调用,其他地方不能调用。"," * @param { String } key 编辑器的可接受的选项名称"," * @param { * } val 该选项可接受的值"," * @example"," * ```javascript"," * editor.setOpt( 'initContent', '欢迎使用编辑器' );"," * ```"," */",""," /**"," * 该方法是提供给插件里面使用,以{key:value}集合的方式设置插件内用到的配置项默认值"," * @method setOpt"," * @warning 在config文件里面有定义参数key或者用户实例化的时候有传入参数key,该方法设置的key参数值无效"," * @warning 该方法仅供编辑器插件内部和编辑器初始化时调用,其他地方不能调用。"," * @example"," * ```javascript"," * editor.setOpt( {"," * 'initContent': '欢迎使用编辑器'"," * } );"," * ```"," */"," setOpt: function (key, val) {"," var obj = {};"," if (utils.isString(key)) {"," obj[key] = val"," } else {"," obj = key;"," }"," utils.extend(this.options, obj, true);"," },","",""," /**"," * 销毁编辑器实例对象"," * @method destroy"," * @example"," * ```javascript"," * editor.destroy();"," * ```"," */"," destroy: function () {",""," var me = this;"," me.fireEvent('destroy');"," var container = me.container.parentNode;"," var textarea = me.textarea;"," if (!textarea) {"," textarea = document.createElement('textarea');"," container.parentNode.insertBefore(textarea, container);"," } else {"," textarea.style.display = ''"," }",""," textarea.style.width = me.iframe.offsetWidth + 'px';"," textarea.style.height = me.iframe.offsetHeight + 'px';"," textarea.value = me.getContent();"," textarea.id = me.key;"," container.innerHTML = '';"," domUtils.remove(container);"," var key = me.key;"," //trace:2004"," for (var p in me) {"," if (me.hasOwnProperty(p)) {"," delete this[p];"," }"," }"," UE.delEditor(key);"," },",""," /**"," * 渲染编辑器的DOM到指定容器"," * @method render"," * @param { String } containerId 指定一个容器ID"," * @warning 必须且只能调用一次"," */",""," /**"," * 渲染编辑器的DOM到指定容器"," * @method render"," * @param { Element } containerDom 直接指定容器对象"," * @warning 必须且只能调用一次"," */"," render: function (container) {"," var me = this,"," options = me.options,"," getStyleValue = function (attr) {"," return parseInt(domUtils.getComputedStyle(container, attr));"," };"," if (utils.isString(container)) {"," container = document.getElementById(container);"," }"," if (container) {"," if (options.initialFrameWidth) {"," options.minFrameWidth = options.initialFrameWidth"," } else {"," options.minFrameWidth = options.initialFrameWidth = container.offsetWidth;"," }"," if (options.initialFrameHeight) {"," options.minFrameHeight = options.initialFrameHeight"," } else {"," options.initialFrameHeight = options.minFrameHeight = container.offsetHeight;"," }",""," container.style.width = /%$/.test(options.initialFrameWidth) ? '100%' : options.initialFrameWidth -"," getStyleValue(\"padding-left\") - getStyleValue(\"padding-right\") + 'px';"," container.style.height = /%$/.test(options.initialFrameHeight) ? '100%' : options.initialFrameHeight -"," getStyleValue(\"padding-top\") - getStyleValue(\"padding-bottom\") + 'px';",""," container.style.zIndex = options.zIndex;",""," var html = ( ie && browser.version < 9 ? '' : '<!DOCTYPE html>') +"," '<html xmlns=\\'http://www.w3.org/1999/xhtml\\' class=\\'view\\' ><head>' +"," '<style type=\\'text/css\\'>' +"," //设置四周的留边"," '.view{padding:0;word-wrap:break-word;cursor:text;height:90%;}\\n' +"," //设置默认字体和字号"," //font-family不能呢随便改,在safari下fillchar会有解析问题"," 'body{margin:8px;font-family:sans-serif;font-size:16px;}' +"," //设置段落间距"," 'p{margin:5px 0;}</style>' +"," ( options.iframeCssUrl ? '<link rel=\\'stylesheet\\' type=\\'text/css\\' href=\\'' + utils.unhtml(options.iframeCssUrl) + '\\'/>' : '' ) +"," (options.initialStyle ? '<style>' + options.initialStyle + '</style>' : '') +"," '</head><body class=\\'view\\' ></body>' +"," '<script type=\\'text/javascript\\' ' + (ie ? 'defer=\\'defer\\'' : '' ) + ' id=\\'_initialScript\\'>' +"," 'setTimeout(function(){window.parent.UE.instants[\\'ueditorInstant' + me.uid + '\\']._setup(document);},0);' +"," 'var _tmpScript = document.getElementById(\\'_initialScript\\');_tmpScript.parentNode.removeChild(_tmpScript);</script></html>';"," container.appendChild(domUtils.createElement(document, 'iframe', {"," id: 'ueditor_' + me.uid,"," width: \"100%\","," height: \"100%\","," frameborder: \"0\","," src: 'javascript:void(function(){document.open();' + (options.customDomain && document.domain != location.hostname ? 'document.domain=\"' + document.domain + '\";' : '') +"," 'document.write(\"' + html + '\");document.close();}())'"," }));"," container.style.overflow = 'hidden';"," //解决如果是给定的百分比,会导致高度算不对的问题"," setTimeout(function () {"," if (/%$/.test(options.initialFrameWidth)) {"," options.minFrameWidth = options.initialFrameWidth = container.offsetWidth;"," container.style.width = options.initialFrameWidth + 'px';"," }"," if (/%$/.test(options.initialFrameHeight)) {"," options.minFrameHeight = options.initialFrameHeight = container.offsetHeight;"," container.style.height = options.initialFrameHeight + 'px';"," }"," })"," }"," },",""," /**"," * 编辑器初始化"," * @method _setup"," * @private"," * @param { Element } doc 编辑器Iframe中的文档对象"," */"," _setup: function (doc) {",""," var me = this,"," options = me.options;"," if (ie) {"," doc.body.disabled = true;"," doc.body.contentEditable = true;"," doc.body.disabled = false;"," } else {"," doc.body.contentEditable = true;"," }"," doc.body.spellcheck = false;"," me.document = doc;"," me.window = doc.defaultView || doc.parentWindow;"," me.iframe = me.window.frameElement;"," me.body = doc.body;",""," me.selection = new dom.Selection(doc);"," //gecko初始化就能得到range,无法判断isFocus了"," var geckoSel;"," if (browser.gecko && (geckoSel = this.selection.getNative())) {"," geckoSel.removeAllRanges();"," }"," this._initEvents();"," //为form提交提供一个隐藏的textarea"," for (var form = this.iframe.parentNode; !domUtils.isBody(form); form = form.parentNode) {"," if (form.tagName == 'FORM') {"," me.form = form;"," if (me.options.autoSyncData) {"," domUtils.on(me.window, 'blur', function () {"," setValue(form, me);"," });"," } else {"," domUtils.on(form, 'submit', function () {"," setValue(this, me);"," });"," }"," break;"," }"," }"," if (options.initialContent) {"," if (options.autoClearinitialContent) {"," var oldExecCommand = me.execCommand;"," me.execCommand = function () {"," me.fireEvent('firstBeforeExecCommand');"," return oldExecCommand.apply(me, arguments);"," };"," this._setDefaultContent(options.initialContent);"," } else"," this.setContent(options.initialContent, false, true);"," }",""," //编辑器不能为空内容",""," if (domUtils.isEmptyNode(me.body)) {"," me.body.innerHTML = '<p>' + (browser.ie ? '' : '<br/>') + '</p>';"," }"," //如果要求focus, 就把光标定位到内容开始"," if (options.focus) {"," setTimeout(function () {"," me.focus(me.options.focusInEnd);"," //如果自动清除开着,就不需要做selectionchange;"," !me.options.autoClearinitialContent && me._selectionChange();"," }, 0);"," }"," if (!me.container) {"," me.container = this.iframe.parentNode;"," }"," if (options.fullscreen && me.ui) {"," me.ui.setFullScreen(true);"," }",""," try {"," me.document.execCommand('2D-position', false, false);"," } catch (e) {"," }"," try {"," me.document.execCommand('enableInlineTableEditing', false, false);"," } catch (e) {"," }"," try {"," me.document.execCommand('enableObjectResizing', false, false);"," } catch (e) {","// domUtils.on(me.body,browser.ie ? 'resizestart' : 'resize', function( evt ) {","// domUtils.preventDefault(evt)","// });"," }"," me._bindshortcutKeys();"," me.isReady = 1;"," me.fireEvent('ready');"," options.onready && options.onready.call(me);"," if (!browser.ie) {"," domUtils.on(me.window, ['blur', 'focus'], function (e) {"," //chrome下会出现alt+tab切换时,导致选区位置不对"," if (e.type == 'blur') {"," me._bakRange = me.selection.getRange();"," try {"," me._bakNativeRange = me.selection.getNative().getRangeAt(0);"," me.selection.getNative().removeAllRanges();"," } catch (e) {"," me._bakNativeRange = null;"," }",""," } else {"," try {"," me._bakRange && me._bakRange.select();"," } catch (e) {"," }"," }"," });"," }"," //trace:1518 ff3.6body不够寛,会导致点击空白处无法获得焦点"," if (browser.gecko && browser.version <= 10902) {"," //修复ff3.6初始化进来,不能点击获得焦点"," me.body.contentEditable = false;"," setTimeout(function () {"," me.body.contentEditable = true;"," }, 100);"," setInterval(function () {"," me.body.style.height = me.iframe.offsetHeight - 20 + 'px'"," }, 100)"," }"," !options.isShow && me.setHide();"," options.readonly && me.setDisabled();"," },",""," /**"," * 从编辑器的容器节点向上查找form元素,若找到,就同步编辑内容到找到的form里,为提交数据做准备,主要用于是手动提交的情况"," * 后台取得数据的键值,使用你容器上的name属性,如果没有就使用参数里的textarea项"," * @method sync"," * @example"," * ```javascript"," * editor.sync();"," * form.sumbit(); //form变量已经指向了form元素"," * ```"," */",""," /**"," * 根据传入的formId,在页面上查找要同步数据的表单,若找到,就同步编辑内容到找到的form里,为提交数据做准备,主要用于是手动提交的情况"," * 后台取得数据的键值,使用你容器上的name属性,如果没有就使用参数里的textarea项"," * @method sync"," * @param { String } formID 指定一个要同步数据的form的id,编辑器的数据会同步到你指定form下"," */"," sync: function (formId) {"," var me = this,"," form = formId ? document.getElementById(formId) :"," domUtils.findParent(me.iframe.parentNode, function (node) {"," return node.tagName == 'FORM'"," }, true);"," form && setValue(form, me);"," },",""," /**"," * 设置编辑器高度"," * @method setHeight"," * @param { Number } number 设置的高度值,纯数值,不带单位"," * @example"," * ```javascript"," * editor.setHeight(number);"," * ```"," */"," setHeight: function (height, notSetHeight) {"," if (height !== parseInt(this.iframe.parentNode.style.height)) {"," this.iframe.parentNode.style.height = height + 'px';"," }"," !notSetHeight && (this.options.minFrameHeight = this.options.initialFrameHeight = height);",""," this.body.style.height = height + 'px';"," },",""," /**"," * 这个接口是为插件扩展提供的接口,主要是为新添加的插件,如果需要添加快捷键,所提供的接口"," * @method addshortcutkey"," * @param { KeyValueMap } keyset 命令和快捷键的键值对对象,多个按钮的快捷键用“+”分隔"," * @example"," * ```javascript"," * editor.addshortcutkey({"," * \"Bold\" : \"ctrl+66\",//^B"," * \"Italic\" : \"ctrl+73\", //^I"," * });"," * ```"," */"," /**"," * 这个接口是为插件扩展提供的接口,主要是为新添加的插件,如果需要添加快捷键,所提供的接口"," * @method addshortcutkey"," * @param { String } cmd 触发快捷键时,响应的命令"," * @param { String } keys 快捷键的字符串,多个按钮用“+”分隔"," * @example"," * ```javascript"," * editor.addshortcutkey(\"Underline\", \"ctrl+85\"); //^U"," * ```"," */"," addshortcutkey: function (cmd, keys) {"," var obj = {};"," if (keys) {"," obj[cmd] = keys"," } else {"," obj = cmd;"," }"," utils.extend(this.shortcutkeys, obj)"," },",""," /**"," * 对编辑器设置keydown事件监听,绑定快捷键和命令,当快捷键组合触发成功,会响应对应的命令"," * @method _bindshortcutKeys"," * @private"," */"," _bindshortcutKeys: function () {"," var me = this, shortcutkeys = this.shortcutkeys;"," me.addListener('keydown', function (type, e) {"," var keyCode = e.keyCode || e.which;"," for (var i in shortcutkeys) {"," var tmp = shortcutkeys[i].split(',');"," for (var t = 0, ti; ti = tmp[t++];) {"," ti = ti.split(':');"," var key = ti[0], param = ti[1];"," if (/^(ctrl)(\\+shift)?\\+(\\d+)$/.test(key.toLowerCase()) || /^(\\d+)$/.test(key)) {"," if (( (RegExp.$1 == 'ctrl' ? (e.ctrlKey || e.metaKey) : 0)"," && (RegExp.$2 != \"\" ? e[RegExp.$2.slice(1) + \"Key\"] : 1)"," && keyCode == RegExp.$3"," ) ||"," keyCode == RegExp.$1"," ) {"," if (me.queryCommandState(i, param) != -1)"," me.execCommand(i, param);"," domUtils.preventDefault(e);"," }"," }"," }",""," }"," });"," },",""," /**"," * 获取编辑器的内容"," * @method getContent"," * @warning 该方法获取到的是经过编辑器内置的过滤规则进行过滤后得到的内容"," * @return { String } 编辑器的内容字符串, 如果编辑器的内容为空,或者是空的标签内容(如:”<p><br/></p>“), 则返回空字符串"," * @example"," * ```javascript"," * var content = editor.getContent();"," * ```"," */",""," /**"," * 获取编辑器的内容。 可以通过参数定义编辑器内置的判空规则"," * @method getContent"," * @param { Function } fn 自定的判空规则, 要求该方法返回一个boolean类型的值,"," * 代表当前编辑器的内容是否空,"," * 如果返回true, 则该方法将直接返回空字符串;如果返回false,则编辑器将返回"," * 经过内置过滤规则处理后的内容。"," * @remind 该方法在处理包含有初始化内容的时候能起到很好的作用。"," * @warning 该方法获取到的是经过编辑器内置的过滤规则进行过滤后得到的内容"," * @return { String } 编辑器的内容字符串"," * @example"," * ```javascript"," * // editor 是一个编辑器的实例"," * var content = editor.getContent( function ( editor ) {"," * return editor.body.innerHTML === '欢迎使用UEditor';"," * } );"," * ```"," */"," getContent: function (cmd, fn, notSetCursor, ignoreBlank, formatter) {"," var me = this;"," if (cmd && utils.isFunction(cmd)) {"," fn = cmd;"," cmd = '';"," }"," if (fn ? !fn() : !this.hasContents()) {"," return '';"," }"," me.fireEvent('beforegetcontent');"," var root = UE.htmlparser(me.body.innerHTML, ignoreBlank);"," me.filterOutputRule(root);"," me.fireEvent('aftergetcontent', cmd);"," return root.toHtml(formatter);"," },",""," /**"," * 取得完整的html代码,可以直接显示成完整的html文档"," * @method getAllHtml"," * @return { String } 编辑器的内容html文档字符串"," * @eaxmple"," * ```javascript"," * editor.getAllHtml();"," * ```"," */"," getAllHtml: function () {"," var me = this,"," headHtml = [],"," html = '';"," me.fireEvent('getAllHtml', headHtml);"," if (browser.ie && browser.version > 8) {"," var headHtmlForIE9 = '';"," utils.each(me.document.styleSheets, function (si) {"," headHtmlForIE9 += ( si.href ? '<link rel=\"stylesheet\" type=\"text/css\" href=\"' + si.href + '\" />' : '<style>' + si.cssText + '</style>');"," });"," utils.each(me.document.getElementsByTagName('script'), function (si) {"," headHtmlForIE9 += si.outerHTML;"," });",""," }"," return '<html><head>' + (me.options.charset ? '<meta http-equiv=\"Content-Type\" content=\"text/html; charset=' + me.options.charset + '\"/>' : '')"," + (headHtmlForIE9 || me.document.getElementsByTagName('head')[0].innerHTML) + headHtml.join('\\n') + '</head>'"," + '<body ' + (ie && browser.version < 9 ? 'class=\"view\"' : '') + '>' + me.getContent(null, null, true) + '</body></html>';"," },",""," /**"," * 得到编辑器的纯文本内容,但会保留段落格式"," * @method getPlainTxt"," * @return { String } 编辑器带段落格式的纯文本内容字符串"," * @example"," * ```javascript"," * editor.getPlainTxt();"," * ```"," */"," getPlainTxt: function () {"," var reg = new RegExp(domUtils.fillChar, 'g'),"," html = this.body.innerHTML.replace(/[\\n\\r]/g, '');//ie要先去了\\n在处理"," html = html.replace(/<(p|div)[^>]*>(<br\\/?>|&nbsp;)<\\/\\1>/gi, '\\n')"," .replace(/<br\\/?>/gi, '\\n')"," .replace(/<[^>/]+>/g, '')"," .replace(/(\\n)?<\\/([^>]+)>/g, function (a, b, c) {"," return dtd.$block[c] ? '\\n' : b ? b : '';"," });"," //取出来的空格会有c2a0会变成乱码,处理这种情况\\u00a0"," return html.replace(reg, '').replace(/\\u00a0/g, ' ').replace(/&nbsp;/g, ' ');"," },",""," /**"," * 获取编辑器中的纯文本内容,没有段落格式"," * @method getContentTxt"," * @return { String } 编辑器不带段落格式的纯文本内容字符串"," * @example"," * ```javascript"," * editor.getContentTxt();"," * ```"," */"," getContentTxt: function () {"," var reg = new RegExp(domUtils.fillChar, 'g');"," //取出来的空格会有c2a0会变成乱码,处理这种情况\\u00a0"," return this.body[browser.ie ? 'innerText' : 'textContent'].replace(reg, '').replace(/\\u00a0/g, ' ');"," },",""," /**"," * 设置编辑器的内容,可修改编辑器当前的html内容"," * @method setContent"," * @warning 通过该方法插入的内容,是经过编辑器内置的过滤规则进行过滤后得到的内容"," * @warning 该方法会出发selectionchange事件"," * @param { String } 要插入的html内容"," * @example"," * ```javascript"," * editor.getContent('<p>test</p>');"," * ```"," */",""," /**"," * 设置编辑器的内容,可修改编辑器当前的html内容"," * @method setContent"," * @warning 通过该方法插入的内容,是经过编辑器内置的过滤规则进行过滤后得到的内容"," * @warning 该方法会出发selectionchange事件"," * @param { String } html 要插入的html内容"," * @param { Boolean } isAppendTo 若传入true,不清空原来的内容,在最后插入内容,否则,清空内容再插入"," * @example"," * ```javascript"," * //假设设置前的编辑器内容是 <p>old text</p>"," * editor.getContent('<p>new text</p>', true); //插入的结果是<p>old text</p><p>new text</p>"," * ```"," */",""," /**"," * 设置编辑器的内容,可修改编辑器当前的html内容"," * @method setContent"," * @warning 通过该方法插入的内容,是经过编辑器内置的过滤规则进行过滤后得到的内容"," * @param { String } html 要插入的html内容"," * @param { Boolean } isAppendTo 若传入true,不清空原来的内容,在最后插入内容,否则,清空内容再插入"," * @param { Boolean } notFireSelectionchange 若传入true,执行该函数过程不触发编辑器的selectionchange事件"," * @example"," * ```javascript"," * editor.getContent('<p>new text</p>', false, true);"," * ```"," */"," setContent: function (html, isAppendTo, notFireSelectionchange) {"," var me = this;",""," me.fireEvent('beforesetcontent', html);"," var root = UE.htmlparser(html);"," me.filterInputRule(root);"," html = root.toHtml();","",""," me.body.innerHTML = (isAppendTo ? me.body.innerHTML : '') + html;","",""," function isCdataDiv(node) {"," return node.tagName == 'DIV' && node.getAttribute('cdata_tag');"," }",""," //给文本或者inline节点套p标签"," if (me.options.enterTag == 'p') {",""," var child = this.body.firstChild, tmpNode;"," if (!child || child.nodeType == 1 &&"," (dtd.$cdata[child.tagName] || isCdataDiv(child) ||"," domUtils.isCustomeNode(child)"," )"," && child === this.body.lastChild) {"," this.body.innerHTML = '<p>' + (browser.ie ? '&nbsp;' : '<br/>') + '</p>' + this.body.innerHTML;",""," } else {"," var p = me.document.createElement('p');"," while (child) {"," while (child && (child.nodeType == 3 || child.nodeType == 1 && dtd.p[child.tagName] && !dtd.$cdata[child.tagName])) {"," tmpNode = child.nextSibling;"," p.appendChild(child);"," child = tmpNode;"," }"," if (p.firstChild) {"," if (!child) {"," me.body.appendChild(p);"," break;"," } else {"," child.parentNode.insertBefore(p, child);"," p = me.document.createElement('p');"," }"," }"," child = child.nextSibling;"," }"," }"," }"," me.fireEvent('aftersetcontent');"," me.fireEvent('contentchange');",""," !notFireSelectionchange && me._selectionChange();"," //清除保存的选区"," me._bakRange = me._bakIERange = me._bakNativeRange = null;"," //trace:1742 setContent后gecko能得到焦点问题"," var geckoSel;"," if (browser.gecko && (geckoSel = this.selection.getNative())) {"," geckoSel.removeAllRanges();"," }"," if (me.options.autoSyncData) {"," me.form && setValue(me.form, me);"," }"," },",""," /**"," * 让编辑器获得焦点,默认focus到编辑器头部"," * @method focus"," * @example"," * ```javascript"," * editor.focus()"," * ```"," */",""," /**"," * 让编辑器获得焦点,toEnd确定focus位置"," * @method focus"," * @param { Boolean } toEnd 默认focus到编辑器头部,toEnd为true时focus到内容尾部"," * @example"," * ```javascript"," * editor.focus(true)"," * ```"," */"," focus: function (toEnd) {"," try {"," var me = this,"," rng = me.selection.getRange();"," if (toEnd) {"," rng.setStartAtLast(me.body.lastChild).setCursor(false, true);"," } else {"," rng.select(true);"," }"," this.fireEvent('focus');"," } catch (e) {"," }"," },",""," /**"," * 初始化UE事件及部分事件代理"," * @method _initEvents"," * @private"," */"," _initEvents: function () {"," var me = this,"," doc = me.document,"," win = me.window;"," me._proxyDomEvent = utils.bind(me._proxyDomEvent, me);"," domUtils.on(doc, ['click', 'contextmenu', 'mousedown', 'keydown', 'keyup', 'keypress', 'mouseup', 'mouseover', 'mouseout', 'selectstart'], me._proxyDomEvent);"," domUtils.on(win, ['focus', 'blur'], me._proxyDomEvent);"," domUtils.on(doc, ['mouseup', 'keydown'], function (evt) {"," //特殊键不触发selectionchange"," if (evt.type == 'keydown' && (evt.ctrlKey || evt.metaKey || evt.shiftKey || evt.altKey)) {"," return;"," }"," if (evt.button == 2)return;"," me._selectionChange(250, evt);"," });","// //处理拖拽","// //ie ff不能从外边拖入","// //chrome只针对从外边拖入的内容过滤","// var innerDrag = 0, source = browser.ie ? me.body : me.document, dragoverHandler;","// domUtils.on(source, 'dragstart', function () {","// innerDrag = 1;","// });","// domUtils.on(source, browser.webkit ? 'dragover' : 'drop', function () {","// return browser.webkit ?","// function () {","// clearTimeout(dragoverHandler);","// dragoverHandler = setTimeout(function () {","// if (!innerDrag) {","// var sel = me.selection,","// range = sel.getRange();","// if (range) {","// var common = range.getCommonAncestor();","// if (common && me.serialize) {","// var f = me.serialize,","// node =","// f.filter(","// f.transformInput(","// f.parseHTML(","// f.word(common.innerHTML)","// )","// )","// );","// common.innerHTML = f.toHTML(node);","// }","// }","// }","// innerDrag = 0;","// }, 200);","// } :","// function (e) {","// if (!innerDrag) {","// e.preventDefault ? e.preventDefault() : (e.returnValue = false);","// }","// innerDrag = 0;","// }","// }());"," },",""," /**"," * 触发事件代理"," * @method _proxyDomEvent"," * @private"," * @return { * } fireEvent的返回值"," * @see UE.EventBase:fireEvent(String)"," */"," _proxyDomEvent: function (evt) {"," return this.fireEvent(evt.type.replace(/^on/, ''), evt);"," },"," /**"," * 变化选区"," * @method _selectionChange"," * @private"," */"," _selectionChange: function (delay, evt) {"," var me = this;"," //有光标才做selectionchange 为了解决未focus时点击source不能触发更改工具栏状态的问题(source命令notNeedUndo=1)","// if ( !me.selection.isFocus() ){","// return;","// }","",""," var hackForMouseUp = false;"," var mouseX, mouseY;"," if (browser.ie && browser.version < 9 && evt && evt.type == 'mouseup') {"," var range = this.selection.getRange();"," if (!range.collapsed) {"," hackForMouseUp = true;"," mouseX = evt.clientX;"," mouseY = evt.clientY;"," }"," }"," clearTimeout(_selectionChangeTimer);"," _selectionChangeTimer = setTimeout(function () {"," if (!me.selection.getNative()) {"," return;"," }"," //修复一个IE下的bug: 鼠标点击一段已选择的文本中间时,可能在mouseup后的一段时间内取到的range是在selection的type为None下的错误值."," //IE下如果用户是拖拽一段已选择文本,则不会触发mouseup事件,所以这里的特殊处理不会对其有影响"," var ieRange;"," if (hackForMouseUp && me.selection.getNative().type == 'None') {"," ieRange = me.document.body.createTextRange();"," try {"," ieRange.moveToPoint(mouseX, mouseY);"," } catch (ex) {"," ieRange = null;"," }"," }"," var bakGetIERange;"," if (ieRange) {"," bakGetIERange = me.selection.getIERange;"," me.selection.getIERange = function () {"," return ieRange;"," };"," }"," me.selection.cache();"," if (bakGetIERange) {"," me.selection.getIERange = bakGetIERange;"," }"," if (me.selection._cachedRange && me.selection._cachedStartElement) {"," me.fireEvent('beforeselectionchange');"," // 第二个参数causeByUi为true代表由用户交互造成的selectionchange."," me.fireEvent('selectionchange', !!evt);"," me.fireEvent('afterselectionchange');"," me.selection.clear();"," }"," }, delay || 50);"," },",""," /**"," * 执行编辑命令"," * @method _callCmdFn"," * @private"," * @param { String } fnName 函数名称"," * @param { * } args 传给命令函数的参数"," * @return { * } 返回命令函数运行的返回值"," */"," _callCmdFn: function (fnName, args) {"," var cmdName = args[0].toLowerCase(),"," cmd, cmdFn;"," cmd = this.commands[cmdName] || UE.commands[cmdName];"," cmdFn = cmd && cmd[fnName];"," //没有querycommandstate或者没有command的都默认返回0"," if ((!cmd || !cmdFn) && fnName == 'queryCommandState') {"," return 0;"," } else if (cmdFn) {"," return cmdFn.apply(this, args);"," }"," },",""," /**"," * 执行编辑命令cmdName,完成富文本编辑效果"," * @method execCommand"," * @return { * } 返回命令函数运行的返回值"," * @example"," * ```javascript"," * editor.execCommand(cmdName);"," * ```"," */"," execCommand: function (cmdName) {"," cmdName = cmdName.toLowerCase();"," var me = this,"," result,"," cmd = me.commands[cmdName] || UE.commands[cmdName];"," if (!cmd || !cmd.execCommand) {"," return null;"," }"," if (!cmd.notNeedUndo && !me.__hasEnterExecCommand) {"," me.__hasEnterExecCommand = true;"," if (me.queryCommandState.apply(me, arguments) != -1) {"," me.fireEvent('beforeexeccommand', cmdName);"," result = this._callCmdFn('execCommand', arguments);"," !me._ignoreContentChange && me.fireEvent('contentchange');"," me.fireEvent('afterexeccommand', cmdName);"," }"," me.__hasEnterExecCommand = false;"," } else {"," result = this._callCmdFn('execCommand', arguments);"," !me._ignoreContentChange && me.fireEvent('contentchange')"," }"," !me._ignoreContentChange && me._selectionChange();"," return result;"," },",""," /**"," * 根据传入的command命令,查选编辑器当前的选区,返回命令的状态"," * @method queryCommandState"," * @return { Number } number 返回放前命令的状态"," * 返回 -1 当前命令不可用"," * 返回 0 当前命令可用"," * 返回 1 当前命令已经执行过了"," * @example"," * ```javascript"," * editor.queryCommandState(cmdName) => (-1|0|1)"," * ```"," */"," queryCommandState: function (cmdName) {"," return this._callCmdFn('queryCommandState', arguments);"," },",""," /**"," * 根据传入的command命令,查选编辑器当前的选区,根据命令返回相关的值"," * @method queryCommandValue"," * @remind 只有部分插件有此方法"," * @return { * } 返回每个命令特定的当前状态值"," * @grammar editor.queryCommandValue(cmdName) => {*}"," */"," queryCommandValue: function (cmdName) {"," return this._callCmdFn('queryCommandValue', arguments);"," },",""," /**"," * 检查编辑区域中是否有内容"," * @method hasContents"," * @remind 默认有文本内容,或者有以下节点都不认为是空"," * table,ul,ol,dl,iframe,area,base,col,hr,img,embed,input,link,meta,param"," * @return { Boolean } 检查有内容返回true,否则返回false"," * @example"," * ```javascript"," * editor.hasContents()"," * ```"," */",""," /**"," * 检查编辑区域中是否有内容,若包含参数tags中的节点类型,直接返回true"," * @method hasContents"," * @param { Array } tags 传入数组判断时用到的节点类型"," * @return { Boolean } 若文档中包含tags数组里对应的tag,返回true,否则返回false"," * @example"," * ```javascript"," * editor.hasContents(['span']);"," * ```"," */"," hasContents: function (tags) {"," if (tags) {"," for (var i = 0, ci; ci = tags[i++];) {"," if (this.document.getElementsByTagName(ci).length > 0) {"," return true;"," }"," }"," }"," if (!domUtils.isEmptyBlock(this.body)) {"," return true"," }"," //随时添加,定义的特殊标签如果存在,不能认为是空"," tags = ['div'];"," for (i = 0; ci = tags[i++];) {"," var nodes = domUtils.getElementsByTagName(this.document, ci);"," for (var n = 0, cn; cn = nodes[n++];) {"," if (domUtils.isCustomeNode(cn)) {"," return true;"," }"," }"," }"," return false;"," },",""," /**"," * 重置编辑器,可用来做多个tab使用同一个编辑器实例"," * @method reset"," * @remind 此方法会清空编辑器内容,清空回退列表"," * @example"," * ```javascript"," * editor.reset()"," * ```"," */"," reset: function () {"," this.fireEvent('reset');"," },",""," /**"," * 设置当前编辑区域可以编辑"," * @method setEnabled"," * @example"," * ```javascript"," * editor.setEnabled()"," * ```"," */"," setEnabled: function () {"," var me = this, range;"," if (me.body.contentEditable == 'false') {"," me.body.contentEditable = true;"," range = me.selection.getRange();"," //有可能内容丢失了"," try {"," range.moveToBookmark(me.lastBk);"," delete me.lastBk"," } catch (e) {"," range.setStartAtFirst(me.body).collapse(true)"," }"," range.select(true);"," if (me.bkqueryCommandState) {"," me.queryCommandState = me.bkqueryCommandState;"," delete me.bkqueryCommandState;"," }"," me.fireEvent('selectionchange');"," }"," },",""," /**"," * 设置当前编辑区域可以编辑"," * @method enable"," * @return { * } 返回setEnabled方法的返回值"," * @example"," * ```javascript"," * editor.enable()"," * ```"," * @see UE.Editor:setEnabled()"," */"," enable: function () {"," return this.setEnabled();"," },",""," /** 设置当前编辑区域不可编辑"," * @method setDisabled"," */",""," /** 设置当前编辑区域不可编辑,except中的命令除外"," * @method setDisabled"," * @param { String } except 例外命令的字符串"," * @remind 即使设置了disable,此处配置的例外命令仍然可以执行"," * @example"," * ```javascript"," * editor.setDisabled('bold'); //禁用工具栏中除加粗之外的所有功能"," * ```"," */",""," /** 设置当前编辑区域不可编辑,except中的命令除外"," * @method setDisabled"," * @param { Array } except 字符串数组,数组中的命令仍然可以执行"," * @remind 即使设置了disable,此处配置的例外命令仍然可以执行"," * @example"," * ```javascript"," * editor.setDisabled(['bold','insertimage']); //禁用工具栏中除加粗和插入图片之外的所有功能"," * ```"," */"," setDisabled: function (except) {"," var me = this;"," except = except ? utils.isArray(except) ? except : [except] : [];"," if (me.body.contentEditable == 'true') {"," if (!me.lastBk) {"," me.lastBk = me.selection.getRange().createBookmark(true);"," }"," me.body.contentEditable = false;"," me.bkqueryCommandState = me.queryCommandState;"," me.queryCommandState = function (type) {"," if (utils.indexOf(except, type) != -1) {"," return me.bkqueryCommandState.apply(me, arguments);"," }"," return -1;"," };"," me.fireEvent('selectionchange');"," }"," },",""," /** 设置当前编辑区域不可编辑"," * @method disable"," * @see UE.Editor:setEnabled()"," */",""," /** 设置当前编辑区域不可编辑,except中的命令除外"," * @method disable"," * @param { String } except 例外命令的字符串"," * @remind 即使设置了disable,此处配置的例外命令仍然可以执行"," * @example"," * ```javascript"," * editor.disable('bold'); //禁用工具栏中除加粗之外的所有功能"," * ```"," * @see UE.Editor:setEnabled(String)"," */",""," /** 设置当前编辑区域不可编辑,except中的命令除外"," * @method disable"," * @param { Array } except 字符串数组,数组中的命令仍然可以执行"," * @remind 即使设置了disable,此处配置的例外命令仍然可以执行"," * @example"," * ```javascript"," * editor.disable(['bold','insertimage']); //禁用工具栏中除加粗和插入图片之外的所有功能"," * ```"," * @see UE.Editor:setEnabled(Array)"," */"," disable: function (except) {"," return this.setDisabled(except);"," },",""," /**"," * 设置默认内容"," * @method _setDefaultContent"," * @private"," * @param { String } cont 要存入的内容"," */"," _setDefaultContent: function () {"," function clear() {"," var me = this;"," if (me.document.getElementById('initContent')) {"," me.body.innerHTML = '<p>' + (ie ? '' : '<br/>') + '</p>';"," me.removeListener('firstBeforeExecCommand focus', clear);"," setTimeout(function () {"," me.focus();"," me._selectionChange();"," }, 0)"," }"," }",""," return function (cont) {"," var me = this;"," me.body.innerHTML = '<p id=\"initContent\">' + cont + '</p>';",""," me.addListener('firstBeforeExecCommand focus', clear);"," }"," }(),",""," /**"," * 显示编辑器,show方法的兼容版本"," * @method setShow"," * @private"," */"," setShow: function () {"," var me = this, range = me.selection.getRange();"," if (me.container.style.display == 'none') {"," //有可能内容丢失了"," try {"," range.moveToBookmark(me.lastBk);"," delete me.lastBk"," } catch (e) {"," range.setStartAtFirst(me.body).collapse(true)"," }"," //ie下focus实效,所以做了个延迟"," setTimeout(function () {"," range.select(true);"," }, 100);"," me.container.style.display = '';"," }"," },",""," /**"," * 显示编辑器"," * @method show"," * @example"," * ```javascript"," * editor.show()"," * ```"," * @see UE.Editor:setShow(String)"," */"," show: function () {"," return this.setShow();"," },",""," /**"," * 隐藏编辑器,hide方法的兼容版本"," * @method setHide"," * @private"," */"," setHide: function () {"," var me = this;"," if (!me.lastBk) {"," me.lastBk = me.selection.getRange().createBookmark(true);"," }"," me.container.style.display = 'none'"," },",""," /**"," * 隐藏编辑器"," * @method hide"," * @example"," * ```javascript"," * editor.hide()"," * ```"," * @see UE.Editor:setHide()"," */"," hide: function () {"," return this.setHide();"," },",""," /**"," * 根据指定的路径,获取对应的语言资源"," * @method getLang"," * @param { String } path 路径根据的是lang目录下的语言文件的路径结构"," * @return { KeyValueMap | String } 根据路径返回语言资源的Json格式对象或者语言字符串"," * @example"," * ```javascript"," * editor.getLang('contextMenu.delete'); //如果当前是中文,那返回是的是'删除'"," * ```"," */"," getLang: function (path) {"," var lang = UE.I18N[this.options.lang];"," if (!lang) {"," throw Error(\"not import language file\");"," }"," path = (path || \"\").split(\".\");"," for (var i = 0, ci; ci = path[i++];) {"," lang = lang[ci];"," if (!lang)break;"," }"," return lang;"," },",""," /**"," * 计算编辑器当前html内容的长度"," * @method getContentLength"," * @return { Number } 返回计算的长度"," * @example"," * ```javascript"," * editor.getContentLength()"," * ```"," */",""," /**"," * 计算编辑器当前存文本内容的长度"," * @method getContentLength"," * @param { Boolean } ingoneHtml 传入true时,只按照纯文本来计算"," * @return { Number } 返回计算的长度,内容中有hr/img/iframe标签,长度加1"," * @example"," * ```javascript"," * editor.getContentLength(true)"," * ```"," */",""," /**"," * 计算编辑器当前内容的长度"," * @method getContentLength"," * @param { Boolean } ingoneHtml 传入true时,只按照纯文本来计算"," * @param { Array } tagNames 忽略html代码时,遇到数组里的标签,长度加1"," * @return { Number } 返回计算的长度,内容中有hr/img/iframe标签或者参数tagNames中的标签,长度加1"," * @remind 当ingoneHtml为false,第二个参数不作用"," * @example"," * ```javascript"," * editor.getContentLength(true, ['em','strong'])"," * ```"," */"," getContentLength: function (ingoneHtml, tagNames) {"," var count = this.getContent(false, false, true).length;"," if (ingoneHtml) {"," tagNames = (tagNames || []).concat([ 'hr', 'img', 'iframe']);"," count = this.getContentTxt().replace(/[\\t\\r\\n]+/g, '').length;"," for (var i = 0, ci; ci = tagNames[i++];) {"," count += this.document.getElementsByTagName(ci).length;"," }"," }"," return count;"," },",""," /**"," * 添加输入过滤规则"," * @method addInputRule"," * @param { Function } rule 要添加的过滤规则"," * @example"," * ```javascript"," * editor.addInputRule(function(root){"," * $.each(root.getNodesByTagName('div'),function(i,node){"," * node.tagName=\"p\";"," * });"," * });"," * ```"," */"," addInputRule: function (rule) {"," this.inputRules.push(rule);"," },",""," /**"," * 根据输入过滤规则,过滤编辑器内容"," * @method filterInputRule"," * @param { UE.uNode } root 要过滤的uNode节点"," * @remind 执行editor.setContent方法和执行'inserthtml'命令后,会运行该过滤函数"," * @example"," * ```javascript"," * editor.filterInputRule(editor.body);"," * ```"," */"," filterInputRule: function (root) {"," for (var i = 0, ci; ci = this.inputRules[i++];) {"," ci.call(this, root)"," }"," },",""," /**"," * 添加输出过滤规则"," * @method addOutputRule"," * @param { Function } rule 要添加的过滤规则"," * @example"," * ```javascript"," * editor.addOutputRule(function(root){"," * $.each(root.getNodesByTagName('p'),function(i,node){"," * node.tagName=\"div\";"," * });"," * });"," * ```"," */"," addOutputRule: function (rule) {"," this.outputRules.push(rule)"," },",""," /**"," * 根据输出过滤规则,过滤编辑器内容"," * @method filterOutputRule"," * @remind 执行editor.getContent方法的时候,会先运行该过滤函数"," * @param { UE.uNode } root 要过滤的uNode节点"," * @example"," * ```javascript"," * editor.filterOutputRule(editor.body);"," * ```"," */"," filterOutputRule: function (root) {"," for (var i = 0, ci; ci = this.outputRules[i++];) {"," ci.call(this, root)"," }"," }"," };"," utils.inherits(Editor, EventBase);","})();"]; +_$jscoverage['core/Editor.js'][22]++; +(function () { + _$jscoverage['core/Editor.js'][23]++; + var uid = 0, _selectionChangeTimer; + _$jscoverage['core/Editor.js'][32]++; + function setValue(form, editor) { + _$jscoverage['core/Editor.js'][33]++; + var textarea; + _$jscoverage['core/Editor.js'][34]++; + if (editor.textarea) { + _$jscoverage['core/Editor.js'][35]++; + if (utils.isString(editor.textarea)) { + _$jscoverage['core/Editor.js'][36]++; + for (var i = 0, ti, tis = domUtils.getElementsByTagName(form, "textarea"); (ti = tis[(i++)]);) { + _$jscoverage['core/Editor.js'][37]++; + if ((ti.id == ("ueditor_textarea_" + editor.options.textarea))) { + _$jscoverage['core/Editor.js'][38]++; + textarea = ti; + _$jscoverage['core/Editor.js'][39]++; + break; + } +} + } + else { + _$jscoverage['core/Editor.js'][43]++; + textarea = editor.textarea; + } + } + _$jscoverage['core/Editor.js'][46]++; + if ((! textarea)) { + _$jscoverage['core/Editor.js'][47]++; + form.appendChild((textarea = domUtils.createElement(document, "textarea", {"name": editor.options.textarea, "id": ("ueditor_textarea_" + editor.options.textarea), "style": "display:none"}))); + _$jscoverage['core/Editor.js'][53]++; + editor.textarea = textarea; + } + _$jscoverage['core/Editor.js'][55]++; + textarea.value = (editor.hasContents()? (editor.options.allHtmlEnabled? editor.getAllHtml(): editor.getContent(null, null, true)): ""); +} + _$jscoverage['core/Editor.js'][66]++; + function loadPlugins(me) { + _$jscoverage['core/Editor.js'][68]++; + for (var pi in UE.plugins) { + _$jscoverage['core/Editor.js'][69]++; + UE.plugins[pi].call(me); +} + _$jscoverage['core/Editor.js'][71]++; + me.langIsReady = true; + _$jscoverage['core/Editor.js'][73]++; + me.fireEvent("langReady"); +} + _$jscoverage['core/Editor.js'][82]++; + function checkCurLang(I18N) { + _$jscoverage['core/Editor.js'][83]++; + for (var lang in I18N) { + _$jscoverage['core/Editor.js'][84]++; + return lang; +} +} + _$jscoverage['core/Editor.js'][135]++; + var Editor = (UE.Editor = (function (options) { + _$jscoverage['core/Editor.js'][136]++; + var me = this; + _$jscoverage['core/Editor.js'][137]++; + me.uid = (uid++); + _$jscoverage['core/Editor.js'][138]++; + EventBase.call(me); + _$jscoverage['core/Editor.js'][139]++; + me.commands = {}; + _$jscoverage['core/Editor.js'][140]++; + me.options = utils.extend(utils.clone((options || {})), UEDITOR_CONFIG, true); + _$jscoverage['core/Editor.js'][141]++; + me.shortcutkeys = {}; + _$jscoverage['core/Editor.js'][142]++; + me.inputRules = []; + _$jscoverage['core/Editor.js'][143]++; + me.outputRules = []; + _$jscoverage['core/Editor.js'][145]++; + me.setOpt({isShow: true, initialContent: "", initialStyle: "", autoClearinitialContent: false, iframeCssUrl: (me.options.UEDITOR_HOME_URL + "themes/iframe.css"), textarea: "editorValue", focus: false, focusInEnd: true, autoClearEmptyNode: true, fullscreen: false, readonly: false, zIndex: 999, imagePopup: true, enterTag: "p", customDomain: false, lang: "zh-cn", langPath: (me.options.UEDITOR_HOME_URL + "lang/"), theme: "default", themePath: (me.options.UEDITOR_HOME_URL + "themes/"), allHtmlEnabled: false, scaleEnabled: false, tableNativeEditInFF: false, autoSyncData: true}); + _$jscoverage['core/Editor.js'][171]++; + if ((! utils.isEmptyObject(UE.I18N))) { + _$jscoverage['core/Editor.js'][173]++; + me.options.lang = checkCurLang(UE.I18N); + _$jscoverage['core/Editor.js'][174]++; + loadPlugins(me); + } + else { + _$jscoverage['core/Editor.js'][176]++; + utils.loadFile(document, {src: (me.options.langPath + me.options.lang + "/" + me.options.lang + ".js"), tag: "script", type: "text/javascript", defer: "defer"}, (function () { + _$jscoverage['core/Editor.js'][182]++; + loadPlugins(me); +})); + } + _$jscoverage['core/Editor.js'][186]++; + UE.instants[("ueditorInstant" + me.uid)] = me; +})); + _$jscoverage['core/Editor.js'][188]++; + Editor.prototype = {ready: (function (fn) { + _$jscoverage['core/Editor.js'][205]++; + var me = this; + _$jscoverage['core/Editor.js'][206]++; + if (fn) { + _$jscoverage['core/Editor.js'][207]++; + (me.isReady? fn.apply(me): me.addListener("ready", fn)); + } +}), setOpt: (function (key, val) { + _$jscoverage['core/Editor.js'][238]++; + var obj = {}; + _$jscoverage['core/Editor.js'][239]++; + if (utils.isString(key)) { + _$jscoverage['core/Editor.js'][240]++; + obj[key] = val; + } + else { + _$jscoverage['core/Editor.js'][242]++; + obj = key; + } + _$jscoverage['core/Editor.js'][244]++; + utils.extend(this.options, obj, true); +}), destroy: (function () { + _$jscoverage['core/Editor.js'][258]++; + var me = this; + _$jscoverage['core/Editor.js'][259]++; + me.fireEvent("destroy"); + _$jscoverage['core/Editor.js'][260]++; + var container = me.container.parentNode; + _$jscoverage['core/Editor.js'][261]++; + var textarea = me.textarea; + _$jscoverage['core/Editor.js'][262]++; + if ((! textarea)) { + _$jscoverage['core/Editor.js'][263]++; + textarea = document.createElement("textarea"); + _$jscoverage['core/Editor.js'][264]++; + container.parentNode.insertBefore(textarea, container); + } + else { + _$jscoverage['core/Editor.js'][266]++; + textarea.style.display = ""; + } + _$jscoverage['core/Editor.js'][269]++; + textarea.style.width = (me.iframe.offsetWidth + "px"); + _$jscoverage['core/Editor.js'][270]++; + textarea.style.height = (me.iframe.offsetHeight + "px"); + _$jscoverage['core/Editor.js'][271]++; + textarea.value = me.getContent(); + _$jscoverage['core/Editor.js'][272]++; + textarea.id = me.key; + _$jscoverage['core/Editor.js'][273]++; + container.innerHTML = ""; + _$jscoverage['core/Editor.js'][274]++; + domUtils.remove(container); + _$jscoverage['core/Editor.js'][275]++; + var key = me.key; + _$jscoverage['core/Editor.js'][277]++; + for (var p in me) { + _$jscoverage['core/Editor.js'][278]++; + if (me.hasOwnProperty(p)) { + _$jscoverage['core/Editor.js'][279]++; + (delete this[p]); + } +} + _$jscoverage['core/Editor.js'][282]++; + UE.delEditor(key); +}), render: (function (container) { + _$jscoverage['core/Editor.js'][299]++; + var me = this, options = me.options, getStyleValue = (function (attr) { + _$jscoverage['core/Editor.js'][302]++; + return parseInt(domUtils.getComputedStyle(container, attr)); +}); + _$jscoverage['core/Editor.js'][304]++; + if (utils.isString(container)) { + _$jscoverage['core/Editor.js'][305]++; + container = document.getElementById(container); + } + _$jscoverage['core/Editor.js'][307]++; + if (container) { + _$jscoverage['core/Editor.js'][308]++; + if (options.initialFrameWidth) { + _$jscoverage['core/Editor.js'][309]++; + options.minFrameWidth = options.initialFrameWidth; + } + else { + _$jscoverage['core/Editor.js'][311]++; + options.minFrameWidth = (options.initialFrameWidth = container.offsetWidth); + } + _$jscoverage['core/Editor.js'][313]++; + if (options.initialFrameHeight) { + _$jscoverage['core/Editor.js'][314]++; + options.minFrameHeight = options.initialFrameHeight; + } + else { + _$jscoverage['core/Editor.js'][316]++; + options.initialFrameHeight = (options.minFrameHeight = container.offsetHeight); + } + _$jscoverage['core/Editor.js'][319]++; + container.style.width = (/%$/.test(options.initialFrameWidth)? "100%": ((options.initialFrameWidth - getStyleValue("padding-left") - getStyleValue("padding-right")) + "px")); + _$jscoverage['core/Editor.js'][321]++; + container.style.height = (/%$/.test(options.initialFrameHeight)? "100%": ((options.initialFrameHeight - getStyleValue("padding-top") - getStyleValue("padding-bottom")) + "px")); + _$jscoverage['core/Editor.js'][324]++; + container.style.zIndex = options.zIndex; + _$jscoverage['core/Editor.js'][326]++; + var html = (((ie && (browser.version < 9))? "": "") + "" + "" + (options.iframeCssUrl? (""): "") + (options.initialStyle? (""): "") + "" + ""); + _$jscoverage['core/Editor.js'][342]++; + container.appendChild(domUtils.createElement(document, "iframe", {id: ("ueditor_" + me.uid), width: "100%", height: "100%", frameborder: "0", src: ("javascript:void(function(){document.open();" + ((options.customDomain && (document.domain != location.hostname))? ("document.domain=\"" + document.domain + "\";"): "") + "document.write(\"" + html + "\");document.close();}())")})); + _$jscoverage['core/Editor.js'][350]++; + container.style.overflow = "hidden"; + _$jscoverage['core/Editor.js'][352]++; + setTimeout((function () { + _$jscoverage['core/Editor.js'][353]++; + if (/%$/.test(options.initialFrameWidth)) { + _$jscoverage['core/Editor.js'][354]++; + options.minFrameWidth = (options.initialFrameWidth = container.offsetWidth); + _$jscoverage['core/Editor.js'][355]++; + container.style.width = (options.initialFrameWidth + "px"); + } + _$jscoverage['core/Editor.js'][357]++; + if (/%$/.test(options.initialFrameHeight)) { + _$jscoverage['core/Editor.js'][358]++; + options.minFrameHeight = (options.initialFrameHeight = container.offsetHeight); + _$jscoverage['core/Editor.js'][359]++; + container.style.height = (options.initialFrameHeight + "px"); + } +})); + } +}), _setup: (function (doc) { + _$jscoverage['core/Editor.js'][373]++; + var me = this, options = me.options; + _$jscoverage['core/Editor.js'][375]++; + if (ie) { + _$jscoverage['core/Editor.js'][376]++; + doc.body.disabled = true; + _$jscoverage['core/Editor.js'][377]++; + doc.body.contentEditable = true; + _$jscoverage['core/Editor.js'][378]++; + doc.body.disabled = false; + } + else { + _$jscoverage['core/Editor.js'][380]++; + doc.body.contentEditable = true; + } + _$jscoverage['core/Editor.js'][382]++; + doc.body.spellcheck = false; + _$jscoverage['core/Editor.js'][383]++; + me.document = doc; + _$jscoverage['core/Editor.js'][384]++; + me.window = (doc.defaultView || doc.parentWindow); + _$jscoverage['core/Editor.js'][385]++; + me.iframe = me.window.frameElement; + _$jscoverage['core/Editor.js'][386]++; + me.body = doc.body; + _$jscoverage['core/Editor.js'][388]++; + me.selection = new (dom.Selection)(doc); + _$jscoverage['core/Editor.js'][390]++; + var geckoSel; + _$jscoverage['core/Editor.js'][391]++; + if ((browser.gecko && (geckoSel = this.selection.getNative()))) { + _$jscoverage['core/Editor.js'][392]++; + geckoSel.removeAllRanges(); + } + _$jscoverage['core/Editor.js'][394]++; + this._initEvents(); + _$jscoverage['core/Editor.js'][396]++; + for (var form = this.iframe.parentNode; (! domUtils.isBody(form)); (form = form.parentNode)) { + _$jscoverage['core/Editor.js'][397]++; + if ((form.tagName == "FORM")) { + _$jscoverage['core/Editor.js'][398]++; + me.form = form; + _$jscoverage['core/Editor.js'][399]++; + if (me.options.autoSyncData) { + _$jscoverage['core/Editor.js'][400]++; + domUtils.on(me.window, "blur", (function () { + _$jscoverage['core/Editor.js'][401]++; + setValue(form, me); +})); + } + else { + _$jscoverage['core/Editor.js'][404]++; + domUtils.on(form, "submit", (function () { + _$jscoverage['core/Editor.js'][405]++; + setValue(this, me); +})); + } + _$jscoverage['core/Editor.js'][408]++; + break; + } +} + _$jscoverage['core/Editor.js'][411]++; + if (options.initialContent) { + _$jscoverage['core/Editor.js'][412]++; + if (options.autoClearinitialContent) { + _$jscoverage['core/Editor.js'][413]++; + var oldExecCommand = me.execCommand; + _$jscoverage['core/Editor.js'][414]++; + me.execCommand = (function () { + _$jscoverage['core/Editor.js'][415]++; + me.fireEvent("firstBeforeExecCommand"); + _$jscoverage['core/Editor.js'][416]++; + return oldExecCommand.apply(me, arguments); +}); + _$jscoverage['core/Editor.js'][418]++; + this._setDefaultContent(options.initialContent); + } + else { + _$jscoverage['core/Editor.js'][420]++; + this.setContent(options.initialContent, false, true); + } + } + _$jscoverage['core/Editor.js'][425]++; + if (domUtils.isEmptyNode(me.body)) { + _$jscoverage['core/Editor.js'][426]++; + me.body.innerHTML = ("

    " + (browser.ie? "": "
    ") + "

    "); + } + _$jscoverage['core/Editor.js'][429]++; + if (options.focus) { + _$jscoverage['core/Editor.js'][430]++; + setTimeout((function () { + _$jscoverage['core/Editor.js'][431]++; + me.focus(me.options.focusInEnd); + _$jscoverage['core/Editor.js'][433]++; + ((! me.options.autoClearinitialContent) && me._selectionChange()); +}), 0); + } + _$jscoverage['core/Editor.js'][436]++; + if ((! me.container)) { + _$jscoverage['core/Editor.js'][437]++; + me.container = this.iframe.parentNode; + } + _$jscoverage['core/Editor.js'][439]++; + if ((options.fullscreen && me.ui)) { + _$jscoverage['core/Editor.js'][440]++; + me.ui.setFullScreen(true); + } + _$jscoverage['core/Editor.js'][443]++; + try { + _$jscoverage['core/Editor.js'][444]++; + me.document.execCommand("2D-position", false, false); + } + catch (e) { + } + _$jscoverage['core/Editor.js'][447]++; + try { + _$jscoverage['core/Editor.js'][448]++; + me.document.execCommand("enableInlineTableEditing", false, false); + } + catch (e) { + } + _$jscoverage['core/Editor.js'][451]++; + try { + _$jscoverage['core/Editor.js'][452]++; + me.document.execCommand("enableObjectResizing", false, false); + } + catch (e) { + } + _$jscoverage['core/Editor.js'][458]++; + me._bindshortcutKeys(); + _$jscoverage['core/Editor.js'][459]++; + me.isReady = 1; + _$jscoverage['core/Editor.js'][460]++; + me.fireEvent("ready"); + _$jscoverage['core/Editor.js'][461]++; + (options.onready && options.onready.call(me)); + _$jscoverage['core/Editor.js'][462]++; + if ((! browser.ie)) { + _$jscoverage['core/Editor.js'][463]++; + domUtils.on(me.window, ["blur", "focus"], (function (e) { + _$jscoverage['core/Editor.js'][465]++; + if ((e.type == "blur")) { + _$jscoverage['core/Editor.js'][466]++; + me._bakRange = me.selection.getRange(); + _$jscoverage['core/Editor.js'][467]++; + try { + _$jscoverage['core/Editor.js'][468]++; + me._bakNativeRange = me.selection.getNative().getRangeAt(0); + _$jscoverage['core/Editor.js'][469]++; + me.selection.getNative().removeAllRanges(); + } + catch (e) { + _$jscoverage['core/Editor.js'][471]++; + me._bakNativeRange = null; + } + } + else { + _$jscoverage['core/Editor.js'][475]++; + try { + _$jscoverage['core/Editor.js'][476]++; + (me._bakRange && me._bakRange.select()); + } + catch (e) { + } + } +})); + } + _$jscoverage['core/Editor.js'][483]++; + if ((browser.gecko && (browser.version <= 10902))) { + _$jscoverage['core/Editor.js'][485]++; + me.body.contentEditable = false; + _$jscoverage['core/Editor.js'][486]++; + setTimeout((function () { + _$jscoverage['core/Editor.js'][487]++; + me.body.contentEditable = true; +}), 100); + _$jscoverage['core/Editor.js'][489]++; + setInterval((function () { + _$jscoverage['core/Editor.js'][490]++; + me.body.style.height = ((me.iframe.offsetHeight - 20) + "px"); +}), 100); + } + _$jscoverage['core/Editor.js'][493]++; + ((! options.isShow) && me.setHide()); + _$jscoverage['core/Editor.js'][494]++; + (options.readonly && me.setDisabled()); +}), sync: (function (formId) { + _$jscoverage['core/Editor.js'][515]++; + var me = this, form = (formId? document.getElementById(formId): domUtils.findParent(me.iframe.parentNode, (function (node) { + _$jscoverage['core/Editor.js'][518]++; + return (node.tagName == "FORM"); +}), true)); + _$jscoverage['core/Editor.js'][520]++; + (form && setValue(form, me)); +}), setHeight: (function (height, notSetHeight) { + _$jscoverage['core/Editor.js'][533]++; + if ((height !== parseInt(this.iframe.parentNode.style.height))) { + _$jscoverage['core/Editor.js'][534]++; + this.iframe.parentNode.style.height = (height + "px"); + } + _$jscoverage['core/Editor.js'][536]++; + ((! notSetHeight) && (this.options.minFrameHeight = (this.options.initialFrameHeight = height))); + _$jscoverage['core/Editor.js'][538]++; + this.body.style.height = (height + "px"); +}), addshortcutkey: (function (cmd, keys) { + _$jscoverage['core/Editor.js'][564]++; + var obj = {}; + _$jscoverage['core/Editor.js'][565]++; + if (keys) { + _$jscoverage['core/Editor.js'][566]++; + obj[cmd] = keys; + } + else { + _$jscoverage['core/Editor.js'][568]++; + obj = cmd; + } + _$jscoverage['core/Editor.js'][570]++; + utils.extend(this.shortcutkeys, obj); +}), _bindshortcutKeys: (function () { + _$jscoverage['core/Editor.js'][579]++; + var me = this, shortcutkeys = this.shortcutkeys; + _$jscoverage['core/Editor.js'][580]++; + me.addListener("keydown", (function (type, e) { + _$jscoverage['core/Editor.js'][581]++; + var keyCode = (e.keyCode || e.which); + _$jscoverage['core/Editor.js'][582]++; + for (var i in shortcutkeys) { + _$jscoverage['core/Editor.js'][583]++; + var tmp = shortcutkeys[i].split(","); + _$jscoverage['core/Editor.js'][584]++; + for (var t = 0, ti; (ti = tmp[(t++)]);) { + _$jscoverage['core/Editor.js'][585]++; + ti = ti.split(":"); + _$jscoverage['core/Editor.js'][586]++; + var key = ti[0], param = ti[1]; + _$jscoverage['core/Editor.js'][587]++; + if ((/^(ctrl)(\+shift)?\+(\d+)$/.test(key.toLowerCase()) || /^(\d+)$/.test(key))) { + _$jscoverage['core/Editor.js'][588]++; + if (((((RegExp.$1 == "ctrl")? (e.ctrlKey || e.metaKey): 0) && ((RegExp.$2 != "")? e[(RegExp.$2.slice(1) + "Key")]: 1) && (keyCode == RegExp.$3)) || (keyCode == RegExp.$1))) { + _$jscoverage['core/Editor.js'][594]++; + if ((me.queryCommandState(i, param) != -1)) { + _$jscoverage['core/Editor.js'][595]++; + me.execCommand(i, param); + } + _$jscoverage['core/Editor.js'][596]++; + domUtils.preventDefault(e); + } + } +} +} +})); +}), getContent: (function (cmd, fn, notSetCursor, ignoreBlank, formatter) { + _$jscoverage['core/Editor.js'][635]++; + var me = this; + _$jscoverage['core/Editor.js'][636]++; + if ((cmd && utils.isFunction(cmd))) { + _$jscoverage['core/Editor.js'][637]++; + fn = cmd; + _$jscoverage['core/Editor.js'][638]++; + cmd = ""; + } + _$jscoverage['core/Editor.js'][640]++; + if ((fn? (! fn()): (! this.hasContents()))) { + _$jscoverage['core/Editor.js'][641]++; + return ""; + } + _$jscoverage['core/Editor.js'][643]++; + me.fireEvent("beforegetcontent"); + _$jscoverage['core/Editor.js'][644]++; + var root = UE.htmlparser(me.body.innerHTML, ignoreBlank); + _$jscoverage['core/Editor.js'][645]++; + me.filterOutputRule(root); + _$jscoverage['core/Editor.js'][646]++; + me.fireEvent("aftergetcontent", cmd); + _$jscoverage['core/Editor.js'][647]++; + return root.toHtml(formatter); +}), getAllHtml: (function () { + _$jscoverage['core/Editor.js'][660]++; + var me = this, headHtml = [], html = ""; + _$jscoverage['core/Editor.js'][663]++; + me.fireEvent("getAllHtml", headHtml); + _$jscoverage['core/Editor.js'][664]++; + if ((browser.ie && (browser.version > 8))) { + _$jscoverage['core/Editor.js'][665]++; + var headHtmlForIE9 = ""; + _$jscoverage['core/Editor.js'][666]++; + utils.each(me.document.styleSheets, (function (si) { + _$jscoverage['core/Editor.js'][667]++; + headHtmlForIE9 += (si.href? (""): ("")); +})); + _$jscoverage['core/Editor.js'][669]++; + utils.each(me.document.getElementsByTagName("script"), (function (si) { + _$jscoverage['core/Editor.js'][670]++; + headHtmlForIE9 += si.outerHTML; +})); + } + _$jscoverage['core/Editor.js'][674]++; + return ("" + (me.options.charset? (""): "") + (headHtmlForIE9 || me.document.getElementsByTagName("head")[0].innerHTML) + headHtml.join("\n") + "" + "" + me.getContent(null, null, true) + ""); +}), getPlainTxt: (function () { + _$jscoverage['core/Editor.js'][689]++; + var reg = new RegExp(domUtils.fillChar, "g"), html = this.body.innerHTML.replace(/[\n\r]/g, ""); + _$jscoverage['core/Editor.js'][691]++; + html = html.replace(/<(p|div)[^>]*>(| )<\/\1>/gi, "\n").replace(//gi, "\n").replace(/<[^>/]+>/g, "").replace(/(\n)?<\/([^>]+)>/g, (function (a, b, c) { + _$jscoverage['core/Editor.js'][695]++; + return (dtd.$block[c]? "\n": (b? b: "")); +})); + _$jscoverage['core/Editor.js'][698]++; + return html.replace(reg, "").replace(/\u00a0/g, " ").replace(/ /g, " "); +}), getContentTxt: (function () { + _$jscoverage['core/Editor.js'][711]++; + var reg = new RegExp(domUtils.fillChar, "g"); + _$jscoverage['core/Editor.js'][713]++; + return this.body[(browser.ie? "innerText": "textContent")].replace(reg, "").replace(/\u00a0/g, " "); +}), setContent: (function (html, isAppendTo, notFireSelectionchange) { + _$jscoverage['core/Editor.js'][755]++; + var me = this; + _$jscoverage['core/Editor.js'][757]++; + me.fireEvent("beforesetcontent", html); + _$jscoverage['core/Editor.js'][758]++; + var root = UE.htmlparser(html); + _$jscoverage['core/Editor.js'][759]++; + me.filterInputRule(root); + _$jscoverage['core/Editor.js'][760]++; + html = root.toHtml(); + _$jscoverage['core/Editor.js'][763]++; + me.body.innerHTML = ((isAppendTo? me.body.innerHTML: "") + html); + _$jscoverage['core/Editor.js'][766]++; + function isCdataDiv(node) { + _$jscoverage['core/Editor.js'][767]++; + return ((node.tagName == "DIV") && node.getAttribute("cdata_tag")); +} + _$jscoverage['core/Editor.js'][771]++; + if ((me.options.enterTag == "p")) { + _$jscoverage['core/Editor.js'][773]++; + var child = this.body.firstChild, tmpNode; + _$jscoverage['core/Editor.js'][774]++; + if (((! child) || ((child.nodeType == 1) && (dtd.$cdata[child.tagName] || isCdataDiv(child) || domUtils.isCustomeNode(child)) && (child === this.body.lastChild)))) { + _$jscoverage['core/Editor.js'][779]++; + this.body.innerHTML = ("

    " + (browser.ie? " ": "
    ") + "

    " + this.body.innerHTML); + } + else { + _$jscoverage['core/Editor.js'][782]++; + var p = me.document.createElement("p"); + _$jscoverage['core/Editor.js'][783]++; + while (child) { + _$jscoverage['core/Editor.js'][784]++; + while ((child && ((child.nodeType == 3) || ((child.nodeType == 1) && dtd.p[child.tagName] && (! dtd.$cdata[child.tagName]))))) { + _$jscoverage['core/Editor.js'][785]++; + tmpNode = child.nextSibling; + _$jscoverage['core/Editor.js'][786]++; + p.appendChild(child); + _$jscoverage['core/Editor.js'][787]++; + child = tmpNode; +} + _$jscoverage['core/Editor.js'][789]++; + if (p.firstChild) { + _$jscoverage['core/Editor.js'][790]++; + if ((! child)) { + _$jscoverage['core/Editor.js'][791]++; + me.body.appendChild(p); + _$jscoverage['core/Editor.js'][792]++; + break; + } + else { + _$jscoverage['core/Editor.js'][794]++; + child.parentNode.insertBefore(p, child); + _$jscoverage['core/Editor.js'][795]++; + p = me.document.createElement("p"); + } + } + _$jscoverage['core/Editor.js'][798]++; + child = child.nextSibling; +} + } + } + _$jscoverage['core/Editor.js'][802]++; + me.fireEvent("aftersetcontent"); + _$jscoverage['core/Editor.js'][803]++; + me.fireEvent("contentchange"); + _$jscoverage['core/Editor.js'][805]++; + ((! notFireSelectionchange) && me._selectionChange()); + _$jscoverage['core/Editor.js'][807]++; + me._bakRange = (me._bakIERange = (me._bakNativeRange = null)); + _$jscoverage['core/Editor.js'][809]++; + var geckoSel; + _$jscoverage['core/Editor.js'][810]++; + if ((browser.gecko && (geckoSel = this.selection.getNative()))) { + _$jscoverage['core/Editor.js'][811]++; + geckoSel.removeAllRanges(); + } + _$jscoverage['core/Editor.js'][813]++; + if (me.options.autoSyncData) { + _$jscoverage['core/Editor.js'][814]++; + (me.form && setValue(me.form, me)); + } +}), focus: (function (toEnd) { + _$jscoverage['core/Editor.js'][837]++; + try { + _$jscoverage['core/Editor.js'][838]++; + var me = this, rng = me.selection.getRange(); + _$jscoverage['core/Editor.js'][840]++; + if (toEnd) { + _$jscoverage['core/Editor.js'][841]++; + rng.setStartAtLast(me.body.lastChild).setCursor(false, true); + } + else { + _$jscoverage['core/Editor.js'][843]++; + rng.select(true); + } + _$jscoverage['core/Editor.js'][845]++; + this.fireEvent("focus"); + } + catch (e) { + } +}), _initEvents: (function () { + _$jscoverage['core/Editor.js'][856]++; + var me = this, doc = me.document, win = me.window; + _$jscoverage['core/Editor.js'][859]++; + me._proxyDomEvent = utils.bind(me._proxyDomEvent, me); + _$jscoverage['core/Editor.js'][860]++; + domUtils.on(doc, ["click", "contextmenu", "mousedown", "keydown", "keyup", "keypress", "mouseup", "mouseover", "mouseout", "selectstart"], me._proxyDomEvent); + _$jscoverage['core/Editor.js'][861]++; + domUtils.on(win, ["focus", "blur"], me._proxyDomEvent); + _$jscoverage['core/Editor.js'][862]++; + domUtils.on(doc, ["mouseup", "keydown"], (function (evt) { + _$jscoverage['core/Editor.js'][864]++; + if (((evt.type == "keydown") && (evt.ctrlKey || evt.metaKey || evt.shiftKey || evt.altKey))) { + _$jscoverage['core/Editor.js'][865]++; + return; + } + _$jscoverage['core/Editor.js'][867]++; + if ((evt.button == 2)) { + _$jscoverage['core/Editor.js'][867]++; + return; + } + _$jscoverage['core/Editor.js'][868]++; + me._selectionChange(250, evt); +})); +}), _proxyDomEvent: (function (evt) { + _$jscoverage['core/Editor.js'][921]++; + return this.fireEvent(evt.type.replace(/^on/, ""), evt); +}), _selectionChange: (function (delay, evt) { + _$jscoverage['core/Editor.js'][929]++; + var me = this; + _$jscoverage['core/Editor.js'][936]++; + var hackForMouseUp = false; + _$jscoverage['core/Editor.js'][937]++; + var mouseX, mouseY; + _$jscoverage['core/Editor.js'][938]++; + if ((browser.ie && (browser.version < 9) && evt && (evt.type == "mouseup"))) { + _$jscoverage['core/Editor.js'][939]++; + var range = this.selection.getRange(); + _$jscoverage['core/Editor.js'][940]++; + if ((! range.collapsed)) { + _$jscoverage['core/Editor.js'][941]++; + hackForMouseUp = true; + _$jscoverage['core/Editor.js'][942]++; + mouseX = evt.clientX; + _$jscoverage['core/Editor.js'][943]++; + mouseY = evt.clientY; + } + } + _$jscoverage['core/Editor.js'][946]++; + clearTimeout(_selectionChangeTimer); + _$jscoverage['core/Editor.js'][947]++; + _selectionChangeTimer = setTimeout((function () { + _$jscoverage['core/Editor.js'][948]++; + if ((! me.selection.getNative())) { + _$jscoverage['core/Editor.js'][949]++; + return; + } + _$jscoverage['core/Editor.js'][953]++; + var ieRange; + _$jscoverage['core/Editor.js'][954]++; + if ((hackForMouseUp && (me.selection.getNative().type == "None"))) { + _$jscoverage['core/Editor.js'][955]++; + ieRange = me.document.body.createTextRange(); + _$jscoverage['core/Editor.js'][956]++; + try { + _$jscoverage['core/Editor.js'][957]++; + ieRange.moveToPoint(mouseX, mouseY); + } + catch (ex) { + _$jscoverage['core/Editor.js'][959]++; + ieRange = null; + } + } + _$jscoverage['core/Editor.js'][962]++; + var bakGetIERange; + _$jscoverage['core/Editor.js'][963]++; + if (ieRange) { + _$jscoverage['core/Editor.js'][964]++; + bakGetIERange = me.selection.getIERange; + _$jscoverage['core/Editor.js'][965]++; + me.selection.getIERange = (function () { + _$jscoverage['core/Editor.js'][966]++; + return ieRange; +}); + } + _$jscoverage['core/Editor.js'][969]++; + me.selection.cache(); + _$jscoverage['core/Editor.js'][970]++; + if (bakGetIERange) { + _$jscoverage['core/Editor.js'][971]++; + me.selection.getIERange = bakGetIERange; + } + _$jscoverage['core/Editor.js'][973]++; + if ((me.selection._cachedRange && me.selection._cachedStartElement)) { + _$jscoverage['core/Editor.js'][974]++; + me.fireEvent("beforeselectionchange"); + _$jscoverage['core/Editor.js'][976]++; + me.fireEvent("selectionchange", (! (! evt))); + _$jscoverage['core/Editor.js'][977]++; + me.fireEvent("afterselectionchange"); + _$jscoverage['core/Editor.js'][978]++; + me.selection.clear(); + } +}), (delay || 50)); +}), _callCmdFn: (function (fnName, args) { + _$jscoverage['core/Editor.js'][992]++; + var cmdName = args[0].toLowerCase(), cmd, cmdFn; + _$jscoverage['core/Editor.js'][994]++; + cmd = (this.commands[cmdName] || UE.commands[cmdName]); + _$jscoverage['core/Editor.js'][995]++; + cmdFn = (cmd && cmd[fnName]); + _$jscoverage['core/Editor.js'][997]++; + if ((((! cmd) || (! cmdFn)) && (fnName == "queryCommandState"))) { + _$jscoverage['core/Editor.js'][998]++; + return 0; + } + else { + _$jscoverage['core/Editor.js'][999]++; + if (cmdFn) { + _$jscoverage['core/Editor.js'][1000]++; + return cmdFn.apply(this, args); + } + } +}), execCommand: (function (cmdName) { + _$jscoverage['core/Editor.js'][1014]++; + cmdName = cmdName.toLowerCase(); + _$jscoverage['core/Editor.js'][1015]++; + var me = this, result, cmd = (me.commands[cmdName] || UE.commands[cmdName]); + _$jscoverage['core/Editor.js'][1018]++; + if (((! cmd) || (! cmd.execCommand))) { + _$jscoverage['core/Editor.js'][1019]++; + return null; + } + _$jscoverage['core/Editor.js'][1021]++; + if (((! cmd.notNeedUndo) && (! me.__hasEnterExecCommand))) { + _$jscoverage['core/Editor.js'][1022]++; + me.__hasEnterExecCommand = true; + _$jscoverage['core/Editor.js'][1023]++; + if ((me.queryCommandState.apply(me, arguments) != -1)) { + _$jscoverage['core/Editor.js'][1024]++; + me.fireEvent("beforeexeccommand", cmdName); + _$jscoverage['core/Editor.js'][1025]++; + result = this._callCmdFn("execCommand", arguments); + _$jscoverage['core/Editor.js'][1026]++; + ((! me._ignoreContentChange) && me.fireEvent("contentchange")); + _$jscoverage['core/Editor.js'][1027]++; + me.fireEvent("afterexeccommand", cmdName); + } + _$jscoverage['core/Editor.js'][1029]++; + me.__hasEnterExecCommand = false; + } + else { + _$jscoverage['core/Editor.js'][1031]++; + result = this._callCmdFn("execCommand", arguments); + _$jscoverage['core/Editor.js'][1032]++; + ((! me._ignoreContentChange) && me.fireEvent("contentchange")); + } + _$jscoverage['core/Editor.js'][1034]++; + ((! me._ignoreContentChange) && me._selectionChange()); + _$jscoverage['core/Editor.js'][1035]++; + return result; +}), queryCommandState: (function (cmdName) { + _$jscoverage['core/Editor.js'][1051]++; + return this._callCmdFn("queryCommandState", arguments); +}), queryCommandValue: (function (cmdName) { + _$jscoverage['core/Editor.js'][1062]++; + return this._callCmdFn("queryCommandValue", arguments); +}), hasContents: (function (tags) { + _$jscoverage['core/Editor.js'][1088]++; + if (tags) { + _$jscoverage['core/Editor.js'][1089]++; + for (var i = 0, ci; (ci = tags[(i++)]);) { + _$jscoverage['core/Editor.js'][1090]++; + if ((this.document.getElementsByTagName(ci).length > 0)) { + _$jscoverage['core/Editor.js'][1091]++; + return true; + } +} + } + _$jscoverage['core/Editor.js'][1095]++; + if ((! domUtils.isEmptyBlock(this.body))) { + _$jscoverage['core/Editor.js'][1096]++; + return true; + } + _$jscoverage['core/Editor.js'][1099]++; + tags = ["div"]; + _$jscoverage['core/Editor.js'][1100]++; + for (i = 0; (ci = tags[(i++)]);) { + _$jscoverage['core/Editor.js'][1101]++; + var nodes = domUtils.getElementsByTagName(this.document, ci); + _$jscoverage['core/Editor.js'][1102]++; + for (var n = 0, cn; (cn = nodes[(n++)]);) { + _$jscoverage['core/Editor.js'][1103]++; + if (domUtils.isCustomeNode(cn)) { + _$jscoverage['core/Editor.js'][1104]++; + return true; + } +} +} + _$jscoverage['core/Editor.js'][1108]++; + return false; +}), reset: (function () { + _$jscoverage['core/Editor.js'][1121]++; + this.fireEvent("reset"); +}), setEnabled: (function () { + _$jscoverage['core/Editor.js'][1133]++; + var me = this, range; + _$jscoverage['core/Editor.js'][1134]++; + if ((me.body.contentEditable == "false")) { + _$jscoverage['core/Editor.js'][1135]++; + me.body.contentEditable = true; + _$jscoverage['core/Editor.js'][1136]++; + range = me.selection.getRange(); + _$jscoverage['core/Editor.js'][1138]++; + try { + _$jscoverage['core/Editor.js'][1139]++; + range.moveToBookmark(me.lastBk); + _$jscoverage['core/Editor.js'][1140]++; + (delete me.lastBk); + } + catch (e) { + _$jscoverage['core/Editor.js'][1142]++; + range.setStartAtFirst(me.body).collapse(true); + } + _$jscoverage['core/Editor.js'][1144]++; + range.select(true); + _$jscoverage['core/Editor.js'][1145]++; + if (me.bkqueryCommandState) { + _$jscoverage['core/Editor.js'][1146]++; + me.queryCommandState = me.bkqueryCommandState; + _$jscoverage['core/Editor.js'][1147]++; + (delete me.bkqueryCommandState); + } + _$jscoverage['core/Editor.js'][1149]++; + me.fireEvent("selectionchange"); + } +}), enable: (function () { + _$jscoverage['core/Editor.js'][1164]++; + return this.setEnabled(); +}), setDisabled: (function (except) { + _$jscoverage['core/Editor.js'][1191]++; + var me = this; + _$jscoverage['core/Editor.js'][1192]++; + except = (except? (utils.isArray(except)? except: [except]): []); + _$jscoverage['core/Editor.js'][1193]++; + if ((me.body.contentEditable == "true")) { + _$jscoverage['core/Editor.js'][1194]++; + if ((! me.lastBk)) { + _$jscoverage['core/Editor.js'][1195]++; + me.lastBk = me.selection.getRange().createBookmark(true); + } + _$jscoverage['core/Editor.js'][1197]++; + me.body.contentEditable = false; + _$jscoverage['core/Editor.js'][1198]++; + me.bkqueryCommandState = me.queryCommandState; + _$jscoverage['core/Editor.js'][1199]++; + me.queryCommandState = (function (type) { + _$jscoverage['core/Editor.js'][1200]++; + if ((utils.indexOf(except, type) != -1)) { + _$jscoverage['core/Editor.js'][1201]++; + return me.bkqueryCommandState.apply(me, arguments); + } + _$jscoverage['core/Editor.js'][1203]++; + return -1; +}); + _$jscoverage['core/Editor.js'][1205]++; + me.fireEvent("selectionchange"); + } +}), disable: (function (except) { + _$jscoverage['core/Editor.js'][1236]++; + return this.setDisabled(except); +}), _setDefaultContent: (function () { + _$jscoverage['core/Editor.js'][1246]++; + function clear() { + _$jscoverage['core/Editor.js'][1247]++; + var me = this; + _$jscoverage['core/Editor.js'][1248]++; + if (me.document.getElementById("initContent")) { + _$jscoverage['core/Editor.js'][1249]++; + me.body.innerHTML = ("

    " + (ie? "": "
    ") + "

    "); + _$jscoverage['core/Editor.js'][1250]++; + me.removeListener("firstBeforeExecCommand focus", clear); + _$jscoverage['core/Editor.js'][1251]++; + setTimeout((function () { + _$jscoverage['core/Editor.js'][1252]++; + me.focus(); + _$jscoverage['core/Editor.js'][1253]++; + me._selectionChange(); +}), 0); + } +} + _$jscoverage['core/Editor.js'][1258]++; + return (function (cont) { + _$jscoverage['core/Editor.js'][1259]++; + var me = this; + _$jscoverage['core/Editor.js'][1260]++; + me.body.innerHTML = ("

    " + cont + "

    "); + _$jscoverage['core/Editor.js'][1262]++; + me.addListener("firstBeforeExecCommand focus", clear); +}); +})(), setShow: (function () { + _$jscoverage['core/Editor.js'][1272]++; + var me = this, range = me.selection.getRange(); + _$jscoverage['core/Editor.js'][1273]++; + if ((me.container.style.display == "none")) { + _$jscoverage['core/Editor.js'][1275]++; + try { + _$jscoverage['core/Editor.js'][1276]++; + range.moveToBookmark(me.lastBk); + _$jscoverage['core/Editor.js'][1277]++; + (delete me.lastBk); + } + catch (e) { + _$jscoverage['core/Editor.js'][1279]++; + range.setStartAtFirst(me.body).collapse(true); + } + _$jscoverage['core/Editor.js'][1282]++; + setTimeout((function () { + _$jscoverage['core/Editor.js'][1283]++; + range.select(true); +}), 100); + _$jscoverage['core/Editor.js'][1285]++; + me.container.style.display = ""; + } +}), show: (function () { + _$jscoverage['core/Editor.js'][1299]++; + return this.setShow(); +}), setHide: (function () { + _$jscoverage['core/Editor.js'][1308]++; + var me = this; + _$jscoverage['core/Editor.js'][1309]++; + if ((! me.lastBk)) { + _$jscoverage['core/Editor.js'][1310]++; + me.lastBk = me.selection.getRange().createBookmark(true); + } + _$jscoverage['core/Editor.js'][1312]++; + me.container.style.display = "none"; +}), hide: (function () { + _$jscoverage['core/Editor.js'][1325]++; + return this.setHide(); +}), getLang: (function (path) { + _$jscoverage['core/Editor.js'][1339]++; + var lang = UE.I18N[this.options.lang]; + _$jscoverage['core/Editor.js'][1340]++; + if ((! lang)) { + _$jscoverage['core/Editor.js'][1341]++; + throw Error("not import language file"); + } + _$jscoverage['core/Editor.js'][1343]++; + path = (path || "").split("."); + _$jscoverage['core/Editor.js'][1344]++; + for (var i = 0, ci; (ci = path[(i++)]);) { + _$jscoverage['core/Editor.js'][1345]++; + lang = lang[ci]; + _$jscoverage['core/Editor.js'][1346]++; + if ((! lang)) { + _$jscoverage['core/Editor.js'][1346]++; + break; + } +} + _$jscoverage['core/Editor.js'][1348]++; + return lang; +}), getContentLength: (function (ingoneHtml, tagNames) { + _$jscoverage['core/Editor.js'][1385]++; + var count = this.getContent(false, false, true).length; + _$jscoverage['core/Editor.js'][1386]++; + if (ingoneHtml) { + _$jscoverage['core/Editor.js'][1387]++; + tagNames = (tagNames || []).concat(["hr", "img", "iframe"]); + _$jscoverage['core/Editor.js'][1388]++; + count = this.getContentTxt().replace(/[\t\r\n]+/g, "").length; + _$jscoverage['core/Editor.js'][1389]++; + for (var i = 0, ci; (ci = tagNames[(i++)]);) { + _$jscoverage['core/Editor.js'][1390]++; + count += this.document.getElementsByTagName(ci).length; +} + } + _$jscoverage['core/Editor.js'][1393]++; + return count; +}), addInputRule: (function (rule) { + _$jscoverage['core/Editor.js'][1410]++; + this.inputRules.push(rule); +}), filterInputRule: (function (root) { + _$jscoverage['core/Editor.js'][1424]++; + for (var i = 0, ci; (ci = this.inputRules[(i++)]);) { + _$jscoverage['core/Editor.js'][1425]++; + ci.call(this, root); +} +}), addOutputRule: (function (rule) { + _$jscoverage['core/Editor.js'][1443]++; + this.outputRules.push(rule); +}), filterOutputRule: (function (root) { + _$jscoverage['core/Editor.js'][1457]++; + for (var i = 0, ci; (ci = this.outputRules[(i++)]);) { + _$jscoverage['core/Editor.js'][1458]++; + ci.call(this, root); +} +})}; + _$jscoverage['core/Editor.js'][1462]++; + utils.inherits(Editor, EventBase); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/EventBase.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/EventBase.js new file mode 100644 index 000000000..1c090257d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/EventBase.js @@ -0,0 +1,143 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['core/EventBase.js']) { + _$jscoverage['core/EventBase.js'] = []; + _$jscoverage['core/EventBase.js'][32] = 0; + _$jscoverage['core/EventBase.js'][35] = 0; + _$jscoverage['core/EventBase.js'][61] = 0; + _$jscoverage['core/EventBase.js'][62] = 0; + _$jscoverage['core/EventBase.js'][63] = 0; + _$jscoverage['core/EventBase.js'][80] = 0; + _$jscoverage['core/EventBase.js'][81] = 0; + _$jscoverage['core/EventBase.js'][82] = 0; + _$jscoverage['core/EventBase.js'][110] = 0; + _$jscoverage['core/EventBase.js'][111] = 0; + _$jscoverage['core/EventBase.js'][112] = 0; + _$jscoverage['core/EventBase.js'][113] = 0; + _$jscoverage['core/EventBase.js'][115] = 0; + _$jscoverage['core/EventBase.js'][116] = 0; + _$jscoverage['core/EventBase.js'][117] = 0; + _$jscoverage['core/EventBase.js'][118] = 0; + _$jscoverage['core/EventBase.js'][119] = 0; + _$jscoverage['core/EventBase.js'][120] = 0; + _$jscoverage['core/EventBase.js'][121] = 0; + _$jscoverage['core/EventBase.js'][123] = 0; + _$jscoverage['core/EventBase.js'][124] = 0; + _$jscoverage['core/EventBase.js'][128] = 0; + _$jscoverage['core/EventBase.js'][129] = 0; + _$jscoverage['core/EventBase.js'][132] = 0; + _$jscoverage['core/EventBase.js'][148] = 0; + _$jscoverage['core/EventBase.js'][149] = 0; + _$jscoverage['core/EventBase.js'][150] = 0; + _$jscoverage['core/EventBase.js'][151] = 0; +} +_$jscoverage['core/EventBase.js'].source = ["/**"," * UE采用的事件基类"," * @file"," * @module UE"," * @class EventBase"," * @since 1.2.6.1"," */","","/**"," * UEditor公用空间,UEditor所有的功能都挂载在该空间下"," * @unfile"," * @module UE"," */","","/**"," * UE采用的事件基类,继承此类的对应类将获取addListener,removeListener,fireEvent方法。"," * 在UE中,Editor以及所有ui实例都继承了该类,故可以在对应的ui对象以及editor对象上使用上述方法。"," * @unfile"," * @module UE"," * @class EventBase"," */","","/**"," * 通过此构造器,子类可以继承EventBase获取事件监听的方法"," * @constructor"," * @example"," * ```javascript"," * UE.EventBase.call(editor);"," * ```"," */","","var EventBase = UE.EventBase = function () {","};","","EventBase.prototype = {","",""," /**"," * 注册事件监听器"," * @method addListener"," * @param { String } types 监听的事件名称,同时监听多个事件使用空格分隔"," * @param { Function } fn 监听的事件被触发时,会执行该回调函数"," * @waining 事件被触发时,监听的函数假如返回的值恒等于true,回调函数的队列中后面的函数将不执行"," * @example"," * ```javascript"," * editor.addListener('selectionchange',function(){"," * console.log(\"选区已经变化!\");"," * })"," * editor.addListener('beforegetcontent aftergetcontent',function(type){"," * if(type == 'beforegetcontent'){"," * //do something"," * }else{"," * //do something"," * }"," * console.log(this.getContent) // this是注册的事件的编辑器实例"," * })"," * ```"," * @see UE.EventBase:fireEvent(String)"," */"," addListener: function (types, listener) {"," types = utils.trim(types).split(' ');"," for (var i = 0, ti; ti = types[i++];) {"," getListener(this, ti, true).push(listener);"," }"," },","",""," /**"," * 移除事件监听器"," * @method removeListener"," * @param { String } types 移除的事件名称,同时移除多个事件使用空格分隔"," * @param { Function } fn 移除监听事件的函数引用"," * @example"," * ```javascript"," * //changeCallback为方法体"," * editor.removeListener(\"selectionchange\",changeCallback);"," * ```"," */"," removeListener: function (types, listener) {"," types = utils.trim(types).split(' ');"," for (var i = 0, ti; ti = types[i++];) {"," utils.removeItem(getListener(this, ti) || [], listener);"," }"," },","",""," /**"," * 触发事件"," * @method fireEvent"," * @param { String } types 触发的事件名称,同时触发多个事件使用空格分隔"," * @remind 该方法会触发addListener"," * @return { * } 返回触发事件的队列中,最后执行的回调函数的返回值"," * @example"," * ```javascript"," * editor.fireEvent(\"selectionchange\");"," * ```"," */",""," /**"," * 触发事件"," * @method fireEvent"," * @param { String } types 触发的事件名称,同时触发多个事件使用空格分隔"," * @param { *... } options 可选参数,可以传入一个或多个参数,会传给事件触发的回调函数"," * @example"," * ```javascript"," * editor.fireEvent(\"selectionchange\");"," * ```"," */"," fireEvent: function () {"," var types = arguments[0];"," types = utils.trim(types).split(' ');"," for (var i = 0, ti; ti = types[i++];) {"," var listeners = getListener(this, ti),"," r, t, k;"," if (listeners) {"," k = listeners.length;"," while (k--) {"," if (!listeners[k])continue;"," t = listeners[k].apply(this, arguments);"," if (t === true) {"," return t;"," }"," if (t !== undefined) {"," r = t;"," }"," }"," }"," if (t = this['on' + ti.toLowerCase()]) {"," r = t.apply(this, arguments);"," }"," }"," return r;"," }","};","","/**"," * 获得对象所拥有监听类型的所有监听器"," * @unfile"," * @module UE"," * @since 1.2.6.1"," * @method getListener"," * @public"," * @param { Object } obj 查询监听器的对象"," * @param { String } type 事件类型"," * @param { Boolean } force 为true且当前所有type类型的侦听器不存在时,创建一个空监听器数组"," * @return { Array } 监听器数组"," */","function getListener(obj, type, force) {"," var allListeners;"," type = type.toLowerCase();"," return ( ( allListeners = ( obj.__allListeners || force && ( obj.__allListeners = {} ) ) )"," && ( allListeners[type] || force && ( allListeners[type] = [] ) ) );","}"]; +_$jscoverage['core/EventBase.js'][32]++; +var EventBase = (UE.EventBase = (function () { +})); +_$jscoverage['core/EventBase.js'][35]++; +EventBase.prototype = {addListener: (function (types, listener) { + _$jscoverage['core/EventBase.js'][61]++; + types = utils.trim(types).split(" "); + _$jscoverage['core/EventBase.js'][62]++; + for (var i = 0, ti; (ti = types[(i++)]);) { + _$jscoverage['core/EventBase.js'][63]++; + getListener(this, ti, true).push(listener); +} +}), removeListener: (function (types, listener) { + _$jscoverage['core/EventBase.js'][80]++; + types = utils.trim(types).split(" "); + _$jscoverage['core/EventBase.js'][81]++; + for (var i = 0, ti; (ti = types[(i++)]);) { + _$jscoverage['core/EventBase.js'][82]++; + utils.removeItem((getListener(this, ti) || []), listener); +} +}), fireEvent: (function () { + _$jscoverage['core/EventBase.js'][110]++; + var types = arguments[0]; + _$jscoverage['core/EventBase.js'][111]++; + types = utils.trim(types).split(" "); + _$jscoverage['core/EventBase.js'][112]++; + for (var i = 0, ti; (ti = types[(i++)]);) { + _$jscoverage['core/EventBase.js'][113]++; + var listeners = getListener(this, ti), r, t, k; + _$jscoverage['core/EventBase.js'][115]++; + if (listeners) { + _$jscoverage['core/EventBase.js'][116]++; + k = listeners.length; + _$jscoverage['core/EventBase.js'][117]++; + while ((k--)) { + _$jscoverage['core/EventBase.js'][118]++; + if ((! listeners[k])) { + _$jscoverage['core/EventBase.js'][118]++; + continue; + } + _$jscoverage['core/EventBase.js'][119]++; + t = listeners[k].apply(this, arguments); + _$jscoverage['core/EventBase.js'][120]++; + if ((t === true)) { + _$jscoverage['core/EventBase.js'][121]++; + return t; + } + _$jscoverage['core/EventBase.js'][123]++; + if ((t !== undefined)) { + _$jscoverage['core/EventBase.js'][124]++; + r = t; + } +} + } + _$jscoverage['core/EventBase.js'][128]++; + if ((t = this[("on" + ti.toLowerCase())])) { + _$jscoverage['core/EventBase.js'][129]++; + r = t.apply(this, arguments); + } +} + _$jscoverage['core/EventBase.js'][132]++; + return r; +})}; +_$jscoverage['core/EventBase.js'][148]++; +function getListener(obj, type, force) { + _$jscoverage['core/EventBase.js'][149]++; + var allListeners; + _$jscoverage['core/EventBase.js'][150]++; + type = type.toLowerCase(); + _$jscoverage['core/EventBase.js'][151]++; + return ((allListeners = (obj.__allListeners || (force && (obj.__allListeners = {})))) && (allListeners[type] || (force && (allListeners[type] = [])))); +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/Range.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/Range.js new file mode 100644 index 000000000..21bb7e05d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/Range.js @@ -0,0 +1,1888 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['core/Range.js']) { + _$jscoverage['core/Range.js'] = []; + _$jscoverage['core/Range.js'][22] = 0; + _$jscoverage['core/Range.js'][23] = 0; + _$jscoverage['core/Range.js'][31] = 0; + _$jscoverage['core/Range.js'][32] = 0; + _$jscoverage['core/Range.js'][38] = 0; + _$jscoverage['core/Range.js'][39] = 0; + _$jscoverage['core/Range.js'][41] = 0; + _$jscoverage['core/Range.js'][43] = 0; + _$jscoverage['core/Range.js'][44] = 0; + _$jscoverage['core/Range.js'][45] = 0; + _$jscoverage['core/Range.js'][47] = 0; + _$jscoverage['core/Range.js'][48] = 0; + _$jscoverage['core/Range.js'][49] = 0; + _$jscoverage['core/Range.js'][50] = 0; + _$jscoverage['core/Range.js'][51] = 0; + _$jscoverage['core/Range.js'][54] = 0; + _$jscoverage['core/Range.js'][55] = 0; + _$jscoverage['core/Range.js'][56] = 0; + _$jscoverage['core/Range.js'][57] = 0; + _$jscoverage['core/Range.js'][60] = 0; + _$jscoverage['core/Range.js'][61] = 0; + _$jscoverage['core/Range.js'][64] = 0; + _$jscoverage['core/Range.js'][67] = 0; + _$jscoverage['core/Range.js'][74] = 0; + _$jscoverage['core/Range.js'][75] = 0; + _$jscoverage['core/Range.js'][77] = 0; + _$jscoverage['core/Range.js'][78] = 0; + _$jscoverage['core/Range.js'][80] = 0; + _$jscoverage['core/Range.js'][81] = 0; + _$jscoverage['core/Range.js'][83] = 0; + _$jscoverage['core/Range.js'][84] = 0; + _$jscoverage['core/Range.js'][85] = 0; + _$jscoverage['core/Range.js'][87] = 0; + _$jscoverage['core/Range.js'][89] = 0; + _$jscoverage['core/Range.js'][91] = 0; + _$jscoverage['core/Range.js'][92] = 0; + _$jscoverage['core/Range.js'][94] = 0; + _$jscoverage['core/Range.js'][95] = 0; + _$jscoverage['core/Range.js'][96] = 0; + _$jscoverage['core/Range.js'][97] = 0; + _$jscoverage['core/Range.js'][98] = 0; + _$jscoverage['core/Range.js'][99] = 0; + _$jscoverage['core/Range.js'][101] = 0; + _$jscoverage['core/Range.js'][102] = 0; + _$jscoverage['core/Range.js'][105] = 0; + _$jscoverage['core/Range.js'][109] = 0; + _$jscoverage['core/Range.js'][110] = 0; + _$jscoverage['core/Range.js'][112] = 0; + _$jscoverage['core/Range.js'][113] = 0; + _$jscoverage['core/Range.js'][114] = 0; + _$jscoverage['core/Range.js'][116] = 0; + _$jscoverage['core/Range.js'][117] = 0; + _$jscoverage['core/Range.js'][118] = 0; + _$jscoverage['core/Range.js'][120] = 0; + _$jscoverage['core/Range.js'][122] = 0; + _$jscoverage['core/Range.js'][123] = 0; + _$jscoverage['core/Range.js'][124] = 0; + _$jscoverage['core/Range.js'][125] = 0; + _$jscoverage['core/Range.js'][127] = 0; + _$jscoverage['core/Range.js'][128] = 0; + _$jscoverage['core/Range.js'][129] = 0; + _$jscoverage['core/Range.js'][130] = 0; + _$jscoverage['core/Range.js'][131] = 0; + _$jscoverage['core/Range.js'][133] = 0; + _$jscoverage['core/Range.js'][134] = 0; + _$jscoverage['core/Range.js'][138] = 0; + _$jscoverage['core/Range.js'][139] = 0; + _$jscoverage['core/Range.js'][142] = 0; + _$jscoverage['core/Range.js'][143] = 0; + _$jscoverage['core/Range.js'][144] = 0; + _$jscoverage['core/Range.js'][145] = 0; + _$jscoverage['core/Range.js'][147] = 0; + _$jscoverage['core/Range.js'][148] = 0; + _$jscoverage['core/Range.js'][149] = 0; + _$jscoverage['core/Range.js'][152] = 0; + _$jscoverage['core/Range.js'][154] = 0; + _$jscoverage['core/Range.js'][155] = 0; + _$jscoverage['core/Range.js'][157] = 0; + _$jscoverage['core/Range.js'][158] = 0; + _$jscoverage['core/Range.js'][159] = 0; + _$jscoverage['core/Range.js'][193] = 0; + _$jscoverage['core/Range.js'][194] = 0; + _$jscoverage['core/Range.js'][195] = 0; + _$jscoverage['core/Range.js'][199] = 0; + _$jscoverage['core/Range.js'][200] = 0; + _$jscoverage['core/Range.js'][208] = 0; + _$jscoverage['core/Range.js'][209] = 0; + _$jscoverage['core/Range.js'][210] = 0; + _$jscoverage['core/Range.js'][211] = 0; + _$jscoverage['core/Range.js'][212] = 0; + _$jscoverage['core/Range.js'][213] = 0; + _$jscoverage['core/Range.js'][214] = 0; + _$jscoverage['core/Range.js'][218] = 0; + _$jscoverage['core/Range.js'][219] = 0; + _$jscoverage['core/Range.js'][220] = 0; + _$jscoverage['core/Range.js'][223] = 0; + _$jscoverage['core/Range.js'][235] = 0; + _$jscoverage['core/Range.js'][236] = 0; + _$jscoverage['core/Range.js'][237] = 0; + _$jscoverage['core/Range.js'][238] = 0; + _$jscoverage['core/Range.js'][239] = 0; + _$jscoverage['core/Range.js'][240] = 0; + _$jscoverage['core/Range.js'][241] = 0; + _$jscoverage['core/Range.js'][245] = 0; + _$jscoverage['core/Range.js'][263] = 0; + _$jscoverage['core/Range.js'][294] = 0; + _$jscoverage['core/Range.js'][295] = 0; + _$jscoverage['core/Range.js'][296] = 0; + _$jscoverage['core/Range.js'][298] = 0; + _$jscoverage['core/Range.js'][299] = 0; + _$jscoverage['core/Range.js'][300] = 0; + _$jscoverage['core/Range.js'][301] = 0; + _$jscoverage['core/Range.js'][302] = 0; + _$jscoverage['core/Range.js'][305] = 0; + _$jscoverage['core/Range.js'][338] = 0; + _$jscoverage['core/Range.js'][373] = 0; + _$jscoverage['core/Range.js'][407] = 0; + _$jscoverage['core/Range.js'][440] = 0; + _$jscoverage['core/Range.js'][473] = 0; + _$jscoverage['core/Range.js'][504] = 0; + _$jscoverage['core/Range.js'][535] = 0; + _$jscoverage['core/Range.js'][568] = 0; + _$jscoverage['core/Range.js'][602] = 0; + _$jscoverage['core/Range.js'][633] = 0; + _$jscoverage['core/Range.js'][665] = 0; + _$jscoverage['core/Range.js'][691] = 0; + _$jscoverage['core/Range.js'][720] = 0; + _$jscoverage['core/Range.js'][750] = 0; + _$jscoverage['core/Range.js'][751] = 0; + _$jscoverage['core/Range.js'][824] = 0; + _$jscoverage['core/Range.js'][825] = 0; + _$jscoverage['core/Range.js'][826] = 0; + _$jscoverage['core/Range.js'][827] = 0; + _$jscoverage['core/Range.js'][829] = 0; + _$jscoverage['core/Range.js'][830] = 0; + _$jscoverage['core/Range.js'][832] = 0; + _$jscoverage['core/Range.js'][833] = 0; + _$jscoverage['core/Range.js'][880] = 0; + _$jscoverage['core/Range.js'][882] = 0; + _$jscoverage['core/Range.js'][883] = 0; + _$jscoverage['core/Range.js'][885] = 0; + _$jscoverage['core/Range.js'][888] = 0; + _$jscoverage['core/Range.js'][890] = 0; + _$jscoverage['core/Range.js'][891] = 0; + _$jscoverage['core/Range.js'][893] = 0; + _$jscoverage['core/Range.js'][894] = 0; + _$jscoverage['core/Range.js'][898] = 0; + _$jscoverage['core/Range.js'][901] = 0; + _$jscoverage['core/Range.js'][1043] = 0; + _$jscoverage['core/Range.js'][1046] = 0; + _$jscoverage['core/Range.js'][1047] = 0; + _$jscoverage['core/Range.js'][1048] = 0; + _$jscoverage['core/Range.js'][1049] = 0; + _$jscoverage['core/Range.js'][1050] = 0; + _$jscoverage['core/Range.js'][1053] = 0; + _$jscoverage['core/Range.js'][1055] = 0; + _$jscoverage['core/Range.js'][1132] = 0; + _$jscoverage['core/Range.js'][1133] = 0; + _$jscoverage['core/Range.js'][1137] = 0; + _$jscoverage['core/Range.js'][1138] = 0; + _$jscoverage['core/Range.js'][1139] = 0; + _$jscoverage['core/Range.js'][1141] = 0; + _$jscoverage['core/Range.js'][1142] = 0; + _$jscoverage['core/Range.js'][1144] = 0; + _$jscoverage['core/Range.js'][1146] = 0; + _$jscoverage['core/Range.js'][1147] = 0; + _$jscoverage['core/Range.js'][1148] = 0; + _$jscoverage['core/Range.js'][1149] = 0; + _$jscoverage['core/Range.js'][1151] = 0; + _$jscoverage['core/Range.js'][1154] = 0; + _$jscoverage['core/Range.js'][1155] = 0; + _$jscoverage['core/Range.js'][1158] = 0; + _$jscoverage['core/Range.js'][1159] = 0; + _$jscoverage['core/Range.js'][1160] = 0; + _$jscoverage['core/Range.js'][1161] = 0; + _$jscoverage['core/Range.js'][1162] = 0; + _$jscoverage['core/Range.js'][1163] = 0; + _$jscoverage['core/Range.js'][1165] = 0; + _$jscoverage['core/Range.js'][1166] = 0; + _$jscoverage['core/Range.js'][1170] = 0; + _$jscoverage['core/Range.js'][1302] = 0; + _$jscoverage['core/Range.js'][1303] = 0; + _$jscoverage['core/Range.js'][1305] = 0; + _$jscoverage['core/Range.js'][1306] = 0; + _$jscoverage['core/Range.js'][1307] = 0; + _$jscoverage['core/Range.js'][1308] = 0; + _$jscoverage['core/Range.js'][1310] = 0; + _$jscoverage['core/Range.js'][1311] = 0; + _$jscoverage['core/Range.js'][1312] = 0; + _$jscoverage['core/Range.js'][1318] = 0; + _$jscoverage['core/Range.js'][1319] = 0; + _$jscoverage['core/Range.js'][1320] = 0; + _$jscoverage['core/Range.js'][1322] = 0; + _$jscoverage['core/Range.js'][1361] = 0; + _$jscoverage['core/Range.js'][1362] = 0; + _$jscoverage['core/Range.js'][1363] = 0; + _$jscoverage['core/Range.js'][1364] = 0; + _$jscoverage['core/Range.js'][1366] = 0; + _$jscoverage['core/Range.js'][1367] = 0; + _$jscoverage['core/Range.js'][1369] = 0; + _$jscoverage['core/Range.js'][1370] = 0; + _$jscoverage['core/Range.js'][1371] = 0; + _$jscoverage['core/Range.js'][1373] = 0; + _$jscoverage['core/Range.js'][1375] = 0; + _$jscoverage['core/Range.js'][1376] = 0; + _$jscoverage['core/Range.js'][1378] = 0; + _$jscoverage['core/Range.js'][1397] = 0; + _$jscoverage['core/Range.js'][1410] = 0; + _$jscoverage['core/Range.js'][1412] = 0; + _$jscoverage['core/Range.js'][1413] = 0; + _$jscoverage['core/Range.js'][1414] = 0; + _$jscoverage['core/Range.js'][1416] = 0; + _$jscoverage['core/Range.js'][1417] = 0; + _$jscoverage['core/Range.js'][1418] = 0; + _$jscoverage['core/Range.js'][1420] = 0; + _$jscoverage['core/Range.js'][1421] = 0; + _$jscoverage['core/Range.js'][1422] = 0; + _$jscoverage['core/Range.js'][1424] = 0; + _$jscoverage['core/Range.js'][1425] = 0; + _$jscoverage['core/Range.js'][1440] = 0; + _$jscoverage['core/Range.js'][1442] = 0; + _$jscoverage['core/Range.js'][1443] = 0; + _$jscoverage['core/Range.js'][1444] = 0; + _$jscoverage['core/Range.js'][1445] = 0; + _$jscoverage['core/Range.js'][1446] = 0; + _$jscoverage['core/Range.js'][1448] = 0; + _$jscoverage['core/Range.js'][1450] = 0; + _$jscoverage['core/Range.js'][1511] = 0; + _$jscoverage['core/Range.js'][1513] = 0; + _$jscoverage['core/Range.js'][1514] = 0; + _$jscoverage['core/Range.js'][1515] = 0; + _$jscoverage['core/Range.js'][1516] = 0; + _$jscoverage['core/Range.js'][1517] = 0; + _$jscoverage['core/Range.js'][1519] = 0; + _$jscoverage['core/Range.js'][1520] = 0; + _$jscoverage['core/Range.js'][1523] = 0; + _$jscoverage['core/Range.js'][1525] = 0; + _$jscoverage['core/Range.js'][1526] = 0; + _$jscoverage['core/Range.js'][1527] = 0; + _$jscoverage['core/Range.js'][1528] = 0; + _$jscoverage['core/Range.js'][1529] = 0; + _$jscoverage['core/Range.js'][1531] = 0; + _$jscoverage['core/Range.js'][1532] = 0; + _$jscoverage['core/Range.js'][1534] = 0; + _$jscoverage['core/Range.js'][1535] = 0; + _$jscoverage['core/Range.js'][1537] = 0; + _$jscoverage['core/Range.js'][1538] = 0; + _$jscoverage['core/Range.js'][1539] = 0; + _$jscoverage['core/Range.js'][1540] = 0; + _$jscoverage['core/Range.js'][1542] = 0; + _$jscoverage['core/Range.js'][1544] = 0; + _$jscoverage['core/Range.js'][1546] = 0; + _$jscoverage['core/Range.js'][1548] = 0; + _$jscoverage['core/Range.js'][1549] = 0; + _$jscoverage['core/Range.js'][1550] = 0; + _$jscoverage['core/Range.js'][1551] = 0; + _$jscoverage['core/Range.js'][1552] = 0; + _$jscoverage['core/Range.js'][1554] = 0; + _$jscoverage['core/Range.js'][1555] = 0; + _$jscoverage['core/Range.js'][1557] = 0; + _$jscoverage['core/Range.js'][1558] = 0; + _$jscoverage['core/Range.js'][1560] = 0; + _$jscoverage['core/Range.js'][1561] = 0; + _$jscoverage['core/Range.js'][1563] = 0; + _$jscoverage['core/Range.js'][1567] = 0; + _$jscoverage['core/Range.js'][1568] = 0; + _$jscoverage['core/Range.js'][1569] = 0; + _$jscoverage['core/Range.js'][1570] = 0; + _$jscoverage['core/Range.js'][1572] = 0; + _$jscoverage['core/Range.js'][1573] = 0; + _$jscoverage['core/Range.js'][1575] = 0; + _$jscoverage['core/Range.js'][1577] = 0; + _$jscoverage['core/Range.js'][1578] = 0; + _$jscoverage['core/Range.js'][1579] = 0; + _$jscoverage['core/Range.js'][1581] = 0; + _$jscoverage['core/Range.js'][1582] = 0; + _$jscoverage['core/Range.js'][1584] = 0; + _$jscoverage['core/Range.js'][1587] = 0; + _$jscoverage['core/Range.js'][1597] = 0; + _$jscoverage['core/Range.js'][1598] = 0; + _$jscoverage['core/Range.js'][1603] = 0; + _$jscoverage['core/Range.js'][1605] = 0; + _$jscoverage['core/Range.js'][1608] = 0; + _$jscoverage['core/Range.js'][1611] = 0; + _$jscoverage['core/Range.js'][1624] = 0; + _$jscoverage['core/Range.js'][1625] = 0; + _$jscoverage['core/Range.js'][1627] = 0; + _$jscoverage['core/Range.js'][1629] = 0; + _$jscoverage['core/Range.js'][1632] = 0; + _$jscoverage['core/Range.js'][1638] = 0; + _$jscoverage['core/Range.js'][1639] = 0; + _$jscoverage['core/Range.js'][1640] = 0; + _$jscoverage['core/Range.js'][1641] = 0; + _$jscoverage['core/Range.js'][1642] = 0; + _$jscoverage['core/Range.js'][1643] = 0; + _$jscoverage['core/Range.js'][1644] = 0; + _$jscoverage['core/Range.js'][1645] = 0; + _$jscoverage['core/Range.js'][1648] = 0; + _$jscoverage['core/Range.js'][1649] = 0; + _$jscoverage['core/Range.js'][1650] = 0; + _$jscoverage['core/Range.js'][1651] = 0; + _$jscoverage['core/Range.js'][1652] = 0; + _$jscoverage['core/Range.js'][1653] = 0; + _$jscoverage['core/Range.js'][1654] = 0; + _$jscoverage['core/Range.js'][1656] = 0; + _$jscoverage['core/Range.js'][1658] = 0; + _$jscoverage['core/Range.js'][1660] = 0; + _$jscoverage['core/Range.js'][1661] = 0; + _$jscoverage['core/Range.js'][1663] = 0; + _$jscoverage['core/Range.js'][1664] = 0; + _$jscoverage['core/Range.js'][1666] = 0; + _$jscoverage['core/Range.js'][1667] = 0; + _$jscoverage['core/Range.js'][1668] = 0; + _$jscoverage['core/Range.js'][1669] = 0; + _$jscoverage['core/Range.js'][1670] = 0; + _$jscoverage['core/Range.js'][1672] = 0; + _$jscoverage['core/Range.js'][1673] = 0; + _$jscoverage['core/Range.js'][1676] = 0; + _$jscoverage['core/Range.js'][1677] = 0; + _$jscoverage['core/Range.js'][1678] = 0; + _$jscoverage['core/Range.js'][1679] = 0; + _$jscoverage['core/Range.js'][1680] = 0; + _$jscoverage['core/Range.js'][1683] = 0; + _$jscoverage['core/Range.js'][1686] = 0; + _$jscoverage['core/Range.js'][1696] = 0; + _$jscoverage['core/Range.js'][1697] = 0; + _$jscoverage['core/Range.js'][1698] = 0; + _$jscoverage['core/Range.js'][1699] = 0; + _$jscoverage['core/Range.js'][1700] = 0; + _$jscoverage['core/Range.js'][1701] = 0; + _$jscoverage['core/Range.js'][1702] = 0; + _$jscoverage['core/Range.js'][1703] = 0; + _$jscoverage['core/Range.js'][1705] = 0; + _$jscoverage['core/Range.js'][1706] = 0; + _$jscoverage['core/Range.js'][1707] = 0; + _$jscoverage['core/Range.js'][1710] = 0; + _$jscoverage['core/Range.js'][1712] = 0; + _$jscoverage['core/Range.js'][1713] = 0; + _$jscoverage['core/Range.js'][1714] = 0; + _$jscoverage['core/Range.js'][1715] = 0; + _$jscoverage['core/Range.js'][1717] = 0; + _$jscoverage['core/Range.js'][1718] = 0; + _$jscoverage['core/Range.js'][1719] = 0; + _$jscoverage['core/Range.js'][1722] = 0; + _$jscoverage['core/Range.js'][1724] = 0; + _$jscoverage['core/Range.js'][1727] = 0; + _$jscoverage['core/Range.js'][1728] = 0; + _$jscoverage['core/Range.js'][1729] = 0; + _$jscoverage['core/Range.js'][1730] = 0; + _$jscoverage['core/Range.js'][1731] = 0; + _$jscoverage['core/Range.js'][1732] = 0; + _$jscoverage['core/Range.js'][1734] = 0; + _$jscoverage['core/Range.js'][1735] = 0; + _$jscoverage['core/Range.js'][1736] = 0; + _$jscoverage['core/Range.js'][1737] = 0; + _$jscoverage['core/Range.js'][1738] = 0; + _$jscoverage['core/Range.js'][1739] = 0; + _$jscoverage['core/Range.js'][1741] = 0; + _$jscoverage['core/Range.js'][1742] = 0; + _$jscoverage['core/Range.js'][1744] = 0; + _$jscoverage['core/Range.js'][1745] = 0; + _$jscoverage['core/Range.js'][1746] = 0; + _$jscoverage['core/Range.js'][1748] = 0; + _$jscoverage['core/Range.js'][1749] = 0; + _$jscoverage['core/Range.js'][1751] = 0; + _$jscoverage['core/Range.js'][1753] = 0; + _$jscoverage['core/Range.js'][1783] = 0; + _$jscoverage['core/Range.js'][1784] = 0; + _$jscoverage['core/Range.js'][1785] = 0; + _$jscoverage['core/Range.js'][1786] = 0; + _$jscoverage['core/Range.js'][1787] = 0; + _$jscoverage['core/Range.js'][1788] = 0; + _$jscoverage['core/Range.js'][1789] = 0; + _$jscoverage['core/Range.js'][1793] = 0; + _$jscoverage['core/Range.js'][1802] = 0; + _$jscoverage['core/Range.js'][1803] = 0; + _$jscoverage['core/Range.js'][1804] = 0; + _$jscoverage['core/Range.js'][1805] = 0; + _$jscoverage['core/Range.js'][1806] = 0; + _$jscoverage['core/Range.js'][1807] = 0; + _$jscoverage['core/Range.js'][1808] = 0; + _$jscoverage['core/Range.js'][1809] = 0; + _$jscoverage['core/Range.js'][1810] = 0; + _$jscoverage['core/Range.js'][1812] = 0; + _$jscoverage['core/Range.js'][1814] = 0; + _$jscoverage['core/Range.js'][1817] = 0; + _$jscoverage['core/Range.js'][1818] = 0; + _$jscoverage['core/Range.js'][1819] = 0; + _$jscoverage['core/Range.js'][1820] = 0; + _$jscoverage['core/Range.js'][1821] = 0; + _$jscoverage['core/Range.js'][1822] = 0; + _$jscoverage['core/Range.js'][1823] = 0; + _$jscoverage['core/Range.js'][1824] = 0; + _$jscoverage['core/Range.js'][1826] = 0; + _$jscoverage['core/Range.js'][1828] = 0; + _$jscoverage['core/Range.js'][1830] = 0; + _$jscoverage['core/Range.js'][1831] = 0; + _$jscoverage['core/Range.js'][1832] = 0; + _$jscoverage['core/Range.js'][1834] = 0; + _$jscoverage['core/Range.js'][1835] = 0; + _$jscoverage['core/Range.js'][1836] = 0; + _$jscoverage['core/Range.js'][1837] = 0; + _$jscoverage['core/Range.js'][1838] = 0; + _$jscoverage['core/Range.js'][1839] = 0; + _$jscoverage['core/Range.js'][1842] = 0; + _$jscoverage['core/Range.js'][1843] = 0; + _$jscoverage['core/Range.js'][1845] = 0; + _$jscoverage['core/Range.js'][1846] = 0; + _$jscoverage['core/Range.js'][1849] = 0; + _$jscoverage['core/Range.js'][1851] = 0; + _$jscoverage['core/Range.js'][1853] = 0; + _$jscoverage['core/Range.js'][1854] = 0; + _$jscoverage['core/Range.js'][1855] = 0; + _$jscoverage['core/Range.js'][1858] = 0; + _$jscoverage['core/Range.js'][1859] = 0; + _$jscoverage['core/Range.js'][1861] = 0; + _$jscoverage['core/Range.js'][1866] = 0; + _$jscoverage['core/Range.js'][1867] = 0; + _$jscoverage['core/Range.js'][1868] = 0; + _$jscoverage['core/Range.js'][1871] = 0; + _$jscoverage['core/Range.js'][1883] = 0; + _$jscoverage['core/Range.js'][1884] = 0; + _$jscoverage['core/Range.js'][1885] = 0; + _$jscoverage['core/Range.js'][1888] = 0; + _$jscoverage['core/Range.js'][1895] = 0; + _$jscoverage['core/Range.js'][1897] = 0; + _$jscoverage['core/Range.js'][1898] = 0; + _$jscoverage['core/Range.js'][1899] = 0; + _$jscoverage['core/Range.js'][1900] = 0; + _$jscoverage['core/Range.js'][1901] = 0; + _$jscoverage['core/Range.js'][1902] = 0; + _$jscoverage['core/Range.js'][1905] = 0; + _$jscoverage['core/Range.js'][1906] = 0; + _$jscoverage['core/Range.js'][1907] = 0; + _$jscoverage['core/Range.js'][1908] = 0; + _$jscoverage['core/Range.js'][1910] = 0; + _$jscoverage['core/Range.js'][1911] = 0; + _$jscoverage['core/Range.js'][1912] = 0; + _$jscoverage['core/Range.js'][1916] = 0; + _$jscoverage['core/Range.js'][1917] = 0; + _$jscoverage['core/Range.js'][1918] = 0; + _$jscoverage['core/Range.js'][1920] = 0; + _$jscoverage['core/Range.js'][1923] = 0; + _$jscoverage['core/Range.js'][1928] = 0; + _$jscoverage['core/Range.js'][1929] = 0; + _$jscoverage['core/Range.js'][1930] = 0; + _$jscoverage['core/Range.js'][1931] = 0; + _$jscoverage['core/Range.js'][1933] = 0; + _$jscoverage['core/Range.js'][1951] = 0; + _$jscoverage['core/Range.js'][1952] = 0; + _$jscoverage['core/Range.js'][1955] = 0; + _$jscoverage['core/Range.js'][1956] = 0; + _$jscoverage['core/Range.js'][1957] = 0; + _$jscoverage['core/Range.js'][1958] = 0; + _$jscoverage['core/Range.js'][1959] = 0; + _$jscoverage['core/Range.js'][1967] = 0; + _$jscoverage['core/Range.js'][1968] = 0; + _$jscoverage['core/Range.js'][1971] = 0; + _$jscoverage['core/Range.js'][1973] = 0; + _$jscoverage['core/Range.js'][2000] = 0; + _$jscoverage['core/Range.js'][2002] = 0; + _$jscoverage['core/Range.js'][2003] = 0; + _$jscoverage['core/Range.js'][2004] = 0; + _$jscoverage['core/Range.js'][2006] = 0; + _$jscoverage['core/Range.js'][2007] = 0; + _$jscoverage['core/Range.js'][2009] = 0; + _$jscoverage['core/Range.js'][2011] = 0; + _$jscoverage['core/Range.js'][2012] = 0; + _$jscoverage['core/Range.js'][2013] = 0; + _$jscoverage['core/Range.js'][2014] = 0; + _$jscoverage['core/Range.js'][2015] = 0; + _$jscoverage['core/Range.js'][2016] = 0; + _$jscoverage['core/Range.js'][2018] = 0; + _$jscoverage['core/Range.js'][2020] = 0; + _$jscoverage['core/Range.js'][2021] = 0; + _$jscoverage['core/Range.js'][2022] = 0; + _$jscoverage['core/Range.js'][2024] = 0; + _$jscoverage['core/Range.js'][2025] = 0; + _$jscoverage['core/Range.js'][2026] = 0; + _$jscoverage['core/Range.js'][2027] = 0; + _$jscoverage['core/Range.js'][2028] = 0; + _$jscoverage['core/Range.js'][2029] = 0; + _$jscoverage['core/Range.js'][2031] = 0; + _$jscoverage['core/Range.js'][2032] = 0; + _$jscoverage['core/Range.js'][2033] = 0; + _$jscoverage['core/Range.js'][2034] = 0; + _$jscoverage['core/Range.js'][2037] = 0; + _$jscoverage['core/Range.js'][2044] = 0; + _$jscoverage['core/Range.js'][2046] = 0; + _$jscoverage['core/Range.js'][2047] = 0; + _$jscoverage['core/Range.js'][2049] = 0; + _$jscoverage['core/Range.js'][2050] = 0; + _$jscoverage['core/Range.js'][2052] = 0; + _$jscoverage['core/Range.js'][2053] = 0; + _$jscoverage['core/Range.js'][2054] = 0; + _$jscoverage['core/Range.js'][2056] = 0; + _$jscoverage['core/Range.js'][2085] = 0; + _$jscoverage['core/Range.js'][2086] = 0; + _$jscoverage['core/Range.js'][2087] = 0; + _$jscoverage['core/Range.js'][2089] = 0; + _$jscoverage['core/Range.js'][2090] = 0; + _$jscoverage['core/Range.js'][2091] = 0; + _$jscoverage['core/Range.js'][2092] = 0; + _$jscoverage['core/Range.js'][2093] = 0; + _$jscoverage['core/Range.js'][2094] = 0; + _$jscoverage['core/Range.js'][2095] = 0; + _$jscoverage['core/Range.js'][2098] = 0; + _$jscoverage['core/Range.js'][2099] = 0; + _$jscoverage['core/Range.js'][2100] = 0; + _$jscoverage['core/Range.js'][2102] = 0; + _$jscoverage['core/Range.js'][2105] = 0; + _$jscoverage['core/Range.js'][2106] = 0; + _$jscoverage['core/Range.js'][2108] = 0; + _$jscoverage['core/Range.js'][2112] = 0; + _$jscoverage['core/Range.js'][2113] = 0; + _$jscoverage['core/Range.js'][2114] = 0; + _$jscoverage['core/Range.js'][2214] = 0; + _$jscoverage['core/Range.js'][2215] = 0; + _$jscoverage['core/Range.js'][2216] = 0; + _$jscoverage['core/Range.js'][2219] = 0; + _$jscoverage['core/Range.js'][2220] = 0; + _$jscoverage['core/Range.js'][2221] = 0; + _$jscoverage['core/Range.js'][2222] = 0; + _$jscoverage['core/Range.js'][2224] = 0; +} +_$jscoverage['core/Range.js'].source = ["/**"," * Range封装"," * @file"," * @module UE.dom"," * @class Range"," * @since 1.2.6.1"," */","","/**"," * dom操作封装"," * @unfile"," * @module UE.dom"," */","","/**"," * Range实现类,本类是UEditor底层核心类,统一w3cRange和ieRange之间的差异,包括接口和属性"," * @unfile"," * @module UE.dom"," * @class Range"," */","","(function () {"," var guid = 0,"," fillChar = domUtils.fillChar,"," fillData;",""," /*"," * 更新range的collapse状态"," * @param {Range} range range对象"," */"," function updateCollapse(range) {"," range.collapsed ="," range.startContainer && range.endContainer &&"," range.startContainer === range.endContainer &&"," range.startOffset == range.endOffset;"," }",""," function selectOneNode(rng){"," return !rng.collapsed && rng.startContainer.nodeType == 1 && rng.startContainer === rng.endContainer && rng.endOffset - rng.startOffset == 1"," }"," function setEndPoint(toStart, node, offset, range) {"," //如果node是自闭合标签要处理"," if (node.nodeType == 1 && (dtd.$empty[node.tagName] || dtd.$nonChild[node.tagName])) {"," offset = domUtils.getNodeIndex(node) + (toStart ? 0 : 1);"," node = node.parentNode;"," }"," if (toStart) {"," range.startContainer = node;"," range.startOffset = offset;"," if (!range.endContainer) {"," range.collapse(true);"," }"," } else {"," range.endContainer = node;"," range.endOffset = offset;"," if (!range.startContainer) {"," range.collapse(false);"," }"," }"," updateCollapse(range);"," return range;"," }",""," function execContentsAction(range, action) {"," //调整边界"," //range.includeBookmark();"," var start = range.startContainer,"," end = range.endContainer,"," startOffset = range.startOffset,"," endOffset = range.endOffset,"," doc = range.document,"," frag = doc.createDocumentFragment(),"," tmpStart, tmpEnd;"," if (start.nodeType == 1) {"," start = start.childNodes[startOffset] || (tmpStart = start.appendChild(doc.createTextNode('')));"," }"," if (end.nodeType == 1) {"," end = end.childNodes[endOffset] || (tmpEnd = end.appendChild(doc.createTextNode('')));"," }"," if (start === end && start.nodeType == 3) {"," frag.appendChild(doc.createTextNode(start.substringData(startOffset, endOffset - startOffset)));"," //is not clone"," if (action) {"," start.deleteData(startOffset, endOffset - startOffset);"," range.collapse(true);"," }"," return frag;"," }"," var current, currentLevel, clone = frag,"," startParents = domUtils.findParents(start, true), endParents = domUtils.findParents(end, true);"," for (var i = 0; startParents[i] == endParents[i];) {"," i++;"," }"," for (var j = i, si; si = startParents[j]; j++) {"," current = si.nextSibling;"," if (si == start) {"," if (!tmpStart) {"," if (range.startContainer.nodeType == 3) {"," clone.appendChild(doc.createTextNode(start.nodeValue.slice(startOffset)));"," //is not clone"," if (action) {"," start.deleteData(startOffset, start.nodeValue.length - startOffset);"," }"," } else {"," clone.appendChild(!action ? start.cloneNode(true) : start);"," }"," }"," } else {"," currentLevel = si.cloneNode(false);"," clone.appendChild(currentLevel);"," }"," while (current) {"," if (current === end || current === endParents[j]) {"," break;"," }"," si = current.nextSibling;"," clone.appendChild(!action ? current.cloneNode(true) : current);"," current = si;"," }"," clone = currentLevel;"," }"," clone = frag;"," if (!startParents[i]) {"," clone.appendChild(startParents[i - 1].cloneNode(false));"," clone = clone.firstChild;"," }"," for (var j = i, ei; ei = endParents[j]; j++) {"," current = ei.previousSibling;"," if (ei == end) {"," if (!tmpEnd && range.endContainer.nodeType == 3) {"," clone.appendChild(doc.createTextNode(end.substringData(0, endOffset)));"," //is not clone"," if (action) {"," end.deleteData(0, endOffset);"," }"," }"," } else {"," currentLevel = ei.cloneNode(false);"," clone.appendChild(currentLevel);"," }"," //如果两端同级,右边第一次已经被开始做了"," if (j != i || !startParents[i]) {"," while (current) {"," if (current === start) {"," break;"," }"," ei = current.previousSibling;"," clone.insertBefore(!action ? current.cloneNode(true) : current, clone.firstChild);"," current = ei;"," }"," }"," clone = currentLevel;"," }"," if (action) {"," range.setStartBefore(!endParents[i] ? endParents[i - 1] : !startParents[i] ? startParents[i - 1] : endParents[i]).collapse(true);"," }"," tmpStart && domUtils.remove(tmpStart);"," tmpEnd && domUtils.remove(tmpEnd);"," return frag;"," }",""," /**"," * 创建一个跟document绑定的空的Range实例"," * @constructor"," */",""," /**"," * @property { Node } startContainer 当前Range的开始边界的容器节点, 可以是一个元素节点或者是文本节点"," */",""," /**"," * @property { Node } startOffset 当前Range的开始边界容器节点的偏移量, 如果是元素节点,"," * 该值就是childNodes中的第几个节点, 如果是文本节点就是文本内容的第几个字符"," */",""," /**"," * @property { Node } endContainer 当前Range的结束边界的容器节点, 可以是一个元素节点或者是文本节点"," */",""," /**"," * @property { Node } endOffset 当前Range的结束边界容器节点的偏移量, 如果是元素节点,"," * 该值就是childNodes中的第几个节点, 如果是文本节点就是文本内容的第几个字符"," */",""," /**"," * @property { Boolean } collapsed 当前Range是否是闭合的"," */",""," /**"," * @property { Document } document 当前Range所属的Document对象"," */",""," var Range = dom.Range = function (document) {"," var me = this;"," me.startContainer ="," me.startOffset ="," me.endContainer ="," me.endOffset = null;"," me.document = document;"," me.collapsed = true;"," };",""," /*"," * 删除fillData"," * @param doc"," * @param excludeNode"," */"," function removeFillData(doc, excludeNode) {"," try {"," if (fillData && domUtils.inDoc(fillData, doc)) {"," if (!fillData.nodeValue.replace(fillCharReg, '').length) {"," var tmpNode = fillData.parentNode;"," domUtils.remove(fillData);"," while (tmpNode && domUtils.isEmptyInlineElement(tmpNode) &&"," //safari的contains有bug"," (browser.safari ? !(domUtils.getPosition(tmpNode,excludeNode) & domUtils.POSITION_CONTAINS) : !tmpNode.contains(excludeNode))"," ) {"," fillData = tmpNode.parentNode;"," domUtils.remove(tmpNode);"," tmpNode = fillData;"," }"," } else {"," fillData.nodeValue = fillData.nodeValue.replace(fillCharReg, '');"," }"," }"," } catch (e) {"," }"," }",""," /*"," *"," * @param node"," * @param dir"," */"," function mergeSibling(node, dir) {"," var tmpNode;"," node = node[dir];"," while (node && domUtils.isFillChar(node)) {"," tmpNode = node[dir];"," domUtils.remove(node);"," node = tmpNode;"," }"," }",""," Range.prototype = {",""," /**"," * 克隆选中的内容到一个DocumentFragment里"," * @method cloneContents"," * @return { DocumentFragment | NULL } 如果选区是空的将返回null, 否则, 返回包含所clone内容的DocumentFragment元素"," * @example"," * ```html"," * <!-- 被选中的内容 -->"," * <div>123</div><div>456</div>"," *"," * <script>"," * //output: 2"," * console.log( range.cloneContents().childNodes.length );"," * </script>"," * ```"," */"," cloneContents:function () {"," return this.collapsed ? null : execContentsAction(this, 0);"," },",""," /**"," * 删除当前选区范围中的所有内容"," * @method deleteContents"," * @remind 执行完该操作后, 当前Range对象变成了闭合状态"," * @remind 执行该操作会引起当前Range对象的其他属性的变化"," * @return { UE.dom.Range } 当前操作的Range对象"," * @example"," * ```html"," * <body>"," * <!-- 选区开始 -->"," * <div></div>"," * <span></span>"," * <!-- 选区结束 -->"," * </body>"," *"," * <script>"," * //output: 5"," * console.log( document.body.childNodes.length );"," *"," * //执行删除选区内容操作"," * range.deleteContents();"," *"," * //output: 2"," * console.log( document.body.childNodes.length );"," * </script>"," * ```"," */"," deleteContents:function () {"," var txt;"," if (!this.collapsed) {"," execContentsAction(this, 1);"," }"," if (browser.webkit) {"," txt = this.startContainer;"," if (txt.nodeType == 3 && !txt.nodeValue.length) {"," this.setStartBefore(txt).collapse(true);"," domUtils.remove(txt);"," }"," }"," return this;"," },",""," /**"," * 将当前选区的内容提取到一个DocumentFragment里"," * @method extractContents"," * @remind 执行该操作后, 选区将变成闭合状态"," * @warning 执行该操作后, 原来选区所选中的内容将从dom树上剥离出来"," * @return { DocumentFragment } 返回包含所提取内容的DocumentFragment对象"," * @example"," * ```html"," * <body>"," * <!-- 选区开始 -->"," * <div></div>"," * <span></span>"," * <!-- 选区结束 -->"," * </body>"," * <script>"," * //output: 5"," * console.log( document.body.childNodes.length );"," *"," * //执行选区内容提取"," * var contents = range.extractContents();"," *"," * //output: 2"," * console.log( document.body.childNodes.length );"," *"," * //output: 3"," * console.log( contents.childNodes.length );"," *"," * </script>"," */"," extractContents:function () {"," return this.collapsed ? null : execContentsAction(this, 2);"," },",""," /**"," * 设置Range的开始位置"," * @method setStart"," * @remind 如果容器节点是元素节点,那么offset指的是其子元素中索引为offset的元素,"," * 如果是文本节点,那么offset指的是其文本内容的第offset个字符"," * @param { Node } node 将被设为当前选区开始边界容器的节点对象"," * @param { int } offset 开始容器的偏移量"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," * <body>"," * <div id=\"test\"></div>"," * <!-- 选区开始 -->"," * <span></span>"," * <a></a>"," * <!-- 选区结束 -->"," * </body>"," *"," * <script>"," *"," * //output: SPAN"," * console.log( range.startContainer.tagName );"," *"," * range.setStart( document.getElementById( \"test\" ), 0 );"," *"," * //output: DIV"," * console.log( range.startContainer.tagName );"," *"," * </script>"," * ```"," */"," setStart:function (node, offset) {"," return setEndPoint(true, node, offset, this);"," },",""," /**"," * 设置Range的结束位置"," * @method setEnd"," * @param { Node } node 将被设为当前选区结束边界容器的节点对象"," * @param { int } offset 结束容器的偏移量"," * @see UE.dom.Range:setStart(Node,int)"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," * <body>"," * <!-- 选区开始 -->"," * <span></span>"," * <a></a>"," * <!-- 选区结束 -->"," * <div id=\"test\"></div>"," * </body>"," *"," * <script>"," *"," * //output: A"," * console.log( range.endContainer.tagName );"," *"," * range.setEnd( document.getElementById( \"test\" ), 0 );"," *"," * //output: DIV"," * console.log( range.endContainer.tagName );"," *"," * </script>"," * ```"," */"," setEnd:function (node, offset) {"," return setEndPoint(false, node, offset, this);"," },",""," /**"," * 将Range开始位置设置到node节点之后"," * @method setStartAfter"," * @param { Node } node 当前选区开始边界之前的节点"," * @see UE.dom.Range:setStart(Node,int)"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," * <body>"," * <div id=\"test\"></div>"," * <span></span>"," * <!-- 选区开始 -->"," * <a></a>"," * <!-- 选区结束 -->"," * </body>"," *"," * <script>"," *"," * //output: A"," * console.log( range.startContainer.tagName );"," *"," * range.setStartAfter( document.getElementById( \"test\" ) );"," *"," * //output: SPAN"," * console.log( range.startContainer.tagName );"," *"," * </script>"," * ```"," */"," setStartAfter:function (node) {"," return this.setStart(node.parentNode, domUtils.getNodeIndex(node) + 1);"," },",""," /**"," * 将Range开始位置设置到node节点之前"," * @method setStartBefore"," * @param { Node } node 新的选区开始位置在该节点之前"," * @see UE.dom.Range:setStart(Node,int)"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," * <body>"," * <span></span>"," * <div id=\"test\"></div>"," * <!-- 选区开始 -->"," * <a></a>"," * <!-- 选区结束 -->"," * </body>"," *"," * <script>"," *"," * //output: A"," * console.log( range.startContainer.tagName );"," *"," * range.setStartBefore( document.getElementById( \"test\" ) );"," *"," * //output: SPAN"," * console.log( range.startContainer.tagName );"," *"," * </script>"," * ```"," */"," setStartBefore:function (node) {"," return this.setStart(node.parentNode, domUtils.getNodeIndex(node));"," },",""," /**"," * 将Range结束位置设置到node节点之后"," * @method setEndAfter"," * @param { Node } node 目标节点"," * @see UE.dom.Range:setStart(Node,int)"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," * <body>"," * <!-- 选区开始 -->"," * <a></a>"," * <!-- 选区结束 -->"," * <span></span>"," * <div id=\"test\"></div>"," *"," * <script>"," * //output: A"," * console.log( range.endContainer.tagName );"," *"," * range.setEndAfter( document.getElementById( \"test\" ) );"," *"," * //output: DIV"," * console.log( range.endContainer.tagName );"," * </script>"," * </body>"," * ```"," */"," setEndAfter:function (node) {"," return this.setEnd(node.parentNode, domUtils.getNodeIndex(node) + 1);"," },",""," /**"," * 将Range结束位置设置到node节点之前"," * @method setEndBefore"," * @param { Node } node 目标节点"," * @see UE.dom.Range:setStart(Node,int)"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," * <body>"," * <!-- 选区开始 -->"," * <a></a>"," * <!-- 选区结束 -->"," * <span></span>"," * <div id=\"test\"></div>"," *"," * <script>"," * //output: A"," * console.log( range.endContainer.tagName );"," *"," * range.setEndBefore( document.getElementById( \"test\" ) );"," *"," * //output: SPAN"," * console.log( range.endContainer.tagName );"," * </script>"," * </body>"," * ```"," */"," setEndBefore:function (node) {"," return this.setEnd(node.parentNode, domUtils.getNodeIndex(node));"," },",""," /**"," * 设置Range的开始位置设置到node节点内的第一个节点处"," * @method setStartAtFirst"," * @param { Node } node 目标节点"," * @see UE.dom.Range:setStart(Node,int)"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," * <body>"," * <div id=\"test\">"," * <i></i>"," * <!-- 选区开始 -->"," * <a></a>"," * <!-- 选区结束 -->"," * <span></span>"," * </div>"," *"," * <script>"," * //output: '<a></a>'"," * console.log( range.cloneContents() );"," *"," * range.setStartAtFirst( document.getElementById(\"test\") );"," *"," * //output: '<i></i><a></a>'"," * console.log( range.cloneContents() );"," * </script>"," * </body>"," * ```"," */"," setStartAtFirst:function (node) {"," return this.setStart(node, 0);"," },",""," /**"," * 设置Range的开始位置设置到node节点内的最后一个节点处"," * @method setStartAtLast"," * @param { Node } node 目标节点"," * @see UE.dom.Range:setStart(Node,int)"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," * <body>"," * <div id=\"test\">"," * <i></i>"," * <!-- 选区开始 -->"," * <a></a>"," * <!-- 选区结束 -->"," * <span></span>"," * </div>"," *"," * <script>"," * //output: <a></a>"," * console.log( range.cloneContents() );"," *"," * range.setStartAtLast( document.body );"," *"," * //选区已经闭合, 输出空字符串"," * //output: ''"," * console.log( range.cloneContents() );"," * </script>"," * </body>"," * ```"," */"," setStartAtLast:function (node) {"," return this.setStart(node, node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length);"," },",""," /**"," * 设置Range的结束位置设置到node节点内的第一个节点处"," * @method setEndAtFirst"," * @param { Node } node 目标节点"," * @see UE.dom.Range:setStart(Node,int)"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," * <body>"," * <!-- 选区开始 -->"," * <a></a>"," * <!-- 选区结束 -->"," * <span></span>"," * <div id=\"test\"></div>"," *"," * <script>"," * //output: '<a></a>'"," * console.log( range.cloneContents() );"," *"," * range.setEndAtFirst( document.getElementById(\"test\") );"," *"," * //output: '<a></a><div></div>'"," * console.log( range.cloneContents() );"," * </script>"," * </body>"," * ```"," */"," setEndAtFirst:function (node) {"," return this.setEnd(node, 0);"," },",""," /**"," * 设置Range的结束位置设置到node节点内的最后一个节点处"," * @method setEndAtLast"," * @param { Node } node 目标节点"," * @see UE.dom.Range:setStart(Node,int)"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," * <body>"," * <div id=\"test\">"," * <!-- 选区开始 -->"," * <a></a>"," * <!-- 选区结束 -->"," * <span></span>"," * </div>"," *"," * <script>"," * //output: '<a></a>'"," * console.log( range.cloneContents() );"," *"," * range.setEndAtLast( document.getElementById(\"test\") );"," *"," * //output: '<a></a><span></span>'"," * console.log( range.cloneContents() );"," * </script>"," * </body>"," * ```"," */"," setEndAtLast:function (node) {"," return this.setEnd(node, node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length);"," },",""," /**"," * 选中一个节点, 并返回包含这个节点的range对象"," * @method selectNode"," * @param { Node } node 需要选中的节点"," * @return { UE.dom.Range } 当前range对象, 但是选区已经改变, 包含了当前选择的节点对象"," * @example"," * ```html"," * <body>"," *"," * <div id=\"test\"></div>"," *"," * <script>"," *"," * range.selectNode( document.getElementById(\"test\") );"," *"," * //output: '<div id=\"test\"></div>'"," * console.log( range.cloneContents() );"," *"," * </script>"," * </body>"," * ```"," */"," selectNode:function (node) {"," return this.setStartBefore(node).setEndAfter(node);"," },",""," /**"," * 选中给定节点内部的所有节点, 并返回包含这个节点内容的range对象"," * @method selectNodeContents"," * @param { Node } node 目标节点, 当前range将包含该节点内的所有节点"," * @return { UE.dom.Range } 当前range对象, 包含了当前选择的节点对象的所有子节点"," * @example"," * ```html"," * <body>"," *"," * <div id=\"test\">"," * <a></a>"," * <i></i>"," * </div>"," *"," * <script>"," *"," * range.selectNodeContents( document.getElementById(\"test\") );"," *"," * //output: '<a></a><i></i>'"," * console.log( range.cloneContents() );"," *"," * </script>"," * </body>"," * ```"," */"," selectNodeContents:function (node) {"," return this.setStart(node, 0).setEndAtLast(node);"," },",""," /**"," * clone当前Range对象"," * @method cloneRange"," * @return { UE.dom.Range } 当前range对象的一个副本"," * @example"," * ```html"," * <body>"," *"," * <div id=\"test\">"," * <!-- 选区开始 -->"," * <a></a>"," * <i></i>"," * <!-- 选区结束 -->"," * </div>"," *"," * <script>"," *"," * var cloneRange = range.cloneRange();"," *"," * //output: '<a></a><i></i>'"," * console.log( cloneRange.cloneContents() );"," *"," * </script>"," * </body>"," * ```"," */"," cloneRange:function () {"," var me = this;"," return new Range(me.document).setStart(me.startContainer, me.startOffset).setEnd(me.endContainer, me.endOffset);"," },",""," /**"," * 闭合当前选区,向尾部闭合"," * @method collapse"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," * <body>"," *"," * <div id=\"test\">"," * <!-- 选区开始 -->"," * <a></a>"," * <i></i>"," * <!-- 选区结束 -->"," * </div>"," *"," * <script>"," *"," * //output: '<a></a><i></i>'"," * console.log( range.cloneContents() );"," * //output: 1"," * console.log( range.startOffset );"," *"," * range.collapse();"," *"," * //output: ''"," * console.log( range.cloneContents() );"," * //output: 3"," * console.log( range.startOffset );"," *"," * </script>"," * </body>"," * ```"," */",""," /**"," * 闭合当前选区,根据给定的toStart参数项决定是向尾部闭合还是向前闭合,"," * 如果toStart的值为true,则闭合到首部, 反之,则闭合到尾部"," * @method collapse"," * @param { Boolean } toStart 是否向前闭合选区"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," * <body>"," *"," * <div id=\"test\">"," * <!-- 选区开始 -->"," * <a></a>"," * <i></i>"," * <!-- 选区结束 -->"," * </div>"," *"," * <script>"," *"," * //output: '<a></a><i></i>'"," * console.log( range.cloneContents() );"," * //output: 1"," * console.log( range.startOffset );"," *"," * range.collapse();"," *"," * //output: ''"," * console.log( range.cloneContents() );"," * //output: 3"," * console.log( range.startOffset );"," *"," * </script>"," * </body>"," * ```"," */"," collapse:function (toStart) {"," var me = this;"," if (toStart) {"," me.endContainer = me.startContainer;"," me.endOffset = me.startOffset;"," } else {"," me.startContainer = me.endContainer;"," me.startOffset = me.endOffset;"," }"," me.collapsed = true;"," return me;"," },",""," /*"," * 调整range的边界,使其\"收缩\"到最小的位置"," * @name shrinkBoundary"," * @grammar range.shrinkBoundary() => Range //range开始位置和结束位置都调整,参见<code><a href=\"#adjustmentboundary\">adjustmentBoundary</a></code>"," * @grammar range.shrinkBoundary(true) => Range //仅调整开始位置,忽略结束位置"," * @example"," * <b>xx[</b>xxxxx] ==> <b>xx</b>[xxxxx]"," * <b>x[xx</b><i>]xxx</i> ==> <b>x[xx]</b><i>xxx</i>"," * [<b><i>xxxx</i>xxxxxxx</b>] ==> <b><i>[xxxx</i>xxxxxxx]</b>"," */"," /**"," * 调整range的开始位置和结束位置,使其\"收缩\"到最小的位置"," * @method shrinkBoundary"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," * <body>"," *"," * <div id=\"test\">"," * <!-- 选区开始 -->"," * <a></a>"," * <i></i>"," * <!-- 选区结束 -->"," * </div>"," *"," * <script>"," *"," * //output: '<a></a><i></i>'"," * console.log( range.cloneContents() );"," * //output: 1"," * console.log( range.startOffset );"," *"," * range.collapse();"," *"," * //output: ''"," * console.log( range.cloneContents() );"," * //output: 3"," * console.log( range.startOffset );"," *"," * </script>"," * </body>"," * ```"," */"," shrinkBoundary:function (ignoreEnd) {"," var me = this, child,"," collapsed = me.collapsed;"," function check(node){"," return node.nodeType == 1 && !domUtils.isBookmarkNode(node) && !dtd.$empty[node.tagName] && !dtd.$nonChild[node.tagName]"," }"," while (me.startContainer.nodeType == 1 //是element"," && (child = me.startContainer.childNodes[me.startOffset]) //子节点也是element"," && check(child)) {"," me.setStart(child, 0);"," }"," if (collapsed) {"," return me.collapse(true);"," }"," if (!ignoreEnd) {"," while (me.endContainer.nodeType == 1//是element"," && me.endOffset > 0 //如果是空元素就退出 endOffset=0那么endOffst-1为负值,childNodes[endOffset]报错"," && (child = me.endContainer.childNodes[me.endOffset - 1]) //子节点也是element"," && check(child)) {"," me.setEnd(child, child.childNodes.length);"," }"," }"," return me;"," },",""," /**"," * 获取当前选区所包含的所有节点的公共祖先节点,"," * 返回的公共祖先节点一定不是range自身的容器节点, 但有可能是一个文本节点"," * @method getCommonAncestor"," * @return { Node } 当前range对象内所有节点的公共祖先节点"," * @example"," * ```html"," * <body>"," *"," * <div id=\"test\">"," * <!-- 选区开始 -->"," * <a></a>"," * <i></i>"," * <!-- 选区结束 -->"," * </div>"," *"," * <script>"," *"," * var ancestorNode = range.getCommonAncestor();"," *"," * //output: 'DIV'"," * console.log( ancestorNode.tagName );"," *"," * </script>"," *"," * </body>"," * ```"," * @example"," * ```html"," * <body>"," *"," * <div id=\"test\">"," * <span>"," * <!-- 选区开始 -->"," * <a></a>"," * </span>"," * <span>"," * <i></i>"," * <!-- 选区结束 -->"," * </span>"," * </div>"," *"," * <script>"," *"," * var ancestorNode = range.getCommonAncestor();"," *"," * //output: 'DIV'"," * console.log( ancestorNode.tagName );"," *"," * </script>"," *"," * </body>"," * ```"," */",""," /**"," * 获取当前选区所包含的所有节点的公共祖先节点, 可以根据给定的参数 includeSelf 决定获取到"," * 的公共祖先节点是否可以是当前选区的startContainer或endContainer节点, 如果 includeSelf"," * 的取值为true, 则返回的节点可以是自身的容器节点, 否则, 则不能是容器节点"," * @method getCommonAncestor"," * @param { Boolean } includeSelf 是否允许获取到的公共祖先节点是当前range对象的容器节点"," * @return { Node } 当前range对象内所有节点的公共祖先节点"," * @see UE.dom.Range:getCommonAncestor()"," * @example"," * ```html"," * <body>"," *"," * <!-- 选区开始 -->"," * <div id=\"test\">"," * <a></a>"," * <i></i>"," * </div>"," * <!-- 选区结束 -->"," *"," * <script>"," *"," * var ancestorNode = range.getCommonAncestor( true );"," *"," * //output: 'DIV'"," * console.log( ancestorNode.tagName );"," *"," * ancestorNode = range.getCommonAncestor( false );"," *"," * //output: BODY"," * console.log( ancestorNode.tagName );"," *"," * </script>"," *"," * </body>"," * ```"," */",""," /**"," * 获取当前选区所包含的所有节点的公共祖先节点, 可以根据给定的参数 includeSelf 决定获取到"," * 的公共祖先节点是否可以是当前选区的startContainer或endContainer节点, 如果 includeSelf"," * 的取值为true, 则返回的节点可以是自身的容器节点, 否则, 则不能是容器节点; 同时可以根据"," * ignoreTextNode 参数的取值决定是否忽略类型为文本节点的祖先节点。"," * @method getCommonAncestor"," * @param { Boolean } includeSelf 是否允许获取到的公共祖先节点是当前range对象的容器节点"," * @param { Boolean } ignoreTextNode 获取祖先节点的过程中是否忽略类型为文本节点的祖先节点"," * @return { Node } 当前range对象内所有节点的公共祖先节点"," * @see UE.dom.Range:getCommonAncestor()"," * @see UE.dom.Range:getCommonAncestor(Boolean)"," * @example"," * ```html"," * <body>"," *"," * <div id=\"test\">"," * <span>"," * 我是一个"," * <!-- 选区开始 -->"," * 文本"," * <!-- 选区结束 -->"," * 内容"," * </span>"," * </div>"," *"," * <script>"," *"," * var ancestorNode = range.getCommonAncestor( true, false );"," *"," * //output: 3"," * console.log( ancestorNode.nodeType );"," * //output: SPAN"," * console.log( ancestorNode.parentNode.tagName );"," *"," * ancestorNode = range.getCommonAncestor( true, true );"," *"," * //output: 1"," * console.log( ancestorNode.nodeType );"," * //output: SPAN"," * console.log( ancestorNode.tagName );"," *"," * </script>"," *"," * </body>"," * ```"," */"," getCommonAncestor:function (includeSelf, ignoreTextNode) {"," var me = this,"," start = me.startContainer,"," end = me.endContainer;"," if (start === end) {"," if (includeSelf && selectOneNode(this)) {"," start = start.childNodes[me.startOffset];"," if(start.nodeType == 1)"," return start;"," }"," //只有在上来就相等的情况下才会出现是文本的情况"," return ignoreTextNode && start.nodeType == 3 ? start.parentNode : start;"," }"," return domUtils.getCommonAncestor(start, end);"," },",""," /**"," * 调整当前Range的开始和结束边界容器,如果是容器节点是文本节点,就调整到包含该文本节点的父节点上"," * @method trimBoundary"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," *"," * <body>"," * <div>"," * 你好"," * <!-- 选区开始 -->"," * 我是一段文本, 我旁边的注释内容其实是不存在的,仅仅是为了描述一下选区的边界"," * <!-- 选区结束 -->"," * 到这里文本结束了"," * </div>"," *"," * <script>"," *"," * //output: 3"," * console.log( range.startContainer.nodeType );"," * //output: 3"," * console.log( range.endContainer.nodeType );"," *"," * range.trimBoundary();"," *"," * //output: 1"," * console.log( range.startContainer.nodeType );"," * //output: 1"," * console.log( range.endContainer.nodeType );"," *"," * </script>"," * </body>"," *"," * ```"," */",""," /**"," * 调整当前Range的开始和结束边界容器,如果是容器节点是文本节点,就调整到包含该文本节点的父节点上,"," * 可以根据 ignoreEnd 参数的值决定是否调整对结束边界的调整"," * @method trimBoundary"," * @param { Boolean } ignoreEnd 是否忽略对结束边界的调整"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," *"," * <body>"," * <div>"," * 你好"," * <!-- 选区开始 -->"," * 我是一段文本, 我旁边的注释内容其实是不存在的,仅仅是为了描述一下选区的边界"," * <!-- 选区结束 -->"," * 到这里文本结束了"," * </div>"," *"," * <script>"," *"," * //output: 3"," * console.log( range.startContainer.nodeType );"," * //output: 3"," * console.log( range.endContainer.nodeType );"," *"," * range.trimBoundary( true );"," *"," * //output: 1"," * console.log( range.startContainer.nodeType );"," * //output: 3"," * console.log( range.endContainer.nodeType );"," *"," * </script>"," * </body>"," *"," * ```"," */"," trimBoundary:function (ignoreEnd) {"," this.txtToElmBoundary();"," var start = this.startContainer,"," offset = this.startOffset,"," collapsed = this.collapsed,"," end = this.endContainer;"," if (start.nodeType == 3) {"," if (offset == 0) {"," this.setStartBefore(start);"," } else {"," if (offset >= start.nodeValue.length) {"," this.setStartAfter(start);"," } else {"," var textNode = domUtils.split(start, offset);"," //跟新结束边界"," if (start === end) {"," this.setEnd(textNode, this.endOffset - offset);"," } else if (start.parentNode === end) {"," this.endOffset += 1;"," }"," this.setStartBefore(textNode);"," }"," }"," if (collapsed) {"," return this.collapse(true);"," }"," }"," if (!ignoreEnd) {"," offset = this.endOffset;"," end = this.endContainer;"," if (end.nodeType == 3) {"," if (offset == 0) {"," this.setEndBefore(end);"," } else {"," offset < end.nodeValue.length && domUtils.split(end, offset);"," this.setEndAfter(end);"," }"," }"," }"," return this;"," },",""," /**"," * 如果选区在文本的边界上,就扩展选区到文本的父节点上, 如果当前选区是闭合的, 则什么也不做"," * @method txtToElmBoundary"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," *"," * <body>"," * <div>"," * <!-- 选区开始 -->"," * 你好,我是一段文本, 我旁边的注释内容其实是不存在的,仅仅是为了描述一下选区的边界"," * <!-- 选区结束 -->"," * 到这里文本结束了"," * </div>"," *"," * <script>"," *"," * //output: 3"," * console.log( range.startContainer.nodeType );"," * //output: 3"," * console.log( range.endContainer.nodeType );"," *"," * range.txtToElmBoundary();"," *"," * //output: 1"," * console.log( range.startContainer.nodeType );"," * //output: 3"," * console.log( range.endContainer.nodeType );"," *"," * </script>"," * </body>"," *"," * ```"," * @example"," * ```html"," *"," * <body>"," * <div>"," * <!-- 选区开始 -->"," * 你好,我是一段文本, 我旁边的注释内容其实是不存在的,仅仅是为了描述一下选区的边界"," * 到这里文本结束了"," * <!-- 选区结束 -->"," * </div>"," *"," * <script>"," *"," * //output: 3"," * console.log( range.startContainer.nodeType );"," * //output: 3"," * console.log( range.endContainer.nodeType );"," *"," * range.txtToElmBoundary();"," *"," * //output: 1"," * console.log( range.startContainer.nodeType );"," * //output: 1"," * console.log( range.endContainer.nodeType );"," *"," * </script>"," * </body>"," *"," * ```"," */",""," /**"," * 如果选区在文本的边界上,就扩展选区到文本的父节点上, 如果当前选区是闭合的, 则根据参数项"," * ignoreCollapsed 的值决定是否执行该调整"," * @method txtToElmBoundary"," * @param { Boolean } ignoreCollapsed 是否忽略选区的闭合状态, 如果该参数取值为true, 则"," * 不论选区是否闭合, 都会执行该操作, 反之, 则不会对闭合的选区执行该操作"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," *"," * <body>"," * <div>"," * 你好,我是一段文本, 我旁边的注释内容其实是不存在的,仅仅是为了描述一下选区的边界"," * <!-- 选区开始 --><!-- 选区结束 -->"," * 到这里文本结束了"," * </div>"," *"," * <script>"," *"," * //output: 3"," * console.log( range.startContainer.nodeType );"," * //output: 3"," * console.log( range.endContainer.nodeType );"," *"," * range.txtToElmBoundary( true );"," *"," * //output: 1"," * console.log( range.startContainer.nodeType );"," * //output: 1"," * console.log( range.endContainer.nodeType );"," *"," * </script>"," * </body>"," *"," * ```"," * @example"," * ```html"," *"," * <body>"," * <div>"," * 你好,我是一段文本, 我旁边的注释内容其实是不存在的,仅仅是为了描述一下选区的边界"," * <!-- 选区开始 --><!-- 选区结束 -->"," * 到这里文本结束了"," * </div>"," *"," * <script>"," *"," * //output: 3"," * console.log( range.startContainer.nodeType );"," * //output: 3"," * console.log( range.endContainer.nodeType );"," *"," * range.txtToElmBoundary( false );"," *"," * //output: 3"," * console.log( range.startContainer.nodeType );"," * //output: 3"," * console.log( range.endContainer.nodeType );"," *"," * </script>"," * </body>"," *"," * ```"," */"," txtToElmBoundary:function (ignoreCollapsed) {"," function adjust(r, c) {"," var container = r[c + 'Container'],"," offset = r[c + 'Offset'];"," if (container.nodeType == 3) {"," if (!offset) {"," r['set' + c.replace(/(\\w)/, function (a) {"," return a.toUpperCase();"," }) + 'Before'](container);"," } else if (offset >= container.nodeValue.length) {"," r['set' + c.replace(/(\\w)/, function (a) {"," return a.toUpperCase();"," }) + 'After' ](container);"," }"," }"," }",""," if (ignoreCollapsed || !this.collapsed) {"," adjust(this, 'start');"," adjust(this, 'end');"," }"," return this;"," },",""," /**"," * 在当前选区的开始位置后紧临着插入一个节点,新插入的节点会被该range包含"," * @method insertNode"," * @param { Node } 需要插入的节点"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," * <body>"," *"," * <div id=\"test\">"," * <!-- 选区开始 -->"," * <span></span>"," * <i></i>"," * <!-- 选区结束 -->"," * </div>"," *"," * <script>"," *"," *"," * var newNode = document.createElement('div');"," * newNode.id = 'ueditor';"," *"," * //output: <span></span><i></i>"," * console.log( range.cloneContents() );"," *"," * range.insertNode( newNode );"," *"," * //output: <div id=\"ueditor\"></div><span></span><i></i>"," * console.log( range.cloneContents() );"," *"," * </script>"," *"," * </body>"," * ```"," */"," insertNode:function (node) {"," var first = node, length = 1;"," if (node.nodeType == 11) {"," first = node.firstChild;"," length = node.childNodes.length;"," }"," this.trimBoundary(true);"," var start = this.startContainer,"," offset = this.startOffset;"," var nextNode = start.childNodes[ offset ];"," if (nextNode) {"," start.insertBefore(node, nextNode);"," } else {"," start.appendChild(node);"," }"," if (first.parentNode === this.endContainer) {"," this.endOffset = this.endOffset + length;"," }"," return this.setStartBefore(first);"," },",""," /**"," * 闭合选区到当前选区的开始位置, 并且定位光标到闭合后的位置"," * @method setCursor"," * @return { UE.dom.Range } 当前range对象"," * @see UE.dom.Range:collapse()"," */",""," /**"," * 闭合选区, 并且定位光标到闭合后的位置, 可以根据参数toEnd的值控制选区是向前闭合还是向后闭合"," * @method setCursor"," * @param { Boolean } toEnd 是否向后闭合, 如果为true, 则闭合选区时, 将向结束容器方向闭合,"," * 反之,则向开始容器方向闭合"," * @return { UE.dom.Range } 当前range对象"," * @see UE.dom.Range:collapse(Boolean)"," */"," setCursor:function (toEnd, noFillData) {"," return this.collapse(!toEnd).select(noFillData);"," },",""," /**"," * 创建当前range的一个书签,记录下当前range的位置,方便当dom树改变时,还能找回原来的选区位置"," * @method createBookmark"," * @param { Boolean } serialize 控制返回的标记位置是对当前位置的引用还是ID,如果该值为true,则"," * 返回标记位置的ID, 反之则返回标记位置的引用"," * @return { KeyValueMap } 返回一个书签记录键值对, 其包含的key有: start => 开始标记的ID或者引用,"," * end => 结束标记的ID或引用, id => 当前标记的类型, 如果为true,则表示"," * 返回的记录的类型为ID, 反之则为引用"," */"," createBookmark:function (serialize, same) {"," var endNode,"," startNode = this.document.createElement('span');"," startNode.style.cssText = 'display:none;line-height:0px;';"," startNode.appendChild(this.document.createTextNode('\\u200D'));"," startNode.id = '_baidu_bookmark_start_' + (same ? '' : guid++);",""," if (!this.collapsed) {"," endNode = startNode.cloneNode(true);"," endNode.id = '_baidu_bookmark_end_' + (same ? '' : guid++);"," }"," this.insertNode(startNode);"," if (endNode) {"," this.collapse().insertNode(endNode).setEndBefore(endNode);"," }"," this.setStartAfter(startNode);"," return {"," start:serialize ? startNode.id : startNode,"," end:endNode ? serialize ? endNode.id : endNode : null,"," id:serialize"," }"," },",""," /**"," * 调整当前range的边界到书签位置,并删除该书签对象所标记的位置内的节点"," * @method moveToBookmark"," * @param { BookMark } createBookmark所创建的标签对象"," * @return { UE.dom.Range } 当前range对象"," * @see UE.dom.Range:createBookmark(Boolean)"," */"," moveToBookmark:function (bookmark) {"," var start = bookmark.id ? this.document.getElementById(bookmark.start) : bookmark.start,"," end = bookmark.end && bookmark.id ? this.document.getElementById(bookmark.end) : bookmark.end;"," this.setStartBefore(start);"," domUtils.remove(start);"," if (end) {"," this.setEndBefore(end);"," domUtils.remove(end);"," } else {"," this.collapse(true);"," }"," return this;"," },",""," /**"," * 调整range的边界,使其\"放大\"到最近的父节点"," * @method enlarge"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," *"," * <body>"," * <div>"," * <span>"," * <b>a<!-- 选区开始 -->b</b>"," * cdef"," * <!-- 选区结束 -->"," * </span>"," * </div>"," *"," * <script>"," *"," * range.enlarge();"," *"," * //output: <span><b>ab</b>cdef</span>"," * console.log( enlarge.cloneContents() );"," *"," * </script>"," * </body>"," * ```"," */",""," /**"," * 调整range的边界,使其\"放大\"到最近的父节点,根据参数 toBlock 的取值, 可以"," * 要求扩大之后的父节点是block节点"," * @method enlarge"," * @param { Boolean } toBlock 是否要求扩大之后的父节点必须是block节点"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," *"," * <body>"," * <div>"," * <span>"," * <b>a<!-- 选区开始 -->b</b>"," * cdef"," * <!-- 选区结束 -->"," * </span>"," * </div>"," *"," * <script>"," *"," * range.enlarge( true );"," *"," * //output: <div><span><b>ab</b>cdef</span></div>"," * console.log( enlarge.cloneContents() );"," *"," * </script>"," * </body>"," * ```"," */"," enlarge:function (toBlock, stopFn) {"," var isBody = domUtils.isBody,"," pre, node, tmp = this.document.createTextNode('');"," if (toBlock) {"," node = this.startContainer;"," if (node.nodeType == 1) {"," if (node.childNodes[this.startOffset]) {"," pre = node = node.childNodes[this.startOffset]"," } else {"," node.appendChild(tmp);"," pre = node = tmp;"," }"," } else {"," pre = node;"," }"," while (1) {"," if (domUtils.isBlockElm(node)) {"," node = pre;"," while ((pre = node.previousSibling) && !domUtils.isBlockElm(pre)) {"," node = pre;"," }"," this.setStartBefore(node);"," break;"," }"," pre = node;"," node = node.parentNode;"," }"," node = this.endContainer;"," if (node.nodeType == 1) {"," if (pre = node.childNodes[this.endOffset]) {"," node.insertBefore(tmp, pre);"," } else {"," node.appendChild(tmp);"," }"," pre = node = tmp;"," } else {"," pre = node;"," }"," while (1) {"," if (domUtils.isBlockElm(node)) {"," node = pre;"," while ((pre = node.nextSibling) && !domUtils.isBlockElm(pre)) {"," node = pre;"," }"," this.setEndAfter(node);"," break;"," }"," pre = node;"," node = node.parentNode;"," }"," if (tmp.parentNode === this.endContainer) {"," this.endOffset--;"," }"," domUtils.remove(tmp);"," }",""," // 扩展边界到最大"," if (!this.collapsed) {"," while (this.startOffset == 0) {"," if (stopFn && stopFn(this.startContainer)) {"," break;"," }"," if (isBody(this.startContainer)) {"," break;"," }"," this.setStartBefore(this.startContainer);"," }"," while (this.endOffset == (this.endContainer.nodeType == 1 ? this.endContainer.childNodes.length : this.endContainer.nodeValue.length)) {"," if (stopFn && stopFn(this.endContainer)) {"," break;"," }"," if (isBody(this.endContainer)) {"," break;"," }"," this.setEndAfter(this.endContainer);"," }"," }"," return this;"," },",""," /**"," * 调整Range的边界,使其\"缩小\"到最合适的位置"," * @method adjustmentBoundary"," * @return { UE.dom.Range } 当前range对象"," * @see UE.dom.Range:shrinkBoundary()"," */"," adjustmentBoundary:function () {"," if (!this.collapsed) {"," while (!domUtils.isBody(this.startContainer) &&"," this.startOffset == this.startContainer[this.startContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length &&"," this.startContainer[this.startContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length"," ) {",""," this.setStartAfter(this.startContainer);"," }"," while (!domUtils.isBody(this.endContainer) && !this.endOffset &&"," this.endContainer[this.endContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length"," ) {"," this.setEndBefore(this.endContainer);"," }"," }"," return this;"," },"," /*"," * 给range选区中的内容添加给定的标签,主要用于inline标签"," * @name applyInlineStyle"," * @grammar range.applyInlineStyle(tagName) => Range //tagName为需要添加的样式标签名"," * @grammar range.applyInlineStyle(tagName,attrs) => Range //attrs为属性json对象"," * @desc"," * <code type=\"html\"><p>xxxx[xxxx]x</p> ==> range.applyInlineStyle(\"strong\") ==> <p>xxxx[<strong>xxxx</strong>]x</p>"," * <p>xx[dd<strong>yyyy</strong>]x</p> ==> range.applyInlineStyle(\"strong\") ==> <p>xx[<strong>ddyyyy</strong>]x</p>"," * <p>xxxx[xxxx]x</p> ==> range.applyInlineStyle(\"strong\",{\"style\":\"font-size:12px\"}) ==> <p>xxxx[<strong style=\"font-size:12px\">xxxx</strong>]x</p></code>"," */"," applyInlineStyle:function (tagName, attrs, list) {"," if (this.collapsed)return this;"," this.trimBoundary().enlarge(false,"," function (node) {"," return node.nodeType == 1 && domUtils.isBlockElm(node)"," }).adjustmentBoundary();"," var bookmark = this.createBookmark(),"," end = bookmark.end,"," filterFn = function (node) {"," return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' : !domUtils.isWhitespace(node);"," },"," current = domUtils.getNextDomNode(bookmark.start, false, filterFn),"," node,"," pre,"," range = this.cloneRange();"," while (current && (domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING)) {"," if (current.nodeType == 3 || dtd[tagName][current.tagName]) {"," range.setStartBefore(current);"," node = current;"," while (node && (node.nodeType == 3 || dtd[tagName][node.tagName]) && node !== end) {"," pre = node;"," node = domUtils.getNextDomNode(node, node.nodeType == 1, null, function (parent) {"," return dtd[tagName][parent.tagName];"," });"," }"," var frag = range.setEndAfter(pre).extractContents(), elm;"," if (list && list.length > 0) {"," var level, top;"," top = level = list[0].cloneNode(false);"," for (var i = 1, ci; ci = list[i++];) {"," level.appendChild(ci.cloneNode(false));"," level = level.firstChild;"," }"," elm = level;"," } else {"," elm = range.document.createElement(tagName);"," }"," if (attrs) {"," domUtils.setAttributes(elm, attrs);"," }"," elm.appendChild(frag);"," range.insertNode(list ? top : elm);"," //处理下滑线在a上的情况"," var aNode;"," if (tagName == 'span' && attrs.style && /text\\-decoration/.test(attrs.style) && (aNode = domUtils.findParentByTagName(elm, 'a', true))) {"," domUtils.setAttributes(aNode, attrs);"," domUtils.remove(elm, true);"," elm = aNode;"," } else {"," domUtils.mergeSibling(elm);"," domUtils.clearEmptySibling(elm);"," }"," //去除子节点相同的"," domUtils.mergeChild(elm, attrs);"," current = domUtils.getNextDomNode(elm, false, filterFn);"," domUtils.mergeToParent(elm);"," if (node === end) {"," break;"," }"," } else {"," current = domUtils.getNextDomNode(current, true, filterFn);"," }"," }"," return this.moveToBookmark(bookmark);"," },"," /*"," * 对当前range选中的节点,去掉给定的标签节点,但标签中的内容保留,主要用于处理inline元素"," * @name removeInlineStyle"," * @grammar range.removeInlineStyle(tagNames) => Range //tagNames 为需要去掉的样式标签名,支持\"b\"或者[\"b\",\"i\",\"u\"]"," * @desc"," * <code type=\"html\">xx[x<span>xxx<em>yyy</em>zz]z</span> => range.removeInlineStyle([\"em\"]) => xx[x<span>xxxyyyzz]z</span></code>"," */"," removeInlineStyle:function (tagNames) {"," if (this.collapsed)return this;"," tagNames = utils.isArray(tagNames) ? tagNames : [tagNames];"," this.shrinkBoundary().adjustmentBoundary();"," var start = this.startContainer, end = this.endContainer;"," while (1) {"," if (start.nodeType == 1) {"," if (utils.indexOf(tagNames, start.tagName.toLowerCase()) > -1) {"," break;"," }"," if (start.tagName.toLowerCase() == 'body') {"," start = null;"," break;"," }"," }"," start = start.parentNode;"," }"," while (1) {"," if (end.nodeType == 1) {"," if (utils.indexOf(tagNames, end.tagName.toLowerCase()) > -1) {"," break;"," }"," if (end.tagName.toLowerCase() == 'body') {"," end = null;"," break;"," }"," }"," end = end.parentNode;"," }"," var bookmark = this.createBookmark(),"," frag,"," tmpRange;"," if (start) {"," tmpRange = this.cloneRange().setEndBefore(bookmark.start).setStartBefore(start);"," frag = tmpRange.extractContents();"," tmpRange.insertNode(frag);"," domUtils.clearEmptySibling(start, true);"," start.parentNode.insertBefore(bookmark.start, start);"," }"," if (end) {"," tmpRange = this.cloneRange().setStartAfter(bookmark.end).setEndAfter(end);"," frag = tmpRange.extractContents();"," tmpRange.insertNode(frag);"," domUtils.clearEmptySibling(end, false, true);"," end.parentNode.insertBefore(bookmark.end, end.nextSibling);"," }"," var current = domUtils.getNextDomNode(bookmark.start, false, function (node) {"," return node.nodeType == 1;"," }), next;"," while (current && current !== bookmark.end) {"," next = domUtils.getNextDomNode(current, true, function (node) {"," return node.nodeType == 1;"," });"," if (utils.indexOf(tagNames, current.tagName.toLowerCase()) > -1) {"," domUtils.remove(current, true);"," }"," current = next;"," }"," return this.moveToBookmark(bookmark);"," },",""," /**"," * 获取当前选区中的首个自闭合的节点"," * @method getClosedNode"," * @return { Node | NULL } 如果在当前选区中存在自闭合的节点, 则返回该节点, 否则返回NULL"," * @example"," * ```html"," * <body>"," * <div>"," * <!-- 选区开始 -->"," * <a></a>"," * <span><img></span>"," * <i></i>"," * <!-- 选区结束 -->"," * </div>"," *"," * <script>"," *"," * var node = range.getCloseNode();"," *"," * //output: IMG"," * console.log( node.tagName );"," *"," * </script>"," * </body>"," * ```"," */"," getClosedNode:function () {"," var node;"," if (!this.collapsed) {"," var range = this.cloneRange().adjustmentBoundary().shrinkBoundary();"," if (selectOneNode(range)) {"," var child = range.startContainer.childNodes[range.startOffset];"," if (child && child.nodeType == 1 && (dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName])) {"," node = child;"," }"," }"," }"," return node;"," },",""," /**"," * 选中当前选区"," * @method select"," * @return { UE.dom.Range } 返回当前Range对象"," */"," select:browser.ie ? function (noFillData, textRange) {"," var nativeRange;"," if (!this.collapsed)"," this.shrinkBoundary();"," var node = this.getClosedNode();"," if (node && !textRange) {"," try {"," nativeRange = this.document.body.createControlRange();"," nativeRange.addElement(node);"," nativeRange.select();"," } catch (e) {}"," return this;"," }"," var bookmark = this.createBookmark(),"," start = bookmark.start,"," end;"," nativeRange = this.document.body.createTextRange();"," nativeRange.moveToElementText(start);"," nativeRange.moveStart('character', 1);"," if (!this.collapsed) {"," var nativeRangeEnd = this.document.body.createTextRange();"," end = bookmark.end;"," nativeRangeEnd.moveToElementText(end);"," nativeRange.setEndPoint('EndToEnd', nativeRangeEnd);"," } else {"," if (!noFillData && this.startContainer.nodeType != 3) {"," //使用<span>|x<span>固定住光标"," var tmpText = this.document.createTextNode(fillChar),"," tmp = this.document.createElement('span');"," tmp.appendChild(this.document.createTextNode(fillChar));"," start.parentNode.insertBefore(tmp, start);"," start.parentNode.insertBefore(tmpText, start);"," //当点b,i,u时,不能清除i上边的b"," removeFillData(this.document, tmpText);"," fillData = tmpText;"," mergeSibling(tmp, 'previousSibling');"," mergeSibling(start, 'nextSibling');"," nativeRange.moveStart('character', -1);"," nativeRange.collapse(true);"," }"," }"," this.moveToBookmark(bookmark);"," tmp && domUtils.remove(tmp);"," //IE在隐藏状态下不支持range操作,catch一下"," try {"," nativeRange.select();"," } catch (e) {"," }"," return this;"," } : function (notInsertFillData) {"," function checkOffset(rng){",""," function check(node,offset,dir){"," if(node.nodeType == 3 && node.nodeValue.length < offset){"," rng[dir + 'Offset'] = node.nodeValue.length"," }"," }"," check(rng.startContainer,rng.startOffset,'start');"," check(rng.endContainer,rng.endOffset,'end');"," }"," var win = domUtils.getWindow(this.document),"," sel = win.getSelection(),"," txtNode;"," //FF下关闭自动长高时滚动条在关闭dialog时会跳"," //ff下如果不body.focus将不能定位闭合光标到编辑器内"," browser.gecko ? this.document.body.focus() : win.focus();"," if (sel) {"," sel.removeAllRanges();"," // trace:870 chrome/safari后边是br对于闭合得range不能定位 所以去掉了判断"," // this.startContainer.nodeType != 3 &&! ((child = this.startContainer.childNodes[this.startOffset]) && child.nodeType == 1 && child.tagName == 'BR'"," if (this.collapsed && !notInsertFillData) {","// //opear如果没有节点接着,原生的不能够定位,不能在body的第一级插入空白节点","// if (notInsertFillData && browser.opera && !domUtils.isBody(this.startContainer) && this.startContainer.nodeType == 1) {","// var tmp = this.document.createTextNode('');","// this.insertNode(tmp).setStart(tmp, 0).collapse(true);","// }","//"," //处理光标落在文本节点的情况"," //处理以下的情况"," //<b>|xxxx</b>"," //<b>xxxx</b>|xxxx"," //xxxx<b>|</b>"," var start = this.startContainer,child = start;"," if(start.nodeType == 1){"," child = start.childNodes[this.startOffset];",""," }"," if( !(start.nodeType == 3 && this.startOffset) &&"," (child ?"," (!child.previousSibling || child.previousSibling.nodeType != 3)"," :"," (!start.lastChild || start.lastChild.nodeType != 3)"," )"," ){"," txtNode = this.document.createTextNode(fillChar);"," //跟着前边走"," this.insertNode(txtNode);"," removeFillData(this.document, txtNode);"," mergeSibling(txtNode, 'previousSibling');"," mergeSibling(txtNode, 'nextSibling');"," fillData = txtNode;"," this.setStart(txtNode, browser.webkit ? 1 : 0).collapse(true);"," }"," }"," var nativeRange = this.document.createRange();"," if(this.collapsed && browser.opera && this.startContainer.nodeType == 1){"," var child = this.startContainer.childNodes[this.startOffset];"," if(!child){"," //往前靠拢"," child = this.startContainer.lastChild;"," if( child && domUtils.isBr(child)){"," this.setStartBefore(child).collapse(true);"," }"," }else{"," //向后靠拢"," while(child && domUtils.isBlockElm(child)){"," if(child.nodeType == 1 && child.childNodes[0]){"," child = child.childNodes[0]"," }else{"," break;"," }"," }"," child && this.setStartBefore(child).collapse(true)"," }",""," }"," //是createAddress最后一位算的不准,现在这里进行微调"," checkOffset(this);"," nativeRange.setStart(this.startContainer, this.startOffset);"," nativeRange.setEnd(this.endContainer, this.endOffset);"," sel.addRange(nativeRange);"," }"," return this;"," },",""," /**"," * 滚动到当前range开始的位置"," * @method scrollToView"," * @param { Window } win 当前range对象所属的window对象"," * @return { UE.dom.Range } 当前Range对象"," */",""," /**"," * 滚动到距离当前range开始位置 offset 的位置处"," * @method scrollToView"," * @param { Window } win 当前range对象所属的window对象"," * @param { Number } offset 距离range开始位置处的偏移量, 如果为正数, 则向下偏移, 反之, 则向上偏移"," * @return { UE.dom.Range } 当前Range对象"," */"," scrollToView:function (win, offset) {"," win = win ? window : domUtils.getWindow(this.document);"," var me = this,"," span = me.document.createElement('span');"," //trace:717"," span.innerHTML = '&nbsp;';"," me.cloneRange().insertNode(span);"," domUtils.scrollToView(span, win, offset);"," domUtils.remove(span);"," return me;"," },"," /**"," * 判断当前选区内容是否占位符"," * @method inFillChar"," * @return { Boolean } 如果是占位符返回true,否则返回false"," */"," inFillChar : function(){"," var start = this.startContainer;"," if(this.collapsed && start.nodeType == 3"," && start.nodeValue.replace(new RegExp('^' + domUtils.fillChar),'').length + 1 == start.nodeValue.length"," ){"," return true;"," }"," return false;"," },",""," /**"," * 保存"," * @method createAddress"," * @return { Boolean } 返回开始和结束的位置"," * @example"," * ```html"," * <body>"," * <p>"," * aaaa"," * <em>"," * <!-- 选区开始 -->"," * bbbb"," * <!-- 选区结束 -->"," * </em>"," * </p>"," *"," * <script>"," * //output: {startAddress:[0,1,0,0],endAddress:[0,1,0,4]}"," * console.log( range.createAddress() );"," * </script>"," * </body>"," * ```"," */"," createAddress : function(ignoreEnd,ignoreTxt){"," var addr = {},me = this;",""," function getAddress(isStart){"," var node = isStart ? me.startContainer : me.endContainer;"," var parents = domUtils.findParents(node,true,function(node){return !domUtils.isBody(node)}),"," addrs = [];"," for(var i = 0,ci;ci = parents[i++];){"," addrs.push(domUtils.getNodeIndex(ci,ignoreTxt));"," }"," var firstIndex = 0;",""," if(ignoreTxt){"," if(node.nodeType == 3){"," var tmpNode = node.previousSibling;"," while(tmpNode && tmpNode.nodeType == 3){"," firstIndex += tmpNode.nodeValue.replace(fillCharReg,'').length;"," tmpNode = tmpNode.previousSibling;"," }"," firstIndex += (isStart ? me.startOffset : me.endOffset)// - (fillCharReg.test(node.nodeValue) ? 1 : 0 )"," }else{"," node = node.childNodes[ isStart ? me.startOffset : me.endOffset];"," if(node){"," firstIndex = domUtils.getNodeIndex(node,ignoreTxt);"," }else{"," node = isStart ? me.startContainer : me.endContainer;"," var first = node.firstChild;"," while(first){"," if(domUtils.isFillChar(first)){"," first = first.nextSibling;"," continue;"," }"," firstIndex++;"," if(first.nodeType == 3){"," while( first && first.nodeType == 3){"," first = first.nextSibling;"," }"," }else{"," first = first.nextSibling;"," }"," }"," }"," }",""," }else{"," firstIndex = isStart ? domUtils.isFillChar(node) ? 0 : me.startOffset : me.endOffset"," }"," if(firstIndex < 0){"," firstIndex = 0;"," }"," addrs.push(firstIndex);"," return addrs;"," }"," addr.startAddress = getAddress(true);"," if(!ignoreEnd){"," addr.endAddress = me.collapsed ? [].concat(addr.startAddress) : getAddress();"," }"," return addr;"," },"," /**"," * 保存"," * @method createAddress"," * @return { Boolean } 返回开始和结束的位置"," * @example"," * ```html"," * <body>"," * <p>"," * aaaa"," * <em>"," * <!-- 选区开始 -->"," * bbbb"," * <!-- 选区结束 -->"," * </em>"," * </p>"," *"," * <script>"," * var range = editor.selection.getRange();"," * range.moveToAddress({startAddress:[0,1,0,0],endAddress:[0,1,0,4]});"," * range.select();"," * //output: 'bbbb'"," * console.log(editor.selection.getText());"," * </script>"," * </body>"," * ```"," */"," moveToAddress : function(addr,ignoreEnd){"," var me = this;"," function getNode(address,isStart){"," var tmpNode = me.document.body,"," parentNode,offset;"," for(var i= 0,ci,l=address.length;i<l;i++){"," ci = address[i];"," parentNode = tmpNode;"," tmpNode = tmpNode.childNodes[ci];"," if(!tmpNode){"," offset = ci;"," break;"," }"," }"," if(isStart){"," if(tmpNode){"," me.setStartBefore(tmpNode)"," }else{"," me.setStart(parentNode,offset)"," }"," }else{"," if(tmpNode){"," me.setEndBefore(tmpNode)"," }else{"," me.setEnd(parentNode,offset)"," }"," }"," }"," getNode(addr.startAddress,true);"," !ignoreEnd && addr.endAddress && getNode(addr.endAddress);"," return me;"," },",""," /**"," * 判断给定的Range对象是否和当前Range对象表示的是同一个选区"," * @method equals"," * @param { UE.dom.Range } 需要判断的Range对象"," * @return { Boolean } 如果给定的Range对象与当前Range对象表示的是同一个选区, 则返回true, 否则返回false"," equals : function(rng){"," for(var p in this){"," if(this.hasOwnProperty(p)){"," if(this[p] !== rng[p])"," return false"," }"," }"," return true;",""," },",""," /**"," * 遍历range内的节点。每当遍历一个节点时, 都会执行参数项 doFn 指定的函数, 该函数的接受当前遍历的节点"," * 作为其参数。"," * @method traversal"," * @param { Function } doFn 对每个遍历的节点要执行的方法, 该方法接受当前遍历的节点作为其参数"," * @return { UE.dom.Range } 当前range对象"," * @example"," * ```html"," *"," * <body>"," *"," * <!-- 选区开始 -->"," * <span></span>"," * <a></a>"," * <!-- 选区结束 -->"," * </body>"," *"," * <script>"," *"," * //output: <span></span><a></a>"," * console.log( range.cloneContents() );"," *"," * range.traversal( function ( node ) {"," *"," * if ( node.nodeType === 1 ) {"," * node.className = \"test\";"," * }"," *"," * } );"," *"," * //output: <span class=\"test\"></span><a class=\"test\"></a>"," * console.log( range.cloneContents() );"," *"," * </script>"," * ```"," */",""," /**"," * 遍历range内的节点。"," * 每当遍历一个节点时, 都会执行参数项 doFn 指定的函数, 该函数的接受当前遍历的节点"," * 作为其参数。"," * 可以通过参数项 filterFn 来指定一个过滤器, 只有符合该过滤器过滤规则的节点才会触"," * 发doFn函数的执行"," * @method traversal"," * @param { Function } doFn 对每个遍历的节点要执行的方法, 该方法接受当前遍历的节点作为其参数"," * @param { Function } filterFn 过滤器, 该函数接受当前遍历的节点作为参数, 如果该节点满足过滤"," * 规则, 请返回true, 该节点会触发doFn, 否则, 请返回false, 则该节点不"," * 会触发doFn。"," * @return { UE.dom.Range } 当前range对象"," * @see UE.dom.Range:traversal(Function)"," * @example"," * ```html"," *"," * <body>"," *"," * <!-- 选区开始 -->"," * <span></span>"," * <a></a>"," * <!-- 选区结束 -->"," * </body>"," *"," * <script>"," *"," * //output: <span></span><a></a>"," * console.log( range.cloneContents() );"," *"," * range.traversal( function ( node ) {"," *"," * node.className = \"test\";"," *"," * }, function ( node ) {"," * return node.nodeType === 1;"," * } );"," *"," * //output: <span class=\"test\"></span><a class=\"test\"></a>"," * console.log( range.cloneContents() );"," *"," * </script>"," * ```"," */"," traversal:function(doFn,filterFn){"," if (this.collapsed)"," return this;"," var bookmark = this.createBookmark(),"," end = bookmark.end,"," current = domUtils.getNextDomNode(bookmark.start, false, filterFn);"," while (current && current !== end && (domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING)) {"," var tmpNode = domUtils.getNextDomNode(current,false,filterFn);"," doFn(current);"," current = tmpNode;"," }"," return this.moveToBookmark(bookmark);"," }"," };","})();"]; +_$jscoverage['core/Range.js'][22]++; +(function () { + _$jscoverage['core/Range.js'][23]++; + var guid = 0, fillChar = domUtils.fillChar, fillData; + _$jscoverage['core/Range.js'][31]++; + function updateCollapse(range) { + _$jscoverage['core/Range.js'][32]++; + range.collapsed = (range.startContainer && range.endContainer && (range.startContainer === range.endContainer) && (range.startOffset == range.endOffset)); +} + _$jscoverage['core/Range.js'][38]++; + function selectOneNode(rng) { + _$jscoverage['core/Range.js'][39]++; + return ((! rng.collapsed) && (rng.startContainer.nodeType == 1) && (rng.startContainer === rng.endContainer) && ((rng.endOffset - rng.startOffset) == 1)); +} + _$jscoverage['core/Range.js'][41]++; + function setEndPoint(toStart, node, offset, range) { + _$jscoverage['core/Range.js'][43]++; + if (((node.nodeType == 1) && (dtd.$empty[node.tagName] || dtd.$nonChild[node.tagName]))) { + _$jscoverage['core/Range.js'][44]++; + offset = (domUtils.getNodeIndex(node) + (toStart? 0: 1)); + _$jscoverage['core/Range.js'][45]++; + node = node.parentNode; + } + _$jscoverage['core/Range.js'][47]++; + if (toStart) { + _$jscoverage['core/Range.js'][48]++; + range.startContainer = node; + _$jscoverage['core/Range.js'][49]++; + range.startOffset = offset; + _$jscoverage['core/Range.js'][50]++; + if ((! range.endContainer)) { + _$jscoverage['core/Range.js'][51]++; + range.collapse(true); + } + } + else { + _$jscoverage['core/Range.js'][54]++; + range.endContainer = node; + _$jscoverage['core/Range.js'][55]++; + range.endOffset = offset; + _$jscoverage['core/Range.js'][56]++; + if ((! range.startContainer)) { + _$jscoverage['core/Range.js'][57]++; + range.collapse(false); + } + } + _$jscoverage['core/Range.js'][60]++; + updateCollapse(range); + _$jscoverage['core/Range.js'][61]++; + return range; +} + _$jscoverage['core/Range.js'][64]++; + function execContentsAction(range, action) { + _$jscoverage['core/Range.js'][67]++; + var start = range.startContainer, end = range.endContainer, startOffset = range.startOffset, endOffset = range.endOffset, doc = range.document, frag = doc.createDocumentFragment(), tmpStart, tmpEnd; + _$jscoverage['core/Range.js'][74]++; + if ((start.nodeType == 1)) { + _$jscoverage['core/Range.js'][75]++; + start = (start.childNodes[startOffset] || (tmpStart = start.appendChild(doc.createTextNode("")))); + } + _$jscoverage['core/Range.js'][77]++; + if ((end.nodeType == 1)) { + _$jscoverage['core/Range.js'][78]++; + end = (end.childNodes[endOffset] || (tmpEnd = end.appendChild(doc.createTextNode("")))); + } + _$jscoverage['core/Range.js'][80]++; + if (((start === end) && (start.nodeType == 3))) { + _$jscoverage['core/Range.js'][81]++; + frag.appendChild(doc.createTextNode(start.substringData(startOffset, (endOffset - startOffset)))); + _$jscoverage['core/Range.js'][83]++; + if (action) { + _$jscoverage['core/Range.js'][84]++; + start.deleteData(startOffset, (endOffset - startOffset)); + _$jscoverage['core/Range.js'][85]++; + range.collapse(true); + } + _$jscoverage['core/Range.js'][87]++; + return frag; + } + _$jscoverage['core/Range.js'][89]++; + var current, currentLevel, clone = frag, startParents = domUtils.findParents(start, true), endParents = domUtils.findParents(end, true); + _$jscoverage['core/Range.js'][91]++; + for (var i = 0; (startParents[i] == endParents[i]);) { + _$jscoverage['core/Range.js'][92]++; + (i++); +} + _$jscoverage['core/Range.js'][94]++; + for (var j = i, si; (si = startParents[j]); (j++)) { + _$jscoverage['core/Range.js'][95]++; + current = si.nextSibling; + _$jscoverage['core/Range.js'][96]++; + if ((si == start)) { + _$jscoverage['core/Range.js'][97]++; + if ((! tmpStart)) { + _$jscoverage['core/Range.js'][98]++; + if ((range.startContainer.nodeType == 3)) { + _$jscoverage['core/Range.js'][99]++; + clone.appendChild(doc.createTextNode(start.nodeValue.slice(startOffset))); + _$jscoverage['core/Range.js'][101]++; + if (action) { + _$jscoverage['core/Range.js'][102]++; + start.deleteData(startOffset, (start.nodeValue.length - startOffset)); + } + } + else { + _$jscoverage['core/Range.js'][105]++; + clone.appendChild(((! action)? start.cloneNode(true): start)); + } + } + } + else { + _$jscoverage['core/Range.js'][109]++; + currentLevel = si.cloneNode(false); + _$jscoverage['core/Range.js'][110]++; + clone.appendChild(currentLevel); + } + _$jscoverage['core/Range.js'][112]++; + while (current) { + _$jscoverage['core/Range.js'][113]++; + if (((current === end) || (current === endParents[j]))) { + _$jscoverage['core/Range.js'][114]++; + break; + } + _$jscoverage['core/Range.js'][116]++; + si = current.nextSibling; + _$jscoverage['core/Range.js'][117]++; + clone.appendChild(((! action)? current.cloneNode(true): current)); + _$jscoverage['core/Range.js'][118]++; + current = si; +} + _$jscoverage['core/Range.js'][120]++; + clone = currentLevel; +} + _$jscoverage['core/Range.js'][122]++; + clone = frag; + _$jscoverage['core/Range.js'][123]++; + if ((! startParents[i])) { + _$jscoverage['core/Range.js'][124]++; + clone.appendChild(startParents[(i - 1)].cloneNode(false)); + _$jscoverage['core/Range.js'][125]++; + clone = clone.firstChild; + } + _$jscoverage['core/Range.js'][127]++; + for (var j = i, ei; (ei = endParents[j]); (j++)) { + _$jscoverage['core/Range.js'][128]++; + current = ei.previousSibling; + _$jscoverage['core/Range.js'][129]++; + if ((ei == end)) { + _$jscoverage['core/Range.js'][130]++; + if (((! tmpEnd) && (range.endContainer.nodeType == 3))) { + _$jscoverage['core/Range.js'][131]++; + clone.appendChild(doc.createTextNode(end.substringData(0, endOffset))); + _$jscoverage['core/Range.js'][133]++; + if (action) { + _$jscoverage['core/Range.js'][134]++; + end.deleteData(0, endOffset); + } + } + } + else { + _$jscoverage['core/Range.js'][138]++; + currentLevel = ei.cloneNode(false); + _$jscoverage['core/Range.js'][139]++; + clone.appendChild(currentLevel); + } + _$jscoverage['core/Range.js'][142]++; + if (((j != i) || (! startParents[i]))) { + _$jscoverage['core/Range.js'][143]++; + while (current) { + _$jscoverage['core/Range.js'][144]++; + if ((current === start)) { + _$jscoverage['core/Range.js'][145]++; + break; + } + _$jscoverage['core/Range.js'][147]++; + ei = current.previousSibling; + _$jscoverage['core/Range.js'][148]++; + clone.insertBefore(((! action)? current.cloneNode(true): current), clone.firstChild); + _$jscoverage['core/Range.js'][149]++; + current = ei; +} + } + _$jscoverage['core/Range.js'][152]++; + clone = currentLevel; +} + _$jscoverage['core/Range.js'][154]++; + if (action) { + _$jscoverage['core/Range.js'][155]++; + range.setStartBefore(((! endParents[i])? endParents[(i - 1)]: ((! startParents[i])? startParents[(i - 1)]: endParents[i]))).collapse(true); + } + _$jscoverage['core/Range.js'][157]++; + (tmpStart && domUtils.remove(tmpStart)); + _$jscoverage['core/Range.js'][158]++; + (tmpEnd && domUtils.remove(tmpEnd)); + _$jscoverage['core/Range.js'][159]++; + return frag; +} + _$jscoverage['core/Range.js'][193]++; + var Range = (dom.Range = (function (document) { + _$jscoverage['core/Range.js'][194]++; + var me = this; + _$jscoverage['core/Range.js'][195]++; + me.startContainer = (me.startOffset = (me.endContainer = (me.endOffset = null))); + _$jscoverage['core/Range.js'][199]++; + me.document = document; + _$jscoverage['core/Range.js'][200]++; + me.collapsed = true; +})); + _$jscoverage['core/Range.js'][208]++; + function removeFillData(doc, excludeNode) { + _$jscoverage['core/Range.js'][209]++; + try { + _$jscoverage['core/Range.js'][210]++; + if ((fillData && domUtils.inDoc(fillData, doc))) { + _$jscoverage['core/Range.js'][211]++; + if ((! fillData.nodeValue.replace(fillCharReg, "").length)) { + _$jscoverage['core/Range.js'][212]++; + var tmpNode = fillData.parentNode; + _$jscoverage['core/Range.js'][213]++; + domUtils.remove(fillData); + _$jscoverage['core/Range.js'][214]++; + while ((tmpNode && domUtils.isEmptyInlineElement(tmpNode) && (browser.safari? (! (domUtils.getPosition(tmpNode, excludeNode) & domUtils.POSITION_CONTAINS)): (! tmpNode.contains(excludeNode))))) { + _$jscoverage['core/Range.js'][218]++; + fillData = tmpNode.parentNode; + _$jscoverage['core/Range.js'][219]++; + domUtils.remove(tmpNode); + _$jscoverage['core/Range.js'][220]++; + tmpNode = fillData; +} + } + else { + _$jscoverage['core/Range.js'][223]++; + fillData.nodeValue = fillData.nodeValue.replace(fillCharReg, ""); + } + } + } + catch (e) { + } +} + _$jscoverage['core/Range.js'][235]++; + function mergeSibling(node, dir) { + _$jscoverage['core/Range.js'][236]++; + var tmpNode; + _$jscoverage['core/Range.js'][237]++; + node = node[dir]; + _$jscoverage['core/Range.js'][238]++; + while ((node && domUtils.isFillChar(node))) { + _$jscoverage['core/Range.js'][239]++; + tmpNode = node[dir]; + _$jscoverage['core/Range.js'][240]++; + domUtils.remove(node); + _$jscoverage['core/Range.js'][241]++; + node = tmpNode; +} +} + _$jscoverage['core/Range.js'][245]++; + Range.prototype = {cloneContents: (function () { + _$jscoverage['core/Range.js'][263]++; + return (this.collapsed? null: execContentsAction(this, 0)); +}), deleteContents: (function () { + _$jscoverage['core/Range.js'][294]++; + var txt; + _$jscoverage['core/Range.js'][295]++; + if ((! this.collapsed)) { + _$jscoverage['core/Range.js'][296]++; + execContentsAction(this, 1); + } + _$jscoverage['core/Range.js'][298]++; + if (browser.webkit) { + _$jscoverage['core/Range.js'][299]++; + txt = this.startContainer; + _$jscoverage['core/Range.js'][300]++; + if (((txt.nodeType == 3) && (! txt.nodeValue.length))) { + _$jscoverage['core/Range.js'][301]++; + this.setStartBefore(txt).collapse(true); + _$jscoverage['core/Range.js'][302]++; + domUtils.remove(txt); + } + } + _$jscoverage['core/Range.js'][305]++; + return this; +}), extractContents: (function () { + _$jscoverage['core/Range.js'][338]++; + return (this.collapsed? null: execContentsAction(this, 2)); +}), setStart: (function (node, offset) { + _$jscoverage['core/Range.js'][373]++; + return setEndPoint(true, node, offset, this); +}), setEnd: (function (node, offset) { + _$jscoverage['core/Range.js'][407]++; + return setEndPoint(false, node, offset, this); +}), setStartAfter: (function (node) { + _$jscoverage['core/Range.js'][440]++; + return this.setStart(node.parentNode, (domUtils.getNodeIndex(node) + 1)); +}), setStartBefore: (function (node) { + _$jscoverage['core/Range.js'][473]++; + return this.setStart(node.parentNode, domUtils.getNodeIndex(node)); +}), setEndAfter: (function (node) { + _$jscoverage['core/Range.js'][504]++; + return this.setEnd(node.parentNode, (domUtils.getNodeIndex(node) + 1)); +}), setEndBefore: (function (node) { + _$jscoverage['core/Range.js'][535]++; + return this.setEnd(node.parentNode, domUtils.getNodeIndex(node)); +}), setStartAtFirst: (function (node) { + _$jscoverage['core/Range.js'][568]++; + return this.setStart(node, 0); +}), setStartAtLast: (function (node) { + _$jscoverage['core/Range.js'][602]++; + return this.setStart(node, ((node.nodeType == 3)? node.nodeValue.length: node.childNodes.length)); +}), setEndAtFirst: (function (node) { + _$jscoverage['core/Range.js'][633]++; + return this.setEnd(node, 0); +}), setEndAtLast: (function (node) { + _$jscoverage['core/Range.js'][665]++; + return this.setEnd(node, ((node.nodeType == 3)? node.nodeValue.length: node.childNodes.length)); +}), selectNode: (function (node) { + _$jscoverage['core/Range.js'][691]++; + return this.setStartBefore(node).setEndAfter(node); +}), selectNodeContents: (function (node) { + _$jscoverage['core/Range.js'][720]++; + return this.setStart(node, 0).setEndAtLast(node); +}), cloneRange: (function () { + _$jscoverage['core/Range.js'][750]++; + var me = this; + _$jscoverage['core/Range.js'][751]++; + return new Range(me.document).setStart(me.startContainer, me.startOffset).setEnd(me.endContainer, me.endOffset); +}), collapse: (function (toStart) { + _$jscoverage['core/Range.js'][824]++; + var me = this; + _$jscoverage['core/Range.js'][825]++; + if (toStart) { + _$jscoverage['core/Range.js'][826]++; + me.endContainer = me.startContainer; + _$jscoverage['core/Range.js'][827]++; + me.endOffset = me.startOffset; + } + else { + _$jscoverage['core/Range.js'][829]++; + me.startContainer = me.endContainer; + _$jscoverage['core/Range.js'][830]++; + me.startOffset = me.endOffset; + } + _$jscoverage['core/Range.js'][832]++; + me.collapsed = true; + _$jscoverage['core/Range.js'][833]++; + return me; +}), shrinkBoundary: (function (ignoreEnd) { + _$jscoverage['core/Range.js'][880]++; + var me = this, child, collapsed = me.collapsed; + _$jscoverage['core/Range.js'][882]++; + function check(node) { + _$jscoverage['core/Range.js'][883]++; + return ((node.nodeType == 1) && (! domUtils.isBookmarkNode(node)) && (! dtd.$empty[node.tagName]) && (! dtd.$nonChild[node.tagName])); +} + _$jscoverage['core/Range.js'][885]++; + while (((me.startContainer.nodeType == 1) && (child = me.startContainer.childNodes[me.startOffset]) && check(child))) { + _$jscoverage['core/Range.js'][888]++; + me.setStart(child, 0); +} + _$jscoverage['core/Range.js'][890]++; + if (collapsed) { + _$jscoverage['core/Range.js'][891]++; + return me.collapse(true); + } + _$jscoverage['core/Range.js'][893]++; + if ((! ignoreEnd)) { + _$jscoverage['core/Range.js'][894]++; + while (((me.endContainer.nodeType == 1) && (me.endOffset > 0) && (child = me.endContainer.childNodes[(me.endOffset - 1)]) && check(child))) { + _$jscoverage['core/Range.js'][898]++; + me.setEnd(child, child.childNodes.length); +} + } + _$jscoverage['core/Range.js'][901]++; + return me; +}), getCommonAncestor: (function (includeSelf, ignoreTextNode) { + _$jscoverage['core/Range.js'][1043]++; + var me = this, start = me.startContainer, end = me.endContainer; + _$jscoverage['core/Range.js'][1046]++; + if ((start === end)) { + _$jscoverage['core/Range.js'][1047]++; + if ((includeSelf && selectOneNode(this))) { + _$jscoverage['core/Range.js'][1048]++; + start = start.childNodes[me.startOffset]; + _$jscoverage['core/Range.js'][1049]++; + if ((start.nodeType == 1)) { + _$jscoverage['core/Range.js'][1050]++; + return start; + } + } + _$jscoverage['core/Range.js'][1053]++; + return ((ignoreTextNode && (start.nodeType == 3))? start.parentNode: start); + } + _$jscoverage['core/Range.js'][1055]++; + return domUtils.getCommonAncestor(start, end); +}), trimBoundary: (function (ignoreEnd) { + _$jscoverage['core/Range.js'][1132]++; + this.txtToElmBoundary(); + _$jscoverage['core/Range.js'][1133]++; + var start = this.startContainer, offset = this.startOffset, collapsed = this.collapsed, end = this.endContainer; + _$jscoverage['core/Range.js'][1137]++; + if ((start.nodeType == 3)) { + _$jscoverage['core/Range.js'][1138]++; + if ((offset == 0)) { + _$jscoverage['core/Range.js'][1139]++; + this.setStartBefore(start); + } + else { + _$jscoverage['core/Range.js'][1141]++; + if ((offset >= start.nodeValue.length)) { + _$jscoverage['core/Range.js'][1142]++; + this.setStartAfter(start); + } + else { + _$jscoverage['core/Range.js'][1144]++; + var textNode = domUtils.split(start, offset); + _$jscoverage['core/Range.js'][1146]++; + if ((start === end)) { + _$jscoverage['core/Range.js'][1147]++; + this.setEnd(textNode, (this.endOffset - offset)); + } + else { + _$jscoverage['core/Range.js'][1148]++; + if ((start.parentNode === end)) { + _$jscoverage['core/Range.js'][1149]++; + this.endOffset += 1; + } + } + _$jscoverage['core/Range.js'][1151]++; + this.setStartBefore(textNode); + } + } + _$jscoverage['core/Range.js'][1154]++; + if (collapsed) { + _$jscoverage['core/Range.js'][1155]++; + return this.collapse(true); + } + } + _$jscoverage['core/Range.js'][1158]++; + if ((! ignoreEnd)) { + _$jscoverage['core/Range.js'][1159]++; + offset = this.endOffset; + _$jscoverage['core/Range.js'][1160]++; + end = this.endContainer; + _$jscoverage['core/Range.js'][1161]++; + if ((end.nodeType == 3)) { + _$jscoverage['core/Range.js'][1162]++; + if ((offset == 0)) { + _$jscoverage['core/Range.js'][1163]++; + this.setEndBefore(end); + } + else { + _$jscoverage['core/Range.js'][1165]++; + ((offset < end.nodeValue.length) && domUtils.split(end, offset)); + _$jscoverage['core/Range.js'][1166]++; + this.setEndAfter(end); + } + } + } + _$jscoverage['core/Range.js'][1170]++; + return this; +}), txtToElmBoundary: (function (ignoreCollapsed) { + _$jscoverage['core/Range.js'][1302]++; + function adjust(r, c) { + _$jscoverage['core/Range.js'][1303]++; + var container = r[(c + "Container")], offset = r[(c + "Offset")]; + _$jscoverage['core/Range.js'][1305]++; + if ((container.nodeType == 3)) { + _$jscoverage['core/Range.js'][1306]++; + if ((! offset)) { + _$jscoverage['core/Range.js'][1307]++; + (r[("set" + c.replace(/(\w)/, (function (a) { + _$jscoverage['core/Range.js'][1308]++; + return a.toUpperCase(); +})) + "Before")])(container); + } + else { + _$jscoverage['core/Range.js'][1310]++; + if ((offset >= container.nodeValue.length)) { + _$jscoverage['core/Range.js'][1311]++; + (r[("set" + c.replace(/(\w)/, (function (a) { + _$jscoverage['core/Range.js'][1312]++; + return a.toUpperCase(); +})) + "After")])(container); + } + } + } +} + _$jscoverage['core/Range.js'][1318]++; + if ((ignoreCollapsed || (! this.collapsed))) { + _$jscoverage['core/Range.js'][1319]++; + adjust(this, "start"); + _$jscoverage['core/Range.js'][1320]++; + adjust(this, "end"); + } + _$jscoverage['core/Range.js'][1322]++; + return this; +}), insertNode: (function (node) { + _$jscoverage['core/Range.js'][1361]++; + var first = node, length = 1; + _$jscoverage['core/Range.js'][1362]++; + if ((node.nodeType == 11)) { + _$jscoverage['core/Range.js'][1363]++; + first = node.firstChild; + _$jscoverage['core/Range.js'][1364]++; + length = node.childNodes.length; + } + _$jscoverage['core/Range.js'][1366]++; + this.trimBoundary(true); + _$jscoverage['core/Range.js'][1367]++; + var start = this.startContainer, offset = this.startOffset; + _$jscoverage['core/Range.js'][1369]++; + var nextNode = start.childNodes[offset]; + _$jscoverage['core/Range.js'][1370]++; + if (nextNode) { + _$jscoverage['core/Range.js'][1371]++; + start.insertBefore(node, nextNode); + } + else { + _$jscoverage['core/Range.js'][1373]++; + start.appendChild(node); + } + _$jscoverage['core/Range.js'][1375]++; + if ((first.parentNode === this.endContainer)) { + _$jscoverage['core/Range.js'][1376]++; + this.endOffset = (this.endOffset + length); + } + _$jscoverage['core/Range.js'][1378]++; + return this.setStartBefore(first); +}), setCursor: (function (toEnd, noFillData) { + _$jscoverage['core/Range.js'][1397]++; + return this.collapse((! toEnd)).select(noFillData); +}), createBookmark: (function (serialize, same) { + _$jscoverage['core/Range.js'][1410]++; + var endNode, startNode = this.document.createElement("span"); + _$jscoverage['core/Range.js'][1412]++; + startNode.style.cssText = "display:none;line-height:0px;"; + _$jscoverage['core/Range.js'][1413]++; + startNode.appendChild(this.document.createTextNode("\u200d")); + _$jscoverage['core/Range.js'][1414]++; + startNode.id = ("_baidu_bookmark_start_" + (same? "": (guid++))); + _$jscoverage['core/Range.js'][1416]++; + if ((! this.collapsed)) { + _$jscoverage['core/Range.js'][1417]++; + endNode = startNode.cloneNode(true); + _$jscoverage['core/Range.js'][1418]++; + endNode.id = ("_baidu_bookmark_end_" + (same? "": (guid++))); + } + _$jscoverage['core/Range.js'][1420]++; + this.insertNode(startNode); + _$jscoverage['core/Range.js'][1421]++; + if (endNode) { + _$jscoverage['core/Range.js'][1422]++; + this.collapse().insertNode(endNode).setEndBefore(endNode); + } + _$jscoverage['core/Range.js'][1424]++; + this.setStartAfter(startNode); + _$jscoverage['core/Range.js'][1425]++; + return ({start: (serialize? startNode.id: startNode), end: (endNode? (serialize? endNode.id: endNode): null), id: serialize}); +}), moveToBookmark: (function (bookmark) { + _$jscoverage['core/Range.js'][1440]++; + var start = (bookmark.id? this.document.getElementById(bookmark.start): bookmark.start), end = ((bookmark.end && bookmark.id)? this.document.getElementById(bookmark.end): bookmark.end); + _$jscoverage['core/Range.js'][1442]++; + this.setStartBefore(start); + _$jscoverage['core/Range.js'][1443]++; + domUtils.remove(start); + _$jscoverage['core/Range.js'][1444]++; + if (end) { + _$jscoverage['core/Range.js'][1445]++; + this.setEndBefore(end); + _$jscoverage['core/Range.js'][1446]++; + domUtils.remove(end); + } + else { + _$jscoverage['core/Range.js'][1448]++; + this.collapse(true); + } + _$jscoverage['core/Range.js'][1450]++; + return this; +}), enlarge: (function (toBlock, stopFn) { + _$jscoverage['core/Range.js'][1511]++; + var isBody = domUtils.isBody, pre, node, tmp = this.document.createTextNode(""); + _$jscoverage['core/Range.js'][1513]++; + if (toBlock) { + _$jscoverage['core/Range.js'][1514]++; + node = this.startContainer; + _$jscoverage['core/Range.js'][1515]++; + if ((node.nodeType == 1)) { + _$jscoverage['core/Range.js'][1516]++; + if (node.childNodes[this.startOffset]) { + _$jscoverage['core/Range.js'][1517]++; + pre = (node = node.childNodes[this.startOffset]); + } + else { + _$jscoverage['core/Range.js'][1519]++; + node.appendChild(tmp); + _$jscoverage['core/Range.js'][1520]++; + pre = (node = tmp); + } + } + else { + _$jscoverage['core/Range.js'][1523]++; + pre = node; + } + _$jscoverage['core/Range.js'][1525]++; + while (true) { + _$jscoverage['core/Range.js'][1526]++; + if (domUtils.isBlockElm(node)) { + _$jscoverage['core/Range.js'][1527]++; + node = pre; + _$jscoverage['core/Range.js'][1528]++; + while (((pre = node.previousSibling) && (! domUtils.isBlockElm(pre)))) { + _$jscoverage['core/Range.js'][1529]++; + node = pre; +} + _$jscoverage['core/Range.js'][1531]++; + this.setStartBefore(node); + _$jscoverage['core/Range.js'][1532]++; + break; + } + _$jscoverage['core/Range.js'][1534]++; + pre = node; + _$jscoverage['core/Range.js'][1535]++; + node = node.parentNode; +} + _$jscoverage['core/Range.js'][1537]++; + node = this.endContainer; + _$jscoverage['core/Range.js'][1538]++; + if ((node.nodeType == 1)) { + _$jscoverage['core/Range.js'][1539]++; + if ((pre = node.childNodes[this.endOffset])) { + _$jscoverage['core/Range.js'][1540]++; + node.insertBefore(tmp, pre); + } + else { + _$jscoverage['core/Range.js'][1542]++; + node.appendChild(tmp); + } + _$jscoverage['core/Range.js'][1544]++; + pre = (node = tmp); + } + else { + _$jscoverage['core/Range.js'][1546]++; + pre = node; + } + _$jscoverage['core/Range.js'][1548]++; + while (true) { + _$jscoverage['core/Range.js'][1549]++; + if (domUtils.isBlockElm(node)) { + _$jscoverage['core/Range.js'][1550]++; + node = pre; + _$jscoverage['core/Range.js'][1551]++; + while (((pre = node.nextSibling) && (! domUtils.isBlockElm(pre)))) { + _$jscoverage['core/Range.js'][1552]++; + node = pre; +} + _$jscoverage['core/Range.js'][1554]++; + this.setEndAfter(node); + _$jscoverage['core/Range.js'][1555]++; + break; + } + _$jscoverage['core/Range.js'][1557]++; + pre = node; + _$jscoverage['core/Range.js'][1558]++; + node = node.parentNode; +} + _$jscoverage['core/Range.js'][1560]++; + if ((tmp.parentNode === this.endContainer)) { + _$jscoverage['core/Range.js'][1561]++; + (this.endOffset--); + } + _$jscoverage['core/Range.js'][1563]++; + domUtils.remove(tmp); + } + _$jscoverage['core/Range.js'][1567]++; + if ((! this.collapsed)) { + _$jscoverage['core/Range.js'][1568]++; + while ((this.startOffset == 0)) { + _$jscoverage['core/Range.js'][1569]++; + if ((stopFn && stopFn(this.startContainer))) { + _$jscoverage['core/Range.js'][1570]++; + break; + } + _$jscoverage['core/Range.js'][1572]++; + if (isBody(this.startContainer)) { + _$jscoverage['core/Range.js'][1573]++; + break; + } + _$jscoverage['core/Range.js'][1575]++; + this.setStartBefore(this.startContainer); +} + _$jscoverage['core/Range.js'][1577]++; + while ((this.endOffset == ((this.endContainer.nodeType == 1)? this.endContainer.childNodes.length: this.endContainer.nodeValue.length))) { + _$jscoverage['core/Range.js'][1578]++; + if ((stopFn && stopFn(this.endContainer))) { + _$jscoverage['core/Range.js'][1579]++; + break; + } + _$jscoverage['core/Range.js'][1581]++; + if (isBody(this.endContainer)) { + _$jscoverage['core/Range.js'][1582]++; + break; + } + _$jscoverage['core/Range.js'][1584]++; + this.setEndAfter(this.endContainer); +} + } + _$jscoverage['core/Range.js'][1587]++; + return this; +}), adjustmentBoundary: (function () { + _$jscoverage['core/Range.js'][1597]++; + if ((! this.collapsed)) { + _$jscoverage['core/Range.js'][1598]++; + while (((! domUtils.isBody(this.startContainer)) && (this.startOffset == this.startContainer[((this.startContainer.nodeType == 3)? "nodeValue": "childNodes")].length) && this.startContainer[((this.startContainer.nodeType == 3)? "nodeValue": "childNodes")].length)) { + _$jscoverage['core/Range.js'][1603]++; + this.setStartAfter(this.startContainer); +} + _$jscoverage['core/Range.js'][1605]++; + while (((! domUtils.isBody(this.endContainer)) && (! this.endOffset) && this.endContainer[((this.endContainer.nodeType == 3)? "nodeValue": "childNodes")].length)) { + _$jscoverage['core/Range.js'][1608]++; + this.setEndBefore(this.endContainer); +} + } + _$jscoverage['core/Range.js'][1611]++; + return this; +}), applyInlineStyle: (function (tagName, attrs, list) { + _$jscoverage['core/Range.js'][1624]++; + if (this.collapsed) { + _$jscoverage['core/Range.js'][1624]++; + return this; + } + _$jscoverage['core/Range.js'][1625]++; + this.trimBoundary().enlarge(false, (function (node) { + _$jscoverage['core/Range.js'][1627]++; + return ((node.nodeType == 1) && domUtils.isBlockElm(node)); +})).adjustmentBoundary(); + _$jscoverage['core/Range.js'][1629]++; + var bookmark = this.createBookmark(), end = bookmark.end, filterFn = (function (node) { + _$jscoverage['core/Range.js'][1632]++; + return ((node.nodeType == 1)? (node.tagName.toLowerCase() != "br"): (! domUtils.isWhitespace(node))); +}), current = domUtils.getNextDomNode(bookmark.start, false, filterFn), node, pre, range = this.cloneRange(); + _$jscoverage['core/Range.js'][1638]++; + while ((current && (domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING))) { + _$jscoverage['core/Range.js'][1639]++; + if (((current.nodeType == 3) || dtd[tagName][current.tagName])) { + _$jscoverage['core/Range.js'][1640]++; + range.setStartBefore(current); + _$jscoverage['core/Range.js'][1641]++; + node = current; + _$jscoverage['core/Range.js'][1642]++; + while ((node && ((node.nodeType == 3) || dtd[tagName][node.tagName]) && (node !== end))) { + _$jscoverage['core/Range.js'][1643]++; + pre = node; + _$jscoverage['core/Range.js'][1644]++; + node = domUtils.getNextDomNode(node, (node.nodeType == 1), null, (function (parent) { + _$jscoverage['core/Range.js'][1645]++; + return dtd[tagName][parent.tagName]; +})); +} + _$jscoverage['core/Range.js'][1648]++; + var frag = range.setEndAfter(pre).extractContents(), elm; + _$jscoverage['core/Range.js'][1649]++; + if ((list && (list.length > 0))) { + _$jscoverage['core/Range.js'][1650]++; + var level, top; + _$jscoverage['core/Range.js'][1651]++; + top = (level = list[0].cloneNode(false)); + _$jscoverage['core/Range.js'][1652]++; + for (var i = 1, ci; (ci = list[(i++)]);) { + _$jscoverage['core/Range.js'][1653]++; + level.appendChild(ci.cloneNode(false)); + _$jscoverage['core/Range.js'][1654]++; + level = level.firstChild; +} + _$jscoverage['core/Range.js'][1656]++; + elm = level; + } + else { + _$jscoverage['core/Range.js'][1658]++; + elm = range.document.createElement(tagName); + } + _$jscoverage['core/Range.js'][1660]++; + if (attrs) { + _$jscoverage['core/Range.js'][1661]++; + domUtils.setAttributes(elm, attrs); + } + _$jscoverage['core/Range.js'][1663]++; + elm.appendChild(frag); + _$jscoverage['core/Range.js'][1664]++; + range.insertNode((list? top: elm)); + _$jscoverage['core/Range.js'][1666]++; + var aNode; + _$jscoverage['core/Range.js'][1667]++; + if (((tagName == "span") && attrs.style && /text\-decoration/.test(attrs.style) && (aNode = domUtils.findParentByTagName(elm, "a", true)))) { + _$jscoverage['core/Range.js'][1668]++; + domUtils.setAttributes(aNode, attrs); + _$jscoverage['core/Range.js'][1669]++; + domUtils.remove(elm, true); + _$jscoverage['core/Range.js'][1670]++; + elm = aNode; + } + else { + _$jscoverage['core/Range.js'][1672]++; + domUtils.mergeSibling(elm); + _$jscoverage['core/Range.js'][1673]++; + domUtils.clearEmptySibling(elm); + } + _$jscoverage['core/Range.js'][1676]++; + domUtils.mergeChild(elm, attrs); + _$jscoverage['core/Range.js'][1677]++; + current = domUtils.getNextDomNode(elm, false, filterFn); + _$jscoverage['core/Range.js'][1678]++; + domUtils.mergeToParent(elm); + _$jscoverage['core/Range.js'][1679]++; + if ((node === end)) { + _$jscoverage['core/Range.js'][1680]++; + break; + } + } + else { + _$jscoverage['core/Range.js'][1683]++; + current = domUtils.getNextDomNode(current, true, filterFn); + } +} + _$jscoverage['core/Range.js'][1686]++; + return this.moveToBookmark(bookmark); +}), removeInlineStyle: (function (tagNames) { + _$jscoverage['core/Range.js'][1696]++; + if (this.collapsed) { + _$jscoverage['core/Range.js'][1696]++; + return this; + } + _$jscoverage['core/Range.js'][1697]++; + tagNames = (utils.isArray(tagNames)? tagNames: [tagNames]); + _$jscoverage['core/Range.js'][1698]++; + this.shrinkBoundary().adjustmentBoundary(); + _$jscoverage['core/Range.js'][1699]++; + var start = this.startContainer, end = this.endContainer; + _$jscoverage['core/Range.js'][1700]++; + while (true) { + _$jscoverage['core/Range.js'][1701]++; + if ((start.nodeType == 1)) { + _$jscoverage['core/Range.js'][1702]++; + if ((utils.indexOf(tagNames, start.tagName.toLowerCase()) > -1)) { + _$jscoverage['core/Range.js'][1703]++; + break; + } + _$jscoverage['core/Range.js'][1705]++; + if ((start.tagName.toLowerCase() == "body")) { + _$jscoverage['core/Range.js'][1706]++; + start = null; + _$jscoverage['core/Range.js'][1707]++; + break; + } + } + _$jscoverage['core/Range.js'][1710]++; + start = start.parentNode; +} + _$jscoverage['core/Range.js'][1712]++; + while (true) { + _$jscoverage['core/Range.js'][1713]++; + if ((end.nodeType == 1)) { + _$jscoverage['core/Range.js'][1714]++; + if ((utils.indexOf(tagNames, end.tagName.toLowerCase()) > -1)) { + _$jscoverage['core/Range.js'][1715]++; + break; + } + _$jscoverage['core/Range.js'][1717]++; + if ((end.tagName.toLowerCase() == "body")) { + _$jscoverage['core/Range.js'][1718]++; + end = null; + _$jscoverage['core/Range.js'][1719]++; + break; + } + } + _$jscoverage['core/Range.js'][1722]++; + end = end.parentNode; +} + _$jscoverage['core/Range.js'][1724]++; + var bookmark = this.createBookmark(), frag, tmpRange; + _$jscoverage['core/Range.js'][1727]++; + if (start) { + _$jscoverage['core/Range.js'][1728]++; + tmpRange = this.cloneRange().setEndBefore(bookmark.start).setStartBefore(start); + _$jscoverage['core/Range.js'][1729]++; + frag = tmpRange.extractContents(); + _$jscoverage['core/Range.js'][1730]++; + tmpRange.insertNode(frag); + _$jscoverage['core/Range.js'][1731]++; + domUtils.clearEmptySibling(start, true); + _$jscoverage['core/Range.js'][1732]++; + start.parentNode.insertBefore(bookmark.start, start); + } + _$jscoverage['core/Range.js'][1734]++; + if (end) { + _$jscoverage['core/Range.js'][1735]++; + tmpRange = this.cloneRange().setStartAfter(bookmark.end).setEndAfter(end); + _$jscoverage['core/Range.js'][1736]++; + frag = tmpRange.extractContents(); + _$jscoverage['core/Range.js'][1737]++; + tmpRange.insertNode(frag); + _$jscoverage['core/Range.js'][1738]++; + domUtils.clearEmptySibling(end, false, true); + _$jscoverage['core/Range.js'][1739]++; + end.parentNode.insertBefore(bookmark.end, end.nextSibling); + } + _$jscoverage['core/Range.js'][1741]++; + var current = domUtils.getNextDomNode(bookmark.start, false, (function (node) { + _$jscoverage['core/Range.js'][1742]++; + return (node.nodeType == 1); +})), next; + _$jscoverage['core/Range.js'][1744]++; + while ((current && (current !== bookmark.end))) { + _$jscoverage['core/Range.js'][1745]++; + next = domUtils.getNextDomNode(current, true, (function (node) { + _$jscoverage['core/Range.js'][1746]++; + return (node.nodeType == 1); +})); + _$jscoverage['core/Range.js'][1748]++; + if ((utils.indexOf(tagNames, current.tagName.toLowerCase()) > -1)) { + _$jscoverage['core/Range.js'][1749]++; + domUtils.remove(current, true); + } + _$jscoverage['core/Range.js'][1751]++; + current = next; +} + _$jscoverage['core/Range.js'][1753]++; + return this.moveToBookmark(bookmark); +}), getClosedNode: (function () { + _$jscoverage['core/Range.js'][1783]++; + var node; + _$jscoverage['core/Range.js'][1784]++; + if ((! this.collapsed)) { + _$jscoverage['core/Range.js'][1785]++; + var range = this.cloneRange().adjustmentBoundary().shrinkBoundary(); + _$jscoverage['core/Range.js'][1786]++; + if (selectOneNode(range)) { + _$jscoverage['core/Range.js'][1787]++; + var child = range.startContainer.childNodes[range.startOffset]; + _$jscoverage['core/Range.js'][1788]++; + if ((child && (child.nodeType == 1) && (dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName]))) { + _$jscoverage['core/Range.js'][1789]++; + node = child; + } + } + } + _$jscoverage['core/Range.js'][1793]++; + return node; +}), select: (browser.ie? (function (noFillData, textRange) { + _$jscoverage['core/Range.js'][1802]++; + var nativeRange; + _$jscoverage['core/Range.js'][1803]++; + if ((! this.collapsed)) { + _$jscoverage['core/Range.js'][1804]++; + this.shrinkBoundary(); + } + _$jscoverage['core/Range.js'][1805]++; + var node = this.getClosedNode(); + _$jscoverage['core/Range.js'][1806]++; + if ((node && (! textRange))) { + _$jscoverage['core/Range.js'][1807]++; + try { + _$jscoverage['core/Range.js'][1808]++; + nativeRange = this.document.body.createControlRange(); + _$jscoverage['core/Range.js'][1809]++; + nativeRange.addElement(node); + _$jscoverage['core/Range.js'][1810]++; + nativeRange.select(); + } + catch (e) { + } + _$jscoverage['core/Range.js'][1812]++; + return this; + } + _$jscoverage['core/Range.js'][1814]++; + var bookmark = this.createBookmark(), start = bookmark.start, end; + _$jscoverage['core/Range.js'][1817]++; + nativeRange = this.document.body.createTextRange(); + _$jscoverage['core/Range.js'][1818]++; + nativeRange.moveToElementText(start); + _$jscoverage['core/Range.js'][1819]++; + nativeRange.moveStart("character", 1); + _$jscoverage['core/Range.js'][1820]++; + if ((! this.collapsed)) { + _$jscoverage['core/Range.js'][1821]++; + var nativeRangeEnd = this.document.body.createTextRange(); + _$jscoverage['core/Range.js'][1822]++; + end = bookmark.end; + _$jscoverage['core/Range.js'][1823]++; + nativeRangeEnd.moveToElementText(end); + _$jscoverage['core/Range.js'][1824]++; + nativeRange.setEndPoint("EndToEnd", nativeRangeEnd); + } + else { + _$jscoverage['core/Range.js'][1826]++; + if (((! noFillData) && (this.startContainer.nodeType != 3))) { + _$jscoverage['core/Range.js'][1828]++; + var tmpText = this.document.createTextNode(fillChar), tmp = this.document.createElement("span"); + _$jscoverage['core/Range.js'][1830]++; + tmp.appendChild(this.document.createTextNode(fillChar)); + _$jscoverage['core/Range.js'][1831]++; + start.parentNode.insertBefore(tmp, start); + _$jscoverage['core/Range.js'][1832]++; + start.parentNode.insertBefore(tmpText, start); + _$jscoverage['core/Range.js'][1834]++; + removeFillData(this.document, tmpText); + _$jscoverage['core/Range.js'][1835]++; + fillData = tmpText; + _$jscoverage['core/Range.js'][1836]++; + mergeSibling(tmp, "previousSibling"); + _$jscoverage['core/Range.js'][1837]++; + mergeSibling(start, "nextSibling"); + _$jscoverage['core/Range.js'][1838]++; + nativeRange.moveStart("character", -1); + _$jscoverage['core/Range.js'][1839]++; + nativeRange.collapse(true); + } + } + _$jscoverage['core/Range.js'][1842]++; + this.moveToBookmark(bookmark); + _$jscoverage['core/Range.js'][1843]++; + (tmp && domUtils.remove(tmp)); + _$jscoverage['core/Range.js'][1845]++; + try { + _$jscoverage['core/Range.js'][1846]++; + nativeRange.select(); + } + catch (e) { + } + _$jscoverage['core/Range.js'][1849]++; + return this; +}): (function (notInsertFillData) { + _$jscoverage['core/Range.js'][1851]++; + function checkOffset(rng) { + _$jscoverage['core/Range.js'][1853]++; + function check(node, offset, dir) { + _$jscoverage['core/Range.js'][1854]++; + if (((node.nodeType == 3) && (node.nodeValue.length < offset))) { + _$jscoverage['core/Range.js'][1855]++; + rng[(dir + "Offset")] = node.nodeValue.length; + } +} + _$jscoverage['core/Range.js'][1858]++; + check(rng.startContainer, rng.startOffset, "start"); + _$jscoverage['core/Range.js'][1859]++; + check(rng.endContainer, rng.endOffset, "end"); +} + _$jscoverage['core/Range.js'][1861]++; + var win = domUtils.getWindow(this.document), sel = win.getSelection(), txtNode; + _$jscoverage['core/Range.js'][1866]++; + (browser.gecko? this.document.body.focus(): win.focus()); + _$jscoverage['core/Range.js'][1867]++; + if (sel) { + _$jscoverage['core/Range.js'][1868]++; + sel.removeAllRanges(); + _$jscoverage['core/Range.js'][1871]++; + if ((this.collapsed && (! notInsertFillData))) { + _$jscoverage['core/Range.js'][1883]++; + var start = this.startContainer, child = start; + _$jscoverage['core/Range.js'][1884]++; + if ((start.nodeType == 1)) { + _$jscoverage['core/Range.js'][1885]++; + child = start.childNodes[this.startOffset]; + } + _$jscoverage['core/Range.js'][1888]++; + if (((! ((start.nodeType == 3) && this.startOffset)) && (child? ((! child.previousSibling) || (child.previousSibling.nodeType != 3)): ((! start.lastChild) || (start.lastChild.nodeType != 3))))) { + _$jscoverage['core/Range.js'][1895]++; + txtNode = this.document.createTextNode(fillChar); + _$jscoverage['core/Range.js'][1897]++; + this.insertNode(txtNode); + _$jscoverage['core/Range.js'][1898]++; + removeFillData(this.document, txtNode); + _$jscoverage['core/Range.js'][1899]++; + mergeSibling(txtNode, "previousSibling"); + _$jscoverage['core/Range.js'][1900]++; + mergeSibling(txtNode, "nextSibling"); + _$jscoverage['core/Range.js'][1901]++; + fillData = txtNode; + _$jscoverage['core/Range.js'][1902]++; + this.setStart(txtNode, (browser.webkit? 1: 0)).collapse(true); + } + } + _$jscoverage['core/Range.js'][1905]++; + var nativeRange = this.document.createRange(); + _$jscoverage['core/Range.js'][1906]++; + if ((this.collapsed && browser.opera && (this.startContainer.nodeType == 1))) { + _$jscoverage['core/Range.js'][1907]++; + var child = this.startContainer.childNodes[this.startOffset]; + _$jscoverage['core/Range.js'][1908]++; + if ((! child)) { + _$jscoverage['core/Range.js'][1910]++; + child = this.startContainer.lastChild; + _$jscoverage['core/Range.js'][1911]++; + if ((child && domUtils.isBr(child))) { + _$jscoverage['core/Range.js'][1912]++; + this.setStartBefore(child).collapse(true); + } + } + else { + _$jscoverage['core/Range.js'][1916]++; + while ((child && domUtils.isBlockElm(child))) { + _$jscoverage['core/Range.js'][1917]++; + if (((child.nodeType == 1) && child.childNodes[0])) { + _$jscoverage['core/Range.js'][1918]++; + child = child.childNodes[0]; + } + else { + _$jscoverage['core/Range.js'][1920]++; + break; + } +} + _$jscoverage['core/Range.js'][1923]++; + (child && this.setStartBefore(child).collapse(true)); + } + } + _$jscoverage['core/Range.js'][1928]++; + checkOffset(this); + _$jscoverage['core/Range.js'][1929]++; + nativeRange.setStart(this.startContainer, this.startOffset); + _$jscoverage['core/Range.js'][1930]++; + nativeRange.setEnd(this.endContainer, this.endOffset); + _$jscoverage['core/Range.js'][1931]++; + sel.addRange(nativeRange); + } + _$jscoverage['core/Range.js'][1933]++; + return this; +})), scrollToView: (function (win, offset) { + _$jscoverage['core/Range.js'][1951]++; + win = (win? window: domUtils.getWindow(this.document)); + _$jscoverage['core/Range.js'][1952]++; + var me = this, span = me.document.createElement("span"); + _$jscoverage['core/Range.js'][1955]++; + span.innerHTML = " "; + _$jscoverage['core/Range.js'][1956]++; + me.cloneRange().insertNode(span); + _$jscoverage['core/Range.js'][1957]++; + domUtils.scrollToView(span, win, offset); + _$jscoverage['core/Range.js'][1958]++; + domUtils.remove(span); + _$jscoverage['core/Range.js'][1959]++; + return me; +}), inFillChar: (function () { + _$jscoverage['core/Range.js'][1967]++; + var start = this.startContainer; + _$jscoverage['core/Range.js'][1968]++; + if ((this.collapsed && (start.nodeType == 3) && ((start.nodeValue.replace(new RegExp(("^" + domUtils.fillChar)), "").length + 1) == start.nodeValue.length))) { + _$jscoverage['core/Range.js'][1971]++; + return true; + } + _$jscoverage['core/Range.js'][1973]++; + return false; +}), createAddress: (function (ignoreEnd, ignoreTxt) { + _$jscoverage['core/Range.js'][2000]++; + var addr = {}, me = this; + _$jscoverage['core/Range.js'][2002]++; + function getAddress(isStart) { + _$jscoverage['core/Range.js'][2003]++; + var node = (isStart? me.startContainer: me.endContainer); + _$jscoverage['core/Range.js'][2004]++; + var parents = domUtils.findParents(node, true, (function (node) { + _$jscoverage['core/Range.js'][2004]++; + return (! domUtils.isBody(node)); +})), addrs = []; + _$jscoverage['core/Range.js'][2006]++; + for (var i = 0, ci; (ci = parents[(i++)]);) { + _$jscoverage['core/Range.js'][2007]++; + addrs.push(domUtils.getNodeIndex(ci, ignoreTxt)); +} + _$jscoverage['core/Range.js'][2009]++; + var firstIndex = 0; + _$jscoverage['core/Range.js'][2011]++; + if (ignoreTxt) { + _$jscoverage['core/Range.js'][2012]++; + if ((node.nodeType == 3)) { + _$jscoverage['core/Range.js'][2013]++; + var tmpNode = node.previousSibling; + _$jscoverage['core/Range.js'][2014]++; + while ((tmpNode && (tmpNode.nodeType == 3))) { + _$jscoverage['core/Range.js'][2015]++; + firstIndex += tmpNode.nodeValue.replace(fillCharReg, "").length; + _$jscoverage['core/Range.js'][2016]++; + tmpNode = tmpNode.previousSibling; +} + _$jscoverage['core/Range.js'][2018]++; + firstIndex += (isStart? me.startOffset: me.endOffset); + } + else { + _$jscoverage['core/Range.js'][2020]++; + node = node.childNodes[(isStart? me.startOffset: me.endOffset)]; + _$jscoverage['core/Range.js'][2021]++; + if (node) { + _$jscoverage['core/Range.js'][2022]++; + firstIndex = domUtils.getNodeIndex(node, ignoreTxt); + } + else { + _$jscoverage['core/Range.js'][2024]++; + node = (isStart? me.startContainer: me.endContainer); + _$jscoverage['core/Range.js'][2025]++; + var first = node.firstChild; + _$jscoverage['core/Range.js'][2026]++; + while (first) { + _$jscoverage['core/Range.js'][2027]++; + if (domUtils.isFillChar(first)) { + _$jscoverage['core/Range.js'][2028]++; + first = first.nextSibling; + _$jscoverage['core/Range.js'][2029]++; + continue; + } + _$jscoverage['core/Range.js'][2031]++; + (firstIndex++); + _$jscoverage['core/Range.js'][2032]++; + if ((first.nodeType == 3)) { + _$jscoverage['core/Range.js'][2033]++; + while ((first && (first.nodeType == 3))) { + _$jscoverage['core/Range.js'][2034]++; + first = first.nextSibling; +} + } + else { + _$jscoverage['core/Range.js'][2037]++; + first = first.nextSibling; + } +} + } + } + } + else { + _$jscoverage['core/Range.js'][2044]++; + firstIndex = (isStart? (domUtils.isFillChar(node)? 0: me.startOffset): me.endOffset); + } + _$jscoverage['core/Range.js'][2046]++; + if ((firstIndex < 0)) { + _$jscoverage['core/Range.js'][2047]++; + firstIndex = 0; + } + _$jscoverage['core/Range.js'][2049]++; + addrs.push(firstIndex); + _$jscoverage['core/Range.js'][2050]++; + return addrs; +} + _$jscoverage['core/Range.js'][2052]++; + addr.startAddress = getAddress(true); + _$jscoverage['core/Range.js'][2053]++; + if ((! ignoreEnd)) { + _$jscoverage['core/Range.js'][2054]++; + addr.endAddress = (me.collapsed? [].concat(addr.startAddress): getAddress()); + } + _$jscoverage['core/Range.js'][2056]++; + return addr; +}), moveToAddress: (function (addr, ignoreEnd) { + _$jscoverage['core/Range.js'][2085]++; + var me = this; + _$jscoverage['core/Range.js'][2086]++; + function getNode(address, isStart) { + _$jscoverage['core/Range.js'][2087]++; + var tmpNode = me.document.body, parentNode, offset; + _$jscoverage['core/Range.js'][2089]++; + for (var i = 0, ci, l = address.length; (i < l); (i++)) { + _$jscoverage['core/Range.js'][2090]++; + ci = address[i]; + _$jscoverage['core/Range.js'][2091]++; + parentNode = tmpNode; + _$jscoverage['core/Range.js'][2092]++; + tmpNode = tmpNode.childNodes[ci]; + _$jscoverage['core/Range.js'][2093]++; + if ((! tmpNode)) { + _$jscoverage['core/Range.js'][2094]++; + offset = ci; + _$jscoverage['core/Range.js'][2095]++; + break; + } +} + _$jscoverage['core/Range.js'][2098]++; + if (isStart) { + _$jscoverage['core/Range.js'][2099]++; + if (tmpNode) { + _$jscoverage['core/Range.js'][2100]++; + me.setStartBefore(tmpNode); + } + else { + _$jscoverage['core/Range.js'][2102]++; + me.setStart(parentNode, offset); + } + } + else { + _$jscoverage['core/Range.js'][2105]++; + if (tmpNode) { + _$jscoverage['core/Range.js'][2106]++; + me.setEndBefore(tmpNode); + } + else { + _$jscoverage['core/Range.js'][2108]++; + me.setEnd(parentNode, offset); + } + } +} + _$jscoverage['core/Range.js'][2112]++; + getNode(addr.startAddress, true); + _$jscoverage['core/Range.js'][2113]++; + ((! ignoreEnd) && addr.endAddress && getNode(addr.endAddress)); + _$jscoverage['core/Range.js'][2114]++; + return me; +}), traversal: (function (doFn, filterFn) { + _$jscoverage['core/Range.js'][2214]++; + if (this.collapsed) { + _$jscoverage['core/Range.js'][2215]++; + return this; + } + _$jscoverage['core/Range.js'][2216]++; + var bookmark = this.createBookmark(), end = bookmark.end, current = domUtils.getNextDomNode(bookmark.start, false, filterFn); + _$jscoverage['core/Range.js'][2219]++; + while ((current && (current !== end) && (domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING))) { + _$jscoverage['core/Range.js'][2220]++; + var tmpNode = domUtils.getNextDomNode(current, false, filterFn); + _$jscoverage['core/Range.js'][2221]++; + doFn(current); + _$jscoverage['core/Range.js'][2222]++; + current = tmpNode; +} + _$jscoverage['core/Range.js'][2224]++; + return this.moveToBookmark(bookmark); +})}; +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/Selection.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/Selection.js new file mode 100644 index 000000000..c12cc84f1 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/Selection.js @@ -0,0 +1,606 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['core/Selection.js']) { + _$jscoverage['core/Selection.js'] = []; + _$jscoverage['core/Selection.js'][13] = 0; + _$jscoverage['core/Selection.js'][15] = 0; + _$jscoverage['core/Selection.js'][16] = 0; + _$jscoverage['core/Selection.js'][17] = 0; + _$jscoverage['core/Selection.js'][18] = 0; + _$jscoverage['core/Selection.js'][19] = 0; + _$jscoverage['core/Selection.js'][21] = 0; + _$jscoverage['core/Selection.js'][22] = 0; + _$jscoverage['core/Selection.js'][24] = 0; + _$jscoverage['core/Selection.js'][29] = 0; + _$jscoverage['core/Selection.js'][30] = 0; + _$jscoverage['core/Selection.js'][31] = 0; + _$jscoverage['core/Selection.js'][32] = 0; + _$jscoverage['core/Selection.js'][33] = 0; + _$jscoverage['core/Selection.js'][34] = 0; + _$jscoverage['core/Selection.js'][35] = 0; + _$jscoverage['core/Selection.js'][36] = 0; + _$jscoverage['core/Selection.js'][37] = 0; + _$jscoverage['core/Selection.js'][40] = 0; + _$jscoverage['core/Selection.js'][43] = 0; + _$jscoverage['core/Selection.js'][44] = 0; + _$jscoverage['core/Selection.js'][45] = 0; + _$jscoverage['core/Selection.js'][46] = 0; + _$jscoverage['core/Selection.js'][47] = 0; + _$jscoverage['core/Selection.js'][48] = 0; + _$jscoverage['core/Selection.js'][49] = 0; + _$jscoverage['core/Selection.js'][50] = 0; + _$jscoverage['core/Selection.js'][53] = 0; + _$jscoverage['core/Selection.js'][54] = 0; + _$jscoverage['core/Selection.js'][55] = 0; + _$jscoverage['core/Selection.js'][57] = 0; + _$jscoverage['core/Selection.js'][59] = 0; + _$jscoverage['core/Selection.js'][60] = 0; + _$jscoverage['core/Selection.js'][61] = 0; + _$jscoverage['core/Selection.js'][62] = 0; + _$jscoverage['core/Selection.js'][63] = 0; + _$jscoverage['core/Selection.js'][67] = 0; + _$jscoverage['core/Selection.js'][68] = 0; + _$jscoverage['core/Selection.js'][69] = 0; + _$jscoverage['core/Selection.js'][70] = 0; + _$jscoverage['core/Selection.js'][71] = 0; + _$jscoverage['core/Selection.js'][73] = 0; + _$jscoverage['core/Selection.js'][76] = 0; + _$jscoverage['core/Selection.js'][85] = 0; + _$jscoverage['core/Selection.js'][86] = 0; + _$jscoverage['core/Selection.js'][87] = 0; + _$jscoverage['core/Selection.js'][89] = 0; + _$jscoverage['core/Selection.js'][90] = 0; + _$jscoverage['core/Selection.js'][91] = 0; + _$jscoverage['core/Selection.js'][92] = 0; + _$jscoverage['core/Selection.js'][93] = 0; + _$jscoverage['core/Selection.js'][96] = 0; + _$jscoverage['core/Selection.js'][104] = 0; + _$jscoverage['core/Selection.js'][105] = 0; + _$jscoverage['core/Selection.js'][107] = 0; + _$jscoverage['core/Selection.js'][108] = 0; + _$jscoverage['core/Selection.js'][110] = 0; + _$jscoverage['core/Selection.js'][112] = 0; + _$jscoverage['core/Selection.js'][113] = 0; + _$jscoverage['core/Selection.js'][114] = 0; + _$jscoverage['core/Selection.js'][116] = 0; + _$jscoverage['core/Selection.js'][119] = 0; + _$jscoverage['core/Selection.js'][120] = 0; + _$jscoverage['core/Selection.js'][121] = 0; + _$jscoverage['core/Selection.js'][122] = 0; + _$jscoverage['core/Selection.js'][123] = 0; + _$jscoverage['core/Selection.js'][124] = 0; + _$jscoverage['core/Selection.js'][125] = 0; + _$jscoverage['core/Selection.js'][127] = 0; + _$jscoverage['core/Selection.js'][128] = 0; + _$jscoverage['core/Selection.js'][129] = 0; + _$jscoverage['core/Selection.js'][130] = 0; + _$jscoverage['core/Selection.js'][134] = 0; + _$jscoverage['core/Selection.js'][137] = 0; + _$jscoverage['core/Selection.js'][140] = 0; + _$jscoverage['core/Selection.js'][151] = 0; + _$jscoverage['core/Selection.js'][152] = 0; + _$jscoverage['core/Selection.js'][153] = 0; + _$jscoverage['core/Selection.js'][155] = 0; + _$jscoverage['core/Selection.js'][168] = 0; + _$jscoverage['core/Selection.js'][169] = 0; + _$jscoverage['core/Selection.js'][170] = 0; + _$jscoverage['core/Selection.js'][171] = 0; + _$jscoverage['core/Selection.js'][174] = 0; + _$jscoverage['core/Selection.js'][182] = 0; + _$jscoverage['core/Selection.js'][183] = 0; + _$jscoverage['core/Selection.js'][184] = 0; + _$jscoverage['core/Selection.js'][185] = 0; + _$jscoverage['core/Selection.js'][198] = 0; + _$jscoverage['core/Selection.js'][199] = 0; + _$jscoverage['core/Selection.js'][201] = 0; + _$jscoverage['core/Selection.js'][202] = 0; + _$jscoverage['core/Selection.js'][203] = 0; + _$jscoverage['core/Selection.js'][205] = 0; + _$jscoverage['core/Selection.js'][212] = 0; + _$jscoverage['core/Selection.js'][219] = 0; + _$jscoverage['core/Selection.js'][220] = 0; + _$jscoverage['core/Selection.js'][222] = 0; + _$jscoverage['core/Selection.js'][236] = 0; + _$jscoverage['core/Selection.js'][237] = 0; + _$jscoverage['core/Selection.js'][238] = 0; + _$jscoverage['core/Selection.js'][240] = 0; + _$jscoverage['core/Selection.js'][241] = 0; + _$jscoverage['core/Selection.js'][242] = 0; + _$jscoverage['core/Selection.js'][244] = 0; + _$jscoverage['core/Selection.js'][245] = 0; + _$jscoverage['core/Selection.js'][247] = 0; + _$jscoverage['core/Selection.js'][248] = 0; + _$jscoverage['core/Selection.js'][252] = 0; + _$jscoverage['core/Selection.js'][253] = 0; + _$jscoverage['core/Selection.js'][255] = 0; + _$jscoverage['core/Selection.js'][256] = 0; + _$jscoverage['core/Selection.js'][257] = 0; + _$jscoverage['core/Selection.js'][258] = 0; + _$jscoverage['core/Selection.js'][260] = 0; + _$jscoverage['core/Selection.js'][261] = 0; + _$jscoverage['core/Selection.js'][263] = 0; + _$jscoverage['core/Selection.js'][267] = 0; + _$jscoverage['core/Selection.js'][270] = 0; + _$jscoverage['core/Selection.js'][271] = 0; + _$jscoverage['core/Selection.js'][272] = 0; + _$jscoverage['core/Selection.js'][273] = 0; + _$jscoverage['core/Selection.js'][274] = 0; + _$jscoverage['core/Selection.js'][275] = 0; + _$jscoverage['core/Selection.js'][276] = 0; + _$jscoverage['core/Selection.js'][280] = 0; + _$jscoverage['core/Selection.js'][281] = 0; + _$jscoverage['core/Selection.js'][283] = 0; + _$jscoverage['core/Selection.js'][286] = 0; + _$jscoverage['core/Selection.js'][298] = 0; + _$jscoverage['core/Selection.js'][299] = 0; + _$jscoverage['core/Selection.js'][301] = 0; + _$jscoverage['core/Selection.js'][304] = 0; + _$jscoverage['core/Selection.js'][305] = 0; + _$jscoverage['core/Selection.js'][307] = 0; + _$jscoverage['core/Selection.js'][310] = 0; + _$jscoverage['core/Selection.js'][311] = 0; + _$jscoverage['core/Selection.js'][313] = 0; + _$jscoverage['core/Selection.js'][315] = 0; + _$jscoverage['core/Selection.js'][316] = 0; + _$jscoverage['core/Selection.js'][317] = 0; + _$jscoverage['core/Selection.js'][318] = 0; + _$jscoverage['core/Selection.js'][319] = 0; + _$jscoverage['core/Selection.js'][320] = 0; + _$jscoverage['core/Selection.js'][321] = 0; + _$jscoverage['core/Selection.js'][322] = 0; + _$jscoverage['core/Selection.js'][326] = 0; + _$jscoverage['core/Selection.js'][327] = 0; + _$jscoverage['core/Selection.js'][328] = 0; + _$jscoverage['core/Selection.js'][329] = 0; + _$jscoverage['core/Selection.js'][331] = 0; + _$jscoverage['core/Selection.js'][332] = 0; + _$jscoverage['core/Selection.js'][335] = 0; + _$jscoverage['core/Selection.js'][347] = 0; + _$jscoverage['core/Selection.js'][348] = 0; + _$jscoverage['core/Selection.js'][349] = 0; + _$jscoverage['core/Selection.js'][350] = 0; + _$jscoverage['core/Selection.js'][352] = 0; + _$jscoverage['core/Selection.js'][363] = 0; +} +_$jscoverage['core/Selection.js'].source = ["/**"," * 选集"," * @file"," * @module UE.dom.Selection"," * @since 1.2.6.1"," */","","/**"," * UEditor公用空间,UEditor所有的功能都挂载在该空间下"," * @module UE"," */","","(function () {",""," function getBoundaryInformation( range, start ) {"," var getIndex = domUtils.getNodeIndex;"," range = range.duplicate();"," range.collapse( start );"," var parent = range.parentElement();"," //如果节点里没有子节点,直接退出"," if ( !parent.hasChildNodes() ) {"," return {container:parent, offset:0};"," }"," var siblings = parent.children,"," child,"," testRange = range.duplicate(),"," startIndex = 0, endIndex = siblings.length - 1, index = -1,"," distance;"," while ( startIndex <= endIndex ) {"," index = Math.floor( (startIndex + endIndex) / 2 );"," child = siblings[index];"," testRange.moveToElementText( child );"," var position = testRange.compareEndPoints( 'StartToStart', range );"," if ( position > 0 ) {"," endIndex = index - 1;"," } else if ( position < 0 ) {"," startIndex = index + 1;"," } else {"," //trace:1043"," return {container:parent, offset:getIndex( child )};"," }"," }"," if ( index == -1 ) {"," testRange.moveToElementText( parent );"," testRange.setEndPoint( 'StartToStart', range );"," distance = testRange.text.replace( /(\\r\\n|\\r)/g, '\\n' ).length;"," siblings = parent.childNodes;"," if ( !distance ) {"," child = siblings[siblings.length - 1];"," return {container:child, offset:child.nodeValue.length};"," }",""," var i = siblings.length;"," while ( distance > 0 ){"," distance -= siblings[ --i ].nodeValue.length;"," }"," return {container:siblings[i], offset:-distance};"," }"," testRange.collapse( position > 0 );"," testRange.setEndPoint( position > 0 ? 'StartToStart' : 'EndToStart', range );"," distance = testRange.text.replace( /(\\r\\n|\\r)/g, '\\n' ).length;"," if ( !distance ) {"," return dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName] ?"," {container:parent, offset:getIndex( child ) + (position > 0 ? 0 : 1)} :"," {container:child, offset:position > 0 ? 0 : child.childNodes.length}"," }"," while ( distance > 0 ) {"," try {"," var pre = child;"," child = child[position > 0 ? 'previousSibling' : 'nextSibling'];"," distance -= child.nodeValue.length;"," } catch ( e ) {"," return {container:parent, offset:getIndex( pre )};"," }"," }"," return {container:child, offset:position > 0 ? -distance : child.nodeValue.length + distance}"," }",""," /*"," * 将ieRange转换为Range对象"," * @param {Range} ieRange ieRange对象"," * @param {Range} range Range对象"," * @return {Range} range 返回转换后的Range对象"," */"," function transformIERangeToRange( ieRange, range ) {"," if ( ieRange.item ) {"," range.selectNode( ieRange.item( 0 ) );"," } else {"," var bi = getBoundaryInformation( ieRange, true );"," range.setStart( bi.container, bi.offset );"," if ( ieRange.compareEndPoints( 'StartToEnd', ieRange ) != 0 ) {"," bi = getBoundaryInformation( ieRange, false );"," range.setEnd( bi.container, bi.offset );"," }"," }"," return range;"," }",""," /*"," * 获得ieRange"," * @param {Selection} sel Selection对象"," * @return {ieRange} 得到ieRange"," */"," function _getIERange( sel ) {"," var ieRange;"," //ie下有可能报错"," try {"," ieRange = sel.getNative().createRange();"," } catch ( e ) {"," return null;"," }"," var el = ieRange.item ? ieRange.item( 0 ) : ieRange.parentElement();"," if ( ( el.ownerDocument || el ) === sel.document ) {"," return ieRange;"," }"," return null;"," }",""," var Selection = dom.Selection = function ( doc ) {"," var me = this, iframe;"," me.document = doc;"," if ( ie ) {"," iframe = domUtils.getWindow( doc ).frameElement;"," domUtils.on( iframe, 'beforedeactivate', function () {"," me._bakIERange = me.getIERange();"," } );"," domUtils.on( iframe, 'activate', function () {"," try {"," if ( !_getIERange( me ) && me._bakIERange ) {"," me._bakIERange.select();"," }"," } catch ( ex ) {"," }"," me._bakIERange = null;"," } );"," }"," iframe = doc = null;"," };",""," Selection.prototype = {"," /**"," * 获取原生seleciton对象"," * @method getNative"," * @return { Object } 获得selection对象"," * @example"," * ```javascript"," * editor.selection.getNative();"," * ```"," */"," getNative:function () {"," var doc = this.document;"," try {"," return !doc ? null : ie && browser.ie < 9 ? doc.selection : domUtils.getWindow( doc ).getSelection();"," } catch ( e ) {"," return null;"," }"," },"," /**"," * 获得ieRange"," * @method getIERange"," * @return { Object } 返回ie原生的Range"," * @example"," * ```javascript"," * editor.selection.getIERange();"," * ```"," */"," getIERange:function () {"," var ieRange = _getIERange( this );"," if ( !ieRange ) {"," if ( this._bakIERange ) {"," return this._bakIERange;"," }"," }"," return ieRange;"," },",""," /**"," * 缓存当前选区的range和选区的开始节点"," * @method cache"," */"," cache:function () {"," this.clear();"," this._cachedRange = this.getRange();"," this._cachedStartElement = this.getStart();"," this._cachedStartElementPath = this.getStartElementPath();"," },",""," /**"," * 获取选区开始位置的父节点到body"," * @method getStartElementPath"," * @return { Array } 返回父节点集合"," * @example"," * ```javascript"," * editor.selection.getStartElementPath();"," * ```"," */"," getStartElementPath:function () {"," if ( this._cachedStartElementPath ) {"," return this._cachedStartElementPath;"," }"," var start = this.getStart();"," if ( start ) {"," return domUtils.findParents( start, true, null, true )"," }"," return [];"," },"," /**"," * 清空缓存"," * @method clear"," */"," clear:function () {"," this._cachedStartElementPath = this._cachedRange = this._cachedStartElement = null;"," },"," /**"," * 编辑器是否得到了选区"," * @method isFocus"," */"," isFocus:function () {"," try {"," return browser.ie && _getIERange( this ) || !browser.ie && this.getNative().rangeCount ? true : false;"," } catch ( e ) {"," return false;"," }",""," },"," /**"," * 获取选区对应的Range"," * @method getRange"," * @return { Object } 得到Range对象"," * @example"," * ```javascript"," * editor.selection.getRange();"," * ```"," */"," getRange:function () {"," var me = this;"," function optimze( range ) {"," var child = me.document.body.firstChild,"," collapsed = range.collapsed;"," while ( child && child.firstChild ) {"," range.setStart( child, 0 );"," child = child.firstChild;"," }"," if ( !range.startContainer ) {"," range.setStart( me.document.body, 0 )"," }"," if ( collapsed ) {"," range.collapse( true );"," }"," }",""," if ( me._cachedRange != null ) {"," return this._cachedRange;"," }"," var range = new baidu.editor.dom.Range( me.document );"," if ( ie && browser.ie < 9 ) {"," var nativeRange = me.getIERange();"," if ( nativeRange ) {"," //备份的_bakIERange可能已经实效了,dom树发生了变化比如从源码模式切回来,所以try一下,实效就放到body开始位置"," try{"," transformIERangeToRange( nativeRange, range );"," }catch(e){"," optimze( range );"," }",""," } else {"," optimze( range );"," }"," } else {"," var sel = me.getNative();"," if ( sel && sel.rangeCount ) {"," var firstRange = sel.getRangeAt( 0 );"," var lastRange = sel.getRangeAt( sel.rangeCount - 1 );"," range.setStart( firstRange.startContainer, firstRange.startOffset ).setEnd( lastRange.endContainer, lastRange.endOffset );"," if ( range.collapsed && domUtils.isBody( range.startContainer ) && !range.startOffset ) {"," optimze( range );"," }"," } else {"," //trace:1734 有可能已经不在dom树上了,标识的节点"," if ( this._bakRange && domUtils.inDoc( this._bakRange.startContainer, this.document ) ){"," return this._bakRange;"," }"," optimze( range );"," }"," }"," return this._bakRange = range;"," },"," /**"," * 获取开始元素,用于状态反射"," * @method getStart"," * @return { Element } 获得开始元素"," * @example"," * ```javascript"," * editor.selection.getStart();"," * ```"," */"," getStart:function () {"," if ( this._cachedStartElement ) {"," return this._cachedStartElement;"," }"," var range = ie ? this.getIERange() : this.getRange(),"," tmpRange,"," start, tmp, parent;"," if ( ie ) {"," if ( !range ) {"," //todo 给第一个值可能会有问题"," return this.document.body.firstChild;"," }"," //control元素"," if ( range.item ){"," return range.item( 0 );"," }"," tmpRange = range.duplicate();"," //修正ie下<b>x</b>[xx] 闭合后 <b>x|</b>xx"," tmpRange.text.length > 0 && tmpRange.moveStart( 'character', 1 );"," tmpRange.collapse( 1 );"," start = tmpRange.parentElement();"," parent = tmp = range.parentElement();"," while ( tmp = tmp.parentNode ) {"," if ( tmp == start ) {"," start = parent;"," break;"," }"," }"," } else {"," range.shrinkBoundary();"," start = range.startContainer;"," if ( start.nodeType == 1 && start.hasChildNodes() ){"," start = start.childNodes[Math.min( start.childNodes.length - 1, range.startOffset )];"," }"," if ( start.nodeType == 3 ){"," return start.parentNode;"," }"," }"," return start;"," },"," /**"," * 得到选区中的文本"," * @method getText"," * @return { String } 选区中包含的文本"," * @example"," * ```javascript"," * editor.selection.getText();"," * ```"," */"," getText:function () {"," var nativeSel, nativeRange;"," if ( this.isFocus() && (nativeSel = this.getNative()) ) {"," nativeRange = browser.ie ? nativeSel.createRange() : nativeSel.getRangeAt( 0 );"," return browser.ie ? nativeRange.text : nativeRange.toString();"," }"," return '';"," },"," /**"," * 清除选区"," * @method clearRange"," * @example"," * ```javascript"," * editor.selection.clearRange();"," * ```"," */"," clearRange : function(){"," this.getNative()[browser.ie ? 'empty' : 'removeAllRanges']();"," }"," };","})();"]; +_$jscoverage['core/Selection.js'][13]++; +(function () { + _$jscoverage['core/Selection.js'][15]++; + function getBoundaryInformation(range, start) { + _$jscoverage['core/Selection.js'][16]++; + var getIndex = domUtils.getNodeIndex; + _$jscoverage['core/Selection.js'][17]++; + range = range.duplicate(); + _$jscoverage['core/Selection.js'][18]++; + range.collapse(start); + _$jscoverage['core/Selection.js'][19]++; + var parent = range.parentElement(); + _$jscoverage['core/Selection.js'][21]++; + if ((! parent.hasChildNodes())) { + _$jscoverage['core/Selection.js'][22]++; + return ({container: parent, offset: 0}); + } + _$jscoverage['core/Selection.js'][24]++; + var siblings = parent.children, child, testRange = range.duplicate(), startIndex = 0, endIndex = (siblings.length - 1), index = -1, distance; + _$jscoverage['core/Selection.js'][29]++; + while ((startIndex <= endIndex)) { + _$jscoverage['core/Selection.js'][30]++; + index = Math.floor(((startIndex + endIndex) / 2)); + _$jscoverage['core/Selection.js'][31]++; + child = siblings[index]; + _$jscoverage['core/Selection.js'][32]++; + testRange.moveToElementText(child); + _$jscoverage['core/Selection.js'][33]++; + var position = testRange.compareEndPoints("StartToStart", range); + _$jscoverage['core/Selection.js'][34]++; + if ((position > 0)) { + _$jscoverage['core/Selection.js'][35]++; + endIndex = (index - 1); + } + else { + _$jscoverage['core/Selection.js'][36]++; + if ((position < 0)) { + _$jscoverage['core/Selection.js'][37]++; + startIndex = (index + 1); + } + else { + _$jscoverage['core/Selection.js'][40]++; + return ({container: parent, offset: getIndex(child)}); + } + } +} + _$jscoverage['core/Selection.js'][43]++; + if ((index == -1)) { + _$jscoverage['core/Selection.js'][44]++; + testRange.moveToElementText(parent); + _$jscoverage['core/Selection.js'][45]++; + testRange.setEndPoint("StartToStart", range); + _$jscoverage['core/Selection.js'][46]++; + distance = testRange.text.replace(/(\r\n|\r)/g, "\n").length; + _$jscoverage['core/Selection.js'][47]++; + siblings = parent.childNodes; + _$jscoverage['core/Selection.js'][48]++; + if ((! distance)) { + _$jscoverage['core/Selection.js'][49]++; + child = siblings[(siblings.length - 1)]; + _$jscoverage['core/Selection.js'][50]++; + return ({container: child, offset: child.nodeValue.length}); + } + _$jscoverage['core/Selection.js'][53]++; + var i = siblings.length; + _$jscoverage['core/Selection.js'][54]++; + while ((distance > 0)) { + _$jscoverage['core/Selection.js'][55]++; + distance -= siblings[(--i)].nodeValue.length; +} + _$jscoverage['core/Selection.js'][57]++; + return ({container: siblings[i], offset: (- distance)}); + } + _$jscoverage['core/Selection.js'][59]++; + testRange.collapse((position > 0)); + _$jscoverage['core/Selection.js'][60]++; + testRange.setEndPoint(((position > 0)? "StartToStart": "EndToStart"), range); + _$jscoverage['core/Selection.js'][61]++; + distance = testRange.text.replace(/(\r\n|\r)/g, "\n").length; + _$jscoverage['core/Selection.js'][62]++; + if ((! distance)) { + _$jscoverage['core/Selection.js'][63]++; + return ((dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName])? {container: parent, offset: (getIndex(child) + ((position > 0)? 0: 1))}: {container: child, offset: ((position > 0)? 0: child.childNodes.length)}); + } + _$jscoverage['core/Selection.js'][67]++; + while ((distance > 0)) { + _$jscoverage['core/Selection.js'][68]++; + try { + _$jscoverage['core/Selection.js'][69]++; + var pre = child; + _$jscoverage['core/Selection.js'][70]++; + child = child[((position > 0)? "previousSibling": "nextSibling")]; + _$jscoverage['core/Selection.js'][71]++; + distance -= child.nodeValue.length; + } + catch (e) { + _$jscoverage['core/Selection.js'][73]++; + return ({container: parent, offset: getIndex(pre)}); + } +} + _$jscoverage['core/Selection.js'][76]++; + return ({container: child, offset: ((position > 0)? (- distance): (child.nodeValue.length + distance))}); +} + _$jscoverage['core/Selection.js'][85]++; + function transformIERangeToRange(ieRange, range) { + _$jscoverage['core/Selection.js'][86]++; + if (ieRange.item) { + _$jscoverage['core/Selection.js'][87]++; + range.selectNode(ieRange.item(0)); + } + else { + _$jscoverage['core/Selection.js'][89]++; + var bi = getBoundaryInformation(ieRange, true); + _$jscoverage['core/Selection.js'][90]++; + range.setStart(bi.container, bi.offset); + _$jscoverage['core/Selection.js'][91]++; + if ((ieRange.compareEndPoints("StartToEnd", ieRange) != 0)) { + _$jscoverage['core/Selection.js'][92]++; + bi = getBoundaryInformation(ieRange, false); + _$jscoverage['core/Selection.js'][93]++; + range.setEnd(bi.container, bi.offset); + } + } + _$jscoverage['core/Selection.js'][96]++; + return range; +} + _$jscoverage['core/Selection.js'][104]++; + function _getIERange(sel) { + _$jscoverage['core/Selection.js'][105]++; + var ieRange; + _$jscoverage['core/Selection.js'][107]++; + try { + _$jscoverage['core/Selection.js'][108]++; + ieRange = sel.getNative().createRange(); + } + catch (e) { + _$jscoverage['core/Selection.js'][110]++; + return null; + } + _$jscoverage['core/Selection.js'][112]++; + var el = (ieRange.item? ieRange.item(0): ieRange.parentElement()); + _$jscoverage['core/Selection.js'][113]++; + if (((el.ownerDocument || el) === sel.document)) { + _$jscoverage['core/Selection.js'][114]++; + return ieRange; + } + _$jscoverage['core/Selection.js'][116]++; + return null; +} + _$jscoverage['core/Selection.js'][119]++; + var Selection = (dom.Selection = (function (doc) { + _$jscoverage['core/Selection.js'][120]++; + var me = this, iframe; + _$jscoverage['core/Selection.js'][121]++; + me.document = doc; + _$jscoverage['core/Selection.js'][122]++; + if (ie) { + _$jscoverage['core/Selection.js'][123]++; + iframe = domUtils.getWindow(doc).frameElement; + _$jscoverage['core/Selection.js'][124]++; + domUtils.on(iframe, "beforedeactivate", (function () { + _$jscoverage['core/Selection.js'][125]++; + me._bakIERange = me.getIERange(); +})); + _$jscoverage['core/Selection.js'][127]++; + domUtils.on(iframe, "activate", (function () { + _$jscoverage['core/Selection.js'][128]++; + try { + _$jscoverage['core/Selection.js'][129]++; + if (((! _getIERange(me)) && me._bakIERange)) { + _$jscoverage['core/Selection.js'][130]++; + me._bakIERange.select(); + } + } + catch (ex) { + } + _$jscoverage['core/Selection.js'][134]++; + me._bakIERange = null; +})); + } + _$jscoverage['core/Selection.js'][137]++; + iframe = (doc = null); +})); + _$jscoverage['core/Selection.js'][140]++; + Selection.prototype = {getNative: (function () { + _$jscoverage['core/Selection.js'][151]++; + var doc = this.document; + _$jscoverage['core/Selection.js'][152]++; + try { + _$jscoverage['core/Selection.js'][153]++; + return ((! doc)? null: ((ie && (browser.ie < 9))? doc.selection: domUtils.getWindow(doc).getSelection())); + } + catch (e) { + _$jscoverage['core/Selection.js'][155]++; + return null; + } +}), getIERange: (function () { + _$jscoverage['core/Selection.js'][168]++; + var ieRange = _getIERange(this); + _$jscoverage['core/Selection.js'][169]++; + if ((! ieRange)) { + _$jscoverage['core/Selection.js'][170]++; + if (this._bakIERange) { + _$jscoverage['core/Selection.js'][171]++; + return this._bakIERange; + } + } + _$jscoverage['core/Selection.js'][174]++; + return ieRange; +}), cache: (function () { + _$jscoverage['core/Selection.js'][182]++; + this.clear(); + _$jscoverage['core/Selection.js'][183]++; + this._cachedRange = this.getRange(); + _$jscoverage['core/Selection.js'][184]++; + this._cachedStartElement = this.getStart(); + _$jscoverage['core/Selection.js'][185]++; + this._cachedStartElementPath = this.getStartElementPath(); +}), getStartElementPath: (function () { + _$jscoverage['core/Selection.js'][198]++; + if (this._cachedStartElementPath) { + _$jscoverage['core/Selection.js'][199]++; + return this._cachedStartElementPath; + } + _$jscoverage['core/Selection.js'][201]++; + var start = this.getStart(); + _$jscoverage['core/Selection.js'][202]++; + if (start) { + _$jscoverage['core/Selection.js'][203]++; + return domUtils.findParents(start, true, null, true); + } + _$jscoverage['core/Selection.js'][205]++; + return []; +}), clear: (function () { + _$jscoverage['core/Selection.js'][212]++; + this._cachedStartElementPath = (this._cachedRange = (this._cachedStartElement = null)); +}), isFocus: (function () { + _$jscoverage['core/Selection.js'][219]++; + try { + _$jscoverage['core/Selection.js'][220]++; + return (((browser.ie && _getIERange(this)) || ((! browser.ie) && this.getNative().rangeCount))? true: false); + } + catch (e) { + _$jscoverage['core/Selection.js'][222]++; + return false; + } +}), getRange: (function () { + _$jscoverage['core/Selection.js'][236]++; + var me = this; + _$jscoverage['core/Selection.js'][237]++; + function optimze(range) { + _$jscoverage['core/Selection.js'][238]++; + var child = me.document.body.firstChild, collapsed = range.collapsed; + _$jscoverage['core/Selection.js'][240]++; + while ((child && child.firstChild)) { + _$jscoverage['core/Selection.js'][241]++; + range.setStart(child, 0); + _$jscoverage['core/Selection.js'][242]++; + child = child.firstChild; +} + _$jscoverage['core/Selection.js'][244]++; + if ((! range.startContainer)) { + _$jscoverage['core/Selection.js'][245]++; + range.setStart(me.document.body, 0); + } + _$jscoverage['core/Selection.js'][247]++; + if (collapsed) { + _$jscoverage['core/Selection.js'][248]++; + range.collapse(true); + } +} + _$jscoverage['core/Selection.js'][252]++; + if ((me._cachedRange != null)) { + _$jscoverage['core/Selection.js'][253]++; + return this._cachedRange; + } + _$jscoverage['core/Selection.js'][255]++; + var range = new (baidu.editor.dom.Range)(me.document); + _$jscoverage['core/Selection.js'][256]++; + if ((ie && (browser.ie < 9))) { + _$jscoverage['core/Selection.js'][257]++; + var nativeRange = me.getIERange(); + _$jscoverage['core/Selection.js'][258]++; + if (nativeRange) { + _$jscoverage['core/Selection.js'][260]++; + try { + _$jscoverage['core/Selection.js'][261]++; + transformIERangeToRange(nativeRange, range); + } + catch (e) { + _$jscoverage['core/Selection.js'][263]++; + optimze(range); + } + } + else { + _$jscoverage['core/Selection.js'][267]++; + optimze(range); + } + } + else { + _$jscoverage['core/Selection.js'][270]++; + var sel = me.getNative(); + _$jscoverage['core/Selection.js'][271]++; + if ((sel && sel.rangeCount)) { + _$jscoverage['core/Selection.js'][272]++; + var firstRange = sel.getRangeAt(0); + _$jscoverage['core/Selection.js'][273]++; + var lastRange = sel.getRangeAt((sel.rangeCount - 1)); + _$jscoverage['core/Selection.js'][274]++; + range.setStart(firstRange.startContainer, firstRange.startOffset).setEnd(lastRange.endContainer, lastRange.endOffset); + _$jscoverage['core/Selection.js'][275]++; + if ((range.collapsed && domUtils.isBody(range.startContainer) && (! range.startOffset))) { + _$jscoverage['core/Selection.js'][276]++; + optimze(range); + } + } + else { + _$jscoverage['core/Selection.js'][280]++; + if ((this._bakRange && domUtils.inDoc(this._bakRange.startContainer, this.document))) { + _$jscoverage['core/Selection.js'][281]++; + return this._bakRange; + } + _$jscoverage['core/Selection.js'][283]++; + optimze(range); + } + } + _$jscoverage['core/Selection.js'][286]++; + return (this._bakRange = range); +}), getStart: (function () { + _$jscoverage['core/Selection.js'][298]++; + if (this._cachedStartElement) { + _$jscoverage['core/Selection.js'][299]++; + return this._cachedStartElement; + } + _$jscoverage['core/Selection.js'][301]++; + var range = (ie? this.getIERange(): this.getRange()), tmpRange, start, tmp, parent; + _$jscoverage['core/Selection.js'][304]++; + if (ie) { + _$jscoverage['core/Selection.js'][305]++; + if ((! range)) { + _$jscoverage['core/Selection.js'][307]++; + return this.document.body.firstChild; + } + _$jscoverage['core/Selection.js'][310]++; + if (range.item) { + _$jscoverage['core/Selection.js'][311]++; + return range.item(0); + } + _$jscoverage['core/Selection.js'][313]++; + tmpRange = range.duplicate(); + _$jscoverage['core/Selection.js'][315]++; + ((tmpRange.text.length > 0) && tmpRange.moveStart("character", 1)); + _$jscoverage['core/Selection.js'][316]++; + tmpRange.collapse(1); + _$jscoverage['core/Selection.js'][317]++; + start = tmpRange.parentElement(); + _$jscoverage['core/Selection.js'][318]++; + parent = (tmp = range.parentElement()); + _$jscoverage['core/Selection.js'][319]++; + while ((tmp = tmp.parentNode)) { + _$jscoverage['core/Selection.js'][320]++; + if ((tmp == start)) { + _$jscoverage['core/Selection.js'][321]++; + start = parent; + _$jscoverage['core/Selection.js'][322]++; + break; + } +} + } + else { + _$jscoverage['core/Selection.js'][326]++; + range.shrinkBoundary(); + _$jscoverage['core/Selection.js'][327]++; + start = range.startContainer; + _$jscoverage['core/Selection.js'][328]++; + if (((start.nodeType == 1) && start.hasChildNodes())) { + _$jscoverage['core/Selection.js'][329]++; + start = start.childNodes[Math.min((start.childNodes.length - 1), range.startOffset)]; + } + _$jscoverage['core/Selection.js'][331]++; + if ((start.nodeType == 3)) { + _$jscoverage['core/Selection.js'][332]++; + return start.parentNode; + } + } + _$jscoverage['core/Selection.js'][335]++; + return start; +}), getText: (function () { + _$jscoverage['core/Selection.js'][347]++; + var nativeSel, nativeRange; + _$jscoverage['core/Selection.js'][348]++; + if ((this.isFocus() && (nativeSel = this.getNative()))) { + _$jscoverage['core/Selection.js'][349]++; + nativeRange = (browser.ie? nativeSel.createRange(): nativeSel.getRangeAt(0)); + _$jscoverage['core/Selection.js'][350]++; + return (browser.ie? nativeRange.text: nativeRange.toString()); + } + _$jscoverage['core/Selection.js'][352]++; + return ""; +}), clearRange: (function () { + _$jscoverage['core/Selection.js'][363]++; + (this.getNative()[(browser.ie? "empty": "removeAllRanges")])(); +})}; +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/ajax.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/ajax.js new file mode 100644 index 000000000..ef9d21189 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/ajax.js @@ -0,0 +1,203 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['core/ajax.js']) { + _$jscoverage['core/ajax.js'] = []; + _$jscoverage['core/ajax.js'][11] = 0; + _$jscoverage['core/ajax.js'][14] = 0; + _$jscoverage['core/ajax.js'][15] = 0; + _$jscoverage['core/ajax.js'][16] = 0; + _$jscoverage['core/ajax.js'][17] = 0; + _$jscoverage['core/ajax.js'][19] = 0; + _$jscoverage['core/ajax.js'][20] = 0; + _$jscoverage['core/ajax.js'][21] = 0; + _$jscoverage['core/ajax.js'][25] = 0; + _$jscoverage['core/ajax.js'][32] = 0; + _$jscoverage['core/ajax.js'][33] = 0; + _$jscoverage['core/ajax.js'][34] = 0; + _$jscoverage['core/ajax.js'][36] = 0; + _$jscoverage['core/ajax.js'][38] = 0; + _$jscoverage['core/ajax.js'][39] = 0; + _$jscoverage['core/ajax.js'][42] = 0; + _$jscoverage['core/ajax.js'][47] = 0; + _$jscoverage['core/ajax.js'][106] = 0; + _$jscoverage['core/ajax.js'][121] = 0; + _$jscoverage['core/ajax.js'][122] = 0; + _$jscoverage['core/ajax.js'][123] = 0; + _$jscoverage['core/ajax.js'][125] = 0; + _$jscoverage['core/ajax.js'][126] = 0; + _$jscoverage['core/ajax.js'][128] = 0; + _$jscoverage['core/ajax.js'][130] = 0; + _$jscoverage['core/ajax.js'][131] = 0; + _$jscoverage['core/ajax.js'][134] = 0; + _$jscoverage['core/ajax.js'][135] = 0; + _$jscoverage['core/ajax.js'][136] = 0; + _$jscoverage['core/ajax.js'][137] = 0; + _$jscoverage['core/ajax.js'][138] = 0; + _$jscoverage['core/ajax.js'][142] = 0; + _$jscoverage['core/ajax.js'][143] = 0; + _$jscoverage['core/ajax.js'][144] = 0; + _$jscoverage['core/ajax.js'][145] = 0; + _$jscoverage['core/ajax.js'][146] = 0; + _$jscoverage['core/ajax.js'][147] = 0; + _$jscoverage['core/ajax.js'][148] = 0; + _$jscoverage['core/ajax.js'][150] = 0; + _$jscoverage['core/ajax.js'][154] = 0; + _$jscoverage['core/ajax.js'][155] = 0; + _$jscoverage['core/ajax.js'][156] = 0; + _$jscoverage['core/ajax.js'][158] = 0; +} +_$jscoverage['core/ajax.js'].source = ["/**"," * @file"," * @module UE.ajax"," * @since 1.2.6.1"," */","","/**"," * 提供对ajax请求的支持"," * @module UE.ajax"," */","UE.ajax = function() {",""," //创建一个ajaxRequest对象"," var fnStr = 'XMLHttpRequest()';"," try {"," new ActiveXObject(\"Msxml2.XMLHTTP\");"," fnStr = 'ActiveXObject(\\'Msxml2.XMLHTTP\\')';"," } catch (e) {"," try {"," new ActiveXObject(\"Microsoft.XMLHTTP\");"," fnStr = 'ActiveXObject(\\'Microsoft.XMLHTTP\\')'"," } catch (e) {"," }"," }"," var creatAjaxRequest = new Function('return new ' + fnStr);","",""," /*"," * 将json参数转化成适合ajax提交的参数列表"," * @param json"," */"," function json2str(json) {"," var strArr = [];"," for (var i in json) {"," //忽略默认的几个参数"," if(i==\"method\" || i==\"timeout\" || i==\"async\") continue;"," //传递过来的对象和函数不在提交之列"," if (!((typeof json[i]).toLowerCase() == \"function\" || (typeof json[i]).toLowerCase() == \"object\")) {"," strArr.push( encodeURIComponent(i) + \"=\"+encodeURIComponent(json[i]) );"," }"," }"," return strArr.join(\"&\");",""," }","",""," return {"," /**"," * 根据给定的参数项,向指定的url发起一个ajax请求。 ajax请求完成后,会根据请求结果调用相应回调: 如果请求"," * 成功, 则调用onsuccess回调, 失败则调用 onerror 回调"," * @method request"," * @param { URLString } url ajax请求的url地址"," * @param { KeyValueMap } ajaxOptions ajax请求选项的键值对,支持的选项如下:"," * @example"," * ```javascript"," * //向sayhello.php发起一个异步的Ajax GET请求, 请求超时时间为10s, 请求完成后执行相应的回调。"," * UE.ajax.requeset( 'sayhello.php', {"," *"," * //请求方法。可选值: 'GET', 'POST',默认值是'POST'"," * method: 'GET',"," *"," * //超时时间。 默认为5000, 单位是ms"," * timeout: 10000,"," *"," * //是否是异步请求。 true为异步请求, false为同步请求"," * async: true,"," *"," * //请求携带的数据。如果请求为GET请求, data会经过stringify后附加到请求url之后。"," * data: {"," * name: 'ueditor'"," * },"," *"," * //请求成功后的回调, 该回调接受当前的XMLHttpRequest对象作为参数。"," * onsuccess: function ( xhr ) {"," * console.log( xhr.responseText );"," * },"," *"," * //请求失败或者超时后的回调。"," * onerror: function ( xhr ) {"," * alert( 'Ajax请求失败' );"," * }"," *"," * } );"," * ```"," */",""," /**"," * 根据给定的参数项发起一个ajax请求, 参数项里必须包含一个url地址。 ajax请求完成后,会根据请求结果调用相应回调: 如果请求"," * 成功, 则调用onsuccess回调, 失败则调用 onerror 回调。"," * @method request"," * @warning 如果在参数项里未提供一个key为“url”的地址值,则该请求将直接退出。"," * @param { KeyValueMap } ajaxOptions ajax请求选项的键值对,支持的选项如下:"," * @example"," * ```javascript"," *"," * //向sayhello.php发起一个异步的Ajax POST请求, 请求超时时间为5s, 请求完成后不执行任何回调。"," * UE.ajax.requeset( 'sayhello.php', {"," *"," * //请求的地址, 该项是必须的。"," * url: 'sayhello.php'"," *"," * } );"," * ```"," */","\t\trequest:function(url, ajaxOptions) {"," var ajaxRequest = creatAjaxRequest(),"," //是否超时"," timeIsOut = false,"," //默认参数"," defaultAjaxOptions = {"," method:\"POST\","," timeout:5000,"," async:true,"," data:{},//需要传递对象的话只能覆盖"," onsuccess:function() {"," },"," onerror:function() {"," }"," };","","\t\t\tif (typeof url === \"object\") {","\t\t\t\tajaxOptions = url;","\t\t\t\turl = ajaxOptions.url;","\t\t\t}","\t\t\tif (!ajaxRequest || !url) return;","\t\t\tvar ajaxOpts = ajaxOptions ? utils.extend(defaultAjaxOptions,ajaxOptions) : defaultAjaxOptions;","","\t\t\tvar submitStr = json2str(ajaxOpts); // { name:\"Jim\",city:\"Beijing\" } --> \"name=Jim&city=Beijing\"","\t\t\t//如果用户直接通过data参数传递json对象过来,则也要将此json对象转化为字符串","\t\t\tif (!utils.isEmptyObject(ajaxOpts.data)){"," submitStr += (submitStr? \"&\":\"\") + json2str(ajaxOpts.data);","\t\t\t}"," //超时检测"," var timerID = setTimeout(function() {"," if (ajaxRequest.readyState != 4) {"," timeIsOut = true;"," ajaxRequest.abort();"," clearTimeout(timerID);"," }"," }, ajaxOpts.timeout);","","\t\t\tvar method = ajaxOpts.method.toUpperCase();"," var str = url + (url.indexOf(\"?\")==-1?\"?\":\"&\") + (method==\"POST\"?\"\":submitStr+ \"&noCache=\" + +new Date);","\t\t\tajaxRequest.open(method, str, ajaxOpts.async);","\t\t\tajaxRequest.onreadystatechange = function() {","\t\t\t\tif (ajaxRequest.readyState == 4) {","\t\t\t\t\tif (!timeIsOut && ajaxRequest.status == 200) {","\t\t\t\t\t\tajaxOpts.onsuccess(ajaxRequest);","\t\t\t\t\t} else {","\t\t\t\t\t\tajaxOpts.onerror(ajaxRequest);","\t\t\t\t\t}","\t\t\t\t}","\t\t\t};","\t\t\tif (method == \"POST\") {","\t\t\t\tajaxRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');","\t\t\t\tajaxRequest.send(submitStr);","\t\t\t} else {","\t\t\t\tajaxRequest.send(null);","\t\t\t}","\t\t}","\t};","","","}();"]; +_$jscoverage['core/ajax.js'][11]++; +UE.ajax = (function () { + _$jscoverage['core/ajax.js'][14]++; + var fnStr = "XMLHttpRequest()"; + _$jscoverage['core/ajax.js'][15]++; + try { + _$jscoverage['core/ajax.js'][16]++; + new ActiveXObject("Msxml2.XMLHTTP"); + _$jscoverage['core/ajax.js'][17]++; + fnStr = "ActiveXObject('Msxml2.XMLHTTP')"; + } + catch (e) { + _$jscoverage['core/ajax.js'][19]++; + try { + _$jscoverage['core/ajax.js'][20]++; + new ActiveXObject("Microsoft.XMLHTTP"); + _$jscoverage['core/ajax.js'][21]++; + fnStr = "ActiveXObject('Microsoft.XMLHTTP')"; + } + catch (e) { + } + } + _$jscoverage['core/ajax.js'][25]++; + var creatAjaxRequest = new Function(("return new " + fnStr)); + _$jscoverage['core/ajax.js'][32]++; + function json2str(json) { + _$jscoverage['core/ajax.js'][33]++; + var strArr = []; + _$jscoverage['core/ajax.js'][34]++; + for (var i in json) { + _$jscoverage['core/ajax.js'][36]++; + if (((i == "method") || (i == "timeout") || (i == "async"))) { + _$jscoverage['core/ajax.js'][36]++; + continue; + } + _$jscoverage['core/ajax.js'][38]++; + if ((! (((typeof json[i]).toLowerCase() == "function") || ((typeof json[i]).toLowerCase() == "object")))) { + _$jscoverage['core/ajax.js'][39]++; + strArr.push((encodeURIComponent(i) + "=" + encodeURIComponent(json[i]))); + } +} + _$jscoverage['core/ajax.js'][42]++; + return strArr.join("&"); +} + _$jscoverage['core/ajax.js'][47]++; + return ({request: (function (url, ajaxOptions) { + _$jscoverage['core/ajax.js'][106]++; + var ajaxRequest = creatAjaxRequest(), timeIsOut = false, defaultAjaxOptions = {method: "POST", timeout: 5000, async: true, data: {}, onsuccess: (function () { +}), onerror: (function () { +})}; + _$jscoverage['core/ajax.js'][121]++; + if (((typeof url) === "object")) { + _$jscoverage['core/ajax.js'][122]++; + ajaxOptions = url; + _$jscoverage['core/ajax.js'][123]++; + url = ajaxOptions.url; + } + _$jscoverage['core/ajax.js'][125]++; + if (((! ajaxRequest) || (! url))) { + _$jscoverage['core/ajax.js'][125]++; + return; + } + _$jscoverage['core/ajax.js'][126]++; + var ajaxOpts = (ajaxOptions? utils.extend(defaultAjaxOptions, ajaxOptions): defaultAjaxOptions); + _$jscoverage['core/ajax.js'][128]++; + var submitStr = json2str(ajaxOpts); + _$jscoverage['core/ajax.js'][130]++; + if ((! utils.isEmptyObject(ajaxOpts.data))) { + _$jscoverage['core/ajax.js'][131]++; + submitStr += ((submitStr? "&": "") + json2str(ajaxOpts.data)); + } + _$jscoverage['core/ajax.js'][134]++; + var timerID = setTimeout((function () { + _$jscoverage['core/ajax.js'][135]++; + if ((ajaxRequest.readyState != 4)) { + _$jscoverage['core/ajax.js'][136]++; + timeIsOut = true; + _$jscoverage['core/ajax.js'][137]++; + ajaxRequest.abort(); + _$jscoverage['core/ajax.js'][138]++; + clearTimeout(timerID); + } +}), ajaxOpts.timeout); + _$jscoverage['core/ajax.js'][142]++; + var method = ajaxOpts.method.toUpperCase(); + _$jscoverage['core/ajax.js'][143]++; + var str = (url + ((url.indexOf("?") == -1)? "?": "&") + ((method == "POST")? "": (submitStr + "&noCache=" + (+ new Date())))); + _$jscoverage['core/ajax.js'][144]++; + ajaxRequest.open(method, str, ajaxOpts.async); + _$jscoverage['core/ajax.js'][145]++; + ajaxRequest.onreadystatechange = (function () { + _$jscoverage['core/ajax.js'][146]++; + if ((ajaxRequest.readyState == 4)) { + _$jscoverage['core/ajax.js'][147]++; + if (((! timeIsOut) && (ajaxRequest.status == 200))) { + _$jscoverage['core/ajax.js'][148]++; + ajaxOpts.onsuccess(ajaxRequest); + } + else { + _$jscoverage['core/ajax.js'][150]++; + ajaxOpts.onerror(ajaxRequest); + } + } +}); + _$jscoverage['core/ajax.js'][154]++; + if ((method == "POST")) { + _$jscoverage['core/ajax.js'][155]++; + ajaxRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + _$jscoverage['core/ajax.js'][156]++; + ajaxRequest.send(submitStr); + } + else { + _$jscoverage['core/ajax.js'][158]++; + ajaxRequest.send(null); + } +})}); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/browser.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/browser.js new file mode 100644 index 000000000..368582eb5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/browser.js @@ -0,0 +1,135 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['core/browser.js']) { + _$jscoverage['core/browser.js'] = []; + _$jscoverage['core/browser.js'][13] = 0; + _$jscoverage['core/browser.js'][14] = 0; + _$jscoverage['core/browser.js'][83] = 0; + _$jscoverage['core/browser.js'][85] = 0; + _$jscoverage['core/browser.js'][88] = 0; + _$jscoverage['core/browser.js'][89] = 0; + _$jscoverage['core/browser.js'][100] = 0; + _$jscoverage['core/browser.js'][112] = 0; + _$jscoverage['core/browser.js'][124] = 0; + _$jscoverage['core/browser.js'][136] = 0; + _$jscoverage['core/browser.js'][149] = 0; + _$jscoverage['core/browser.js'][154] = 0; + _$jscoverage['core/browser.js'][155] = 0; + _$jscoverage['core/browser.js'][156] = 0; + _$jscoverage['core/browser.js'][158] = 0; + _$jscoverage['core/browser.js'][159] = 0; + _$jscoverage['core/browser.js'][173] = 0; + _$jscoverage['core/browser.js'][174] = 0; + _$jscoverage['core/browser.js'][187] = 0; + _$jscoverage['core/browser.js'][188] = 0; + _$jscoverage['core/browser.js'][193] = 0; + _$jscoverage['core/browser.js'][194] = 0; + _$jscoverage['core/browser.js'][197] = 0; + _$jscoverage['core/browser.js'][198] = 0; + _$jscoverage['core/browser.js'][213] = 0; + _$jscoverage['core/browser.js'][224] = 0; + _$jscoverage['core/browser.js'][232] = 0; + _$jscoverage['core/browser.js'][235] = 0; +} +_$jscoverage['core/browser.js'].source = ["/**"," * 浏览器判断模块"," * @file"," * @module UE.browser"," * @since 1.2.6.1"," */","","/**"," * 提供浏览器检测的模块"," * @unfile"," * @module UE.browser"," */","var browser = UE.browser = function(){"," var agent = navigator.userAgent.toLowerCase(),"," opera = window.opera,"," browser = {",""," /**"," * @property {boolean} ie 检测当前浏览器是否为IE"," * @example"," * ```javascript"," * if ( UE.browser.ie ) {"," * console.log( '当前浏览器是IE' );"," * }"," * ```"," */"," ie\t\t: !!window.ActiveXObject,",""," /**"," * @property {boolean} opera 检测当前浏览器是否为Opera"," * @example"," * ```javascript"," * if ( UE.browser.opera ) {"," * console.log( '当前浏览器是Opera' );"," * }"," * ```"," */"," opera\t: ( !!opera && opera.version ),",""," /**"," * @property {boolean} webkit 检测当前浏览器是否是webkit内核的浏览器"," * @example"," * ```javascript"," * if ( UE.browser.webkit ) {"," * console.log( '当前浏览器是webkit内核浏览器' );"," * }"," * ```"," */"," webkit\t: ( agent.indexOf( ' applewebkit/' ) > -1 ),",""," /**"," * @property {boolean} mac 检测当前浏览器是否是运行在mac平台下"," * @example"," * ```javascript"," * if ( UE.browser.mac ) {"," * console.log( '当前浏览器运行在mac平台下' );"," * }"," * ```"," */"," mac\t: ( agent.indexOf( 'macintosh' ) > -1 ),",""," /**"," * @property {boolean} quirks 检测当前浏览器是否处于“怪异模式”下"," * @example"," * ```javascript"," * if ( UE.browser.quirks ) {"," * console.log( '当前浏览器运行处于“怪异模式”' );"," * }"," * ```"," */"," quirks : ( document.compatMode == 'BackCompat' )"," };",""," /**"," * @property {boolean} gecko 检测当前浏览器内核是否是gecko内核"," * @example"," * ```javascript"," * if ( UE.browser.gecko ) {"," * console.log( '当前浏览器内核是gecko内核' );"," * }"," * ```"," */"," browser.gecko =( navigator.product == 'Gecko' && !browser.webkit && !browser.opera );",""," var version = 0;",""," // Internet Explorer 6.0+"," if ( browser.ie ){"," version = parseFloat( agent.match( /msie (\\d+)/ )[1] );"," /**"," * @property { boolean } ie9Compat 检测浏览器模式是否为 IE9 兼容模式"," * @warning 如果浏览器不是IE, 则该值为undefined"," * @example"," * ```javascript"," * if ( UE.browser.ie9Compat ) {"," * console.log( '当前浏览器运行在IE9兼容模式下' );"," * }"," * ```"," */"," browser.ie9Compat = document.documentMode == 9;",""," /**"," * @property { boolean } ie8 检测浏览器是否是IE8浏览器"," * @warning 如果浏览器不是IE, 则该值为undefined"," * @example"," * ```javascript"," * if ( UE.browser.ie8 ) {"," * console.log( '当前浏览器是IE8浏览器' );"," * }"," * ```"," */"," browser.ie8 = !!document.documentMode;",""," /**"," * @property { boolean } ie8Compat 检测浏览器模式是否为 IE8 兼容模式"," * @warning 如果浏览器不是IE, 则该值为undefined"," * @example"," * ```javascript"," * if ( UE.browser.ie8Compat ) {"," * console.log( '当前浏览器运行在IE8兼容模式下' );"," * }"," * ```"," */"," browser.ie8Compat = document.documentMode == 8;",""," /**"," * @property { boolean } ie7Compat 检测浏览器模式是否为 IE7 兼容模式"," * @warning 如果浏览器不是IE, 则该值为undefined"," * @example"," * ```javascript"," * if ( UE.browser.ie7Compat ) {"," * console.log( '当前浏览器运行在IE7兼容模式下' );"," * }"," * ```"," */"," browser.ie7Compat = ( ( version == 7 && !document.documentMode )"," || document.documentMode == 7 );",""," /**"," * @property { boolean } ie6Compat 检测浏览器模式是否为 IE6 模式 或者怪异模式"," * @warning 如果浏览器不是IE, 则该值为undefined"," * @example"," * ```javascript"," * if ( UE.browser.ie6Compat ) {"," * console.log( '当前浏览器运行在IE6模式或者怪异模式下' );"," * }"," * ```"," */"," browser.ie6Compat = ( version < 7 || browser.quirks );",""," }",""," // Gecko."," if ( browser.gecko ){"," var geckoRelease = agent.match( /rv:([\\d\\.]+)/ );"," if ( geckoRelease )"," {"," geckoRelease = geckoRelease[1].split( '.' );"," version = geckoRelease[0] * 10000 + ( geckoRelease[1] || 0 ) * 100 + ( geckoRelease[2] || 0 ) * 1;"," }"," }",""," /**"," * @property { Number } chrome 检测当前浏览器是否为Chrome, 如果是,则返回Chrome的大版本号"," * @warning 如果浏览器不是chrome, 则该值为undefined"," * @example"," * ```javascript"," * if ( UE.browser.chrome ) {"," * console.log( '当前浏览器是Chrome' );"," * }"," * ```"," */"," if (/chrome\\/(\\d+\\.\\d)/i.test(agent)) {"," browser.chrome = + RegExp['\\x241'];"," }",""," /**"," * @property { Number } safari 检测当前浏览器是否为Safari, 如果是,则返回Safari的大版本号"," * @warning 如果浏览器不是safari, 则该值为undefined"," * @example"," * ```javascript"," * if ( UE.browser.safari ) {"," * console.log( '当前浏览器是Safari' );"," * }"," * ```"," */"," if(/(\\d+\\.\\d)?(?:\\.\\d)?\\s+safari\\/?(\\d+\\.\\d+)?/i.test(agent) && !/chrome/i.test(agent)){"," \tbrowser.safari = + (RegExp['\\x241'] || RegExp['\\x242']);"," }","",""," // Opera 9.50+"," if ( browser.opera )"," version = parseFloat( opera.version() );",""," // WebKit 522+ (Safari 3+)"," if ( browser.webkit )"," version = parseFloat( agent.match( / applewebkit\\/(\\d+)/ )[1] );",""," /**"," * @property { Number } version 检测当前浏览器版本号"," * @remind"," * <ul>"," * <li>IE系列返回值为5,6,7,8,9,10等</li>"," * <li>gecko系列会返回10900,158900等</li>"," * <li>webkit系列会返回其build号 (如 522等)</li>"," * </ul>"," * @example"," * ```javascript"," * console.log( '当前浏览器版本号是: ' + UE.browser.version );"," * ```"," */"," browser.version = version;",""," /**"," * @property { boolean } isCompatible 检测当前浏览器是否能够与UEditor良好兼容"," * @example"," * ```javascript"," * if ( UE.browser.isCompatible ) {"," * console.log( '浏览器与UEditor能够良好兼容' );"," * }"," * ```"," */"," browser.isCompatible ="," !browser.mobile && ("," ( browser.ie && version >= 6 ) ||"," ( browser.gecko && version >= 10801 ) ||"," ( browser.opera && version >= 9.5 ) ||"," ( browser.air && version >= 1 ) ||"," ( browser.webkit && version >= 522 ) ||"," false );"," return browser;","}();","//快捷方式","var ie = browser.ie,"," webkit = browser.webkit,"," gecko = browser.gecko,"," opera = browser.opera;"]; +_$jscoverage['core/browser.js'][13]++; +var browser = (UE.browser = (function () { + _$jscoverage['core/browser.js'][14]++; + var agent = navigator.userAgent.toLowerCase(), opera = window.opera, browser = {ie: (! (! window.ActiveXObject)), opera: ((! (! opera)) && opera.version), webkit: (agent.indexOf(" applewebkit/") > -1), mac: (agent.indexOf("macintosh") > -1), quirks: (document.compatMode == "BackCompat")}; + _$jscoverage['core/browser.js'][83]++; + browser.gecko = ((navigator.product == "Gecko") && (! browser.webkit) && (! browser.opera)); + _$jscoverage['core/browser.js'][85]++; + var version = 0; + _$jscoverage['core/browser.js'][88]++; + if (browser.ie) { + _$jscoverage['core/browser.js'][89]++; + version = parseFloat(agent.match(/msie (\d+)/)[1]); + _$jscoverage['core/browser.js'][100]++; + browser.ie9Compat = (document.documentMode == 9); + _$jscoverage['core/browser.js'][112]++; + browser.ie8 = (! (! document.documentMode)); + _$jscoverage['core/browser.js'][124]++; + browser.ie8Compat = (document.documentMode == 8); + _$jscoverage['core/browser.js'][136]++; + browser.ie7Compat = (((version == 7) && (! document.documentMode)) || (document.documentMode == 7)); + _$jscoverage['core/browser.js'][149]++; + browser.ie6Compat = ((version < 7) || browser.quirks); + } + _$jscoverage['core/browser.js'][154]++; + if (browser.gecko) { + _$jscoverage['core/browser.js'][155]++; + var geckoRelease = agent.match(/rv:([\d\.]+)/); + _$jscoverage['core/browser.js'][156]++; + if (geckoRelease) { + _$jscoverage['core/browser.js'][158]++; + geckoRelease = geckoRelease[1].split("."); + _$jscoverage['core/browser.js'][159]++; + version = ((geckoRelease[0] * 10000) + ((geckoRelease[1] || 0) * 100) + ((geckoRelease[2] || 0) * 1)); + } + } + _$jscoverage['core/browser.js'][173]++; + if (/chrome\/(\d+\.\d)/i.test(agent)) { + _$jscoverage['core/browser.js'][174]++; + browser.chrome = (+ RegExp.$1); + } + _$jscoverage['core/browser.js'][187]++; + if ((/(\d+\.\d)?(?:\.\d)?\s+safari\/?(\d+\.\d+)?/i.test(agent) && (! /chrome/i.test(agent)))) { + _$jscoverage['core/browser.js'][188]++; + browser.safari = (+ (RegExp.$1 || RegExp.$2)); + } + _$jscoverage['core/browser.js'][193]++; + if (browser.opera) { + _$jscoverage['core/browser.js'][194]++; + version = parseFloat(opera.version()); + } + _$jscoverage['core/browser.js'][197]++; + if (browser.webkit) { + _$jscoverage['core/browser.js'][198]++; + version = parseFloat(agent.match(/ applewebkit\/(\d+)/)[1]); + } + _$jscoverage['core/browser.js'][213]++; + browser.version = version; + _$jscoverage['core/browser.js'][224]++; + browser.isCompatible = ((! browser.mobile) && ((browser.ie && (version >= 6)) || (browser.gecko && (version >= 10801)) || (browser.opera && (version >= 9.5)) || (browser.air && (version >= 1)) || (browser.webkit && (version >= 522)) || false)); + _$jscoverage['core/browser.js'][232]++; + return browser; +})()); +_$jscoverage['core/browser.js'][235]++; +var ie = browser.ie, webkit = browser.webkit, gecko = browser.gecko, opera = browser.opera; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/domUtils.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/domUtils.js new file mode 100644 index 000000000..12f26b157 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/domUtils.js @@ -0,0 +1,1846 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['core/domUtils.js']) { + _$jscoverage['core/domUtils.js'] = []; + _$jscoverage['core/domUtils.js'][15] = 0; + _$jscoverage['core/domUtils.js'][16] = 0; + _$jscoverage['core/domUtils.js'][18] = 0; + _$jscoverage['core/domUtils.js'][19] = 0; + _$jscoverage['core/domUtils.js'][20] = 0; + _$jscoverage['core/domUtils.js'][21] = 0; + _$jscoverage['core/domUtils.js'][23] = 0; + _$jscoverage['core/domUtils.js'][25] = 0; + _$jscoverage['core/domUtils.js'][26] = 0; + _$jscoverage['core/domUtils.js'][28] = 0; + _$jscoverage['core/domUtils.js'][30] = 0; + _$jscoverage['core/domUtils.js'][53] = 0; + _$jscoverage['core/domUtils.js'][120] = 0; + _$jscoverage['core/domUtils.js'][122] = 0; + _$jscoverage['core/domUtils.js'][124] = 0; + _$jscoverage['core/domUtils.js'][127] = 0; + _$jscoverage['core/domUtils.js'][128] = 0; + _$jscoverage['core/domUtils.js'][130] = 0; + _$jscoverage['core/domUtils.js'][132] = 0; + _$jscoverage['core/domUtils.js'][134] = 0; + _$jscoverage['core/domUtils.js'][136] = 0; + _$jscoverage['core/domUtils.js'][137] = 0; + _$jscoverage['core/domUtils.js'][139] = 0; + _$jscoverage['core/domUtils.js'][141] = 0; + _$jscoverage['core/domUtils.js'][143] = 0; + _$jscoverage['core/domUtils.js'][145] = 0; + _$jscoverage['core/domUtils.js'][146] = 0; + _$jscoverage['core/domUtils.js'][147] = 0; + _$jscoverage['core/domUtils.js'][149] = 0; + _$jscoverage['core/domUtils.js'][151] = 0; + _$jscoverage['core/domUtils.js'][152] = 0; + _$jscoverage['core/domUtils.js'][154] = 0; + _$jscoverage['core/domUtils.js'][155] = 0; + _$jscoverage['core/domUtils.js'][156] = 0; + _$jscoverage['core/domUtils.js'][157] = 0; + _$jscoverage['core/domUtils.js'][159] = 0; + _$jscoverage['core/domUtils.js'][163] = 0; + _$jscoverage['core/domUtils.js'][181] = 0; + _$jscoverage['core/domUtils.js'][183] = 0; + _$jscoverage['core/domUtils.js'][184] = 0; + _$jscoverage['core/domUtils.js'][185] = 0; + _$jscoverage['core/domUtils.js'][186] = 0; + _$jscoverage['core/domUtils.js'][188] = 0; + _$jscoverage['core/domUtils.js'][190] = 0; + _$jscoverage['core/domUtils.js'][192] = 0; + _$jscoverage['core/domUtils.js'][217] = 0; + _$jscoverage['core/domUtils.js'][279] = 0; + _$jscoverage['core/domUtils.js'][280] = 0; + _$jscoverage['core/domUtils.js'][281] = 0; + _$jscoverage['core/domUtils.js'][282] = 0; + _$jscoverage['core/domUtils.js'][283] = 0; + _$jscoverage['core/domUtils.js'][285] = 0; + _$jscoverage['core/domUtils.js'][288] = 0; + _$jscoverage['core/domUtils.js'][350] = 0; + _$jscoverage['core/domUtils.js'][351] = 0; + _$jscoverage['core/domUtils.js'][352] = 0; + _$jscoverage['core/domUtils.js'][365] = 0; + _$jscoverage['core/domUtils.js'][366] = 0; + _$jscoverage['core/domUtils.js'][367] = 0; + _$jscoverage['core/domUtils.js'][369] = 0; + _$jscoverage['core/domUtils.js'][380] = 0; + _$jscoverage['core/domUtils.js'][420] = 0; + _$jscoverage['core/domUtils.js'][422] = 0; + _$jscoverage['core/domUtils.js'][423] = 0; + _$jscoverage['core/domUtils.js'][424] = 0; + _$jscoverage['core/domUtils.js'][425] = 0; + _$jscoverage['core/domUtils.js'][428] = 0; + _$jscoverage['core/domUtils.js'][430] = 0; + _$jscoverage['core/domUtils.js'][437] = 0; + _$jscoverage['core/domUtils.js'][456] = 0; + _$jscoverage['core/domUtils.js'][471] = 0; + _$jscoverage['core/domUtils.js'][472] = 0; + _$jscoverage['core/domUtils.js'][490] = 0; + _$jscoverage['core/domUtils.js'][491] = 0; + _$jscoverage['core/domUtils.js'][492] = 0; + _$jscoverage['core/domUtils.js'][493] = 0; + _$jscoverage['core/domUtils.js'][494] = 0; + _$jscoverage['core/domUtils.js'][495] = 0; + _$jscoverage['core/domUtils.js'][497] = 0; + _$jscoverage['core/domUtils.js'][499] = 0; + _$jscoverage['core/domUtils.js'][500] = 0; + _$jscoverage['core/domUtils.js'][501] = 0; + _$jscoverage['core/domUtils.js'][502] = 0; + _$jscoverage['core/domUtils.js'][503] = 0; + _$jscoverage['core/domUtils.js'][505] = 0; + _$jscoverage['core/domUtils.js'][506] = 0; + _$jscoverage['core/domUtils.js'][507] = 0; + _$jscoverage['core/domUtils.js'][509] = 0; + _$jscoverage['core/domUtils.js'][523] = 0; + _$jscoverage['core/domUtils.js'][524] = 0; + _$jscoverage['core/domUtils.js'][525] = 0; + _$jscoverage['core/domUtils.js'][528] = 0; + _$jscoverage['core/domUtils.js'][529] = 0; + _$jscoverage['core/domUtils.js'][530] = 0; + _$jscoverage['core/domUtils.js'][533] = 0; + _$jscoverage['core/domUtils.js'][534] = 0; + _$jscoverage['core/domUtils.js'][554] = 0; + _$jscoverage['core/domUtils.js'][555] = 0; + _$jscoverage['core/domUtils.js'][556] = 0; + _$jscoverage['core/domUtils.js'][557] = 0; + _$jscoverage['core/domUtils.js'][559] = 0; + _$jscoverage['core/domUtils.js'][561] = 0; + _$jscoverage['core/domUtils.js'][562] = 0; + _$jscoverage['core/domUtils.js'][563] = 0; + _$jscoverage['core/domUtils.js'][564] = 0; + _$jscoverage['core/domUtils.js'][566] = 0; + _$jscoverage['core/domUtils.js'][586] = 0; + _$jscoverage['core/domUtils.js'][604] = 0; + _$jscoverage['core/domUtils.js'][605] = 0; + _$jscoverage['core/domUtils.js'][606] = 0; + _$jscoverage['core/domUtils.js'][607] = 0; + _$jscoverage['core/domUtils.js'][608] = 0; + _$jscoverage['core/domUtils.js'][610] = 0; + _$jscoverage['core/domUtils.js'][641] = 0; + _$jscoverage['core/domUtils.js'][643] = 0; + _$jscoverage['core/domUtils.js'][644] = 0; + _$jscoverage['core/domUtils.js'][645] = 0; + _$jscoverage['core/domUtils.js'][646] = 0; + _$jscoverage['core/domUtils.js'][648] = 0; + _$jscoverage['core/domUtils.js'][649] = 0; + _$jscoverage['core/domUtils.js'][653] = 0; + _$jscoverage['core/domUtils.js'][654] = 0; + _$jscoverage['core/domUtils.js'][655] = 0; + _$jscoverage['core/domUtils.js'][656] = 0; + _$jscoverage['core/domUtils.js'][658] = 0; + _$jscoverage['core/domUtils.js'][659] = 0; + _$jscoverage['core/domUtils.js'][660] = 0; + _$jscoverage['core/domUtils.js'][665] = 0; + _$jscoverage['core/domUtils.js'][669] = 0; + _$jscoverage['core/domUtils.js'][700] = 0; + _$jscoverage['core/domUtils.js'][702] = 0; + _$jscoverage['core/domUtils.js'][703] = 0; + _$jscoverage['core/domUtils.js'][704] = 0; + _$jscoverage['core/domUtils.js'][705] = 0; + _$jscoverage['core/domUtils.js'][707] = 0; + _$jscoverage['core/domUtils.js'][708] = 0; + _$jscoverage['core/domUtils.js'][709] = 0; + _$jscoverage['core/domUtils.js'][711] = 0; + _$jscoverage['core/domUtils.js'][712] = 0; + _$jscoverage['core/domUtils.js'][713] = 0; + _$jscoverage['core/domUtils.js'][714] = 0; + _$jscoverage['core/domUtils.js'][716] = 0; + _$jscoverage['core/domUtils.js'][749] = 0; + _$jscoverage['core/domUtils.js'][750] = 0; + _$jscoverage['core/domUtils.js'][752] = 0; + _$jscoverage['core/domUtils.js'][754] = 0; + _$jscoverage['core/domUtils.js'][755] = 0; + _$jscoverage['core/domUtils.js'][757] = 0; + _$jscoverage['core/domUtils.js'][758] = 0; + _$jscoverage['core/domUtils.js'][759] = 0; + _$jscoverage['core/domUtils.js'][760] = 0; + _$jscoverage['core/domUtils.js'][761] = 0; + _$jscoverage['core/domUtils.js'][763] = 0; + _$jscoverage['core/domUtils.js'][764] = 0; + _$jscoverage['core/domUtils.js'][766] = 0; + _$jscoverage['core/domUtils.js'][769] = 0; + _$jscoverage['core/domUtils.js'][770] = 0; + _$jscoverage['core/domUtils.js'][771] = 0; + _$jscoverage['core/domUtils.js'][772] = 0; + _$jscoverage['core/domUtils.js'][774] = 0; + _$jscoverage['core/domUtils.js'][777] = 0; + _$jscoverage['core/domUtils.js'][779] = 0; + _$jscoverage['core/domUtils.js'][780] = 0; + _$jscoverage['core/domUtils.js'][784] = 0; + _$jscoverage['core/domUtils.js'][785] = 0; + _$jscoverage['core/domUtils.js'][786] = 0; + _$jscoverage['core/domUtils.js'][787] = 0; + _$jscoverage['core/domUtils.js'][790] = 0; + _$jscoverage['core/domUtils.js'][791] = 0; + _$jscoverage['core/domUtils.js'][794] = 0; + _$jscoverage['core/domUtils.js'][824] = 0; + _$jscoverage['core/domUtils.js'][826] = 0; + _$jscoverage['core/domUtils.js'][827] = 0; + _$jscoverage['core/domUtils.js'][828] = 0; + _$jscoverage['core/domUtils.js'][829] = 0; + _$jscoverage['core/domUtils.js'][830] = 0; + _$jscoverage['core/domUtils.js'][831] = 0; + _$jscoverage['core/domUtils.js'][832] = 0; + _$jscoverage['core/domUtils.js'][833] = 0; + _$jscoverage['core/domUtils.js'][835] = 0; + _$jscoverage['core/domUtils.js'][836] = 0; + _$jscoverage['core/domUtils.js'][839] = 0; + _$jscoverage['core/domUtils.js'][841] = 0; + _$jscoverage['core/domUtils.js'][842] = 0; + _$jscoverage['core/domUtils.js'][844] = 0; + _$jscoverage['core/domUtils.js'][845] = 0; + _$jscoverage['core/domUtils.js'][846] = 0; + _$jscoverage['core/domUtils.js'][847] = 0; + _$jscoverage['core/domUtils.js'][849] = 0; + _$jscoverage['core/domUtils.js'][850] = 0; + _$jscoverage['core/domUtils.js'][851] = 0; + _$jscoverage['core/domUtils.js'][854] = 0; + _$jscoverage['core/domUtils.js'][885] = 0; + _$jscoverage['core/domUtils.js'][900] = 0; + _$jscoverage['core/domUtils.js'][913] = 0; + _$jscoverage['core/domUtils.js'][918] = 0; + _$jscoverage['core/domUtils.js'][919] = 0; + _$jscoverage['core/domUtils.js'][920] = 0; + _$jscoverage['core/domUtils.js'][921] = 0; + _$jscoverage['core/domUtils.js'][922] = 0; + _$jscoverage['core/domUtils.js'][923] = 0; + _$jscoverage['core/domUtils.js'][924] = 0; + _$jscoverage['core/domUtils.js'][925] = 0; + _$jscoverage['core/domUtils.js'][926] = 0; + _$jscoverage['core/domUtils.js'][928] = 0; + _$jscoverage['core/domUtils.js'][929] = 0; + _$jscoverage['core/domUtils.js'][931] = 0; + _$jscoverage['core/domUtils.js'][932] = 0; + _$jscoverage['core/domUtils.js'][934] = 0; + _$jscoverage['core/domUtils.js'][935] = 0; + _$jscoverage['core/domUtils.js'][937] = 0; + _$jscoverage['core/domUtils.js'][939] = 0; + _$jscoverage['core/domUtils.js'][940] = 0; + _$jscoverage['core/domUtils.js'][941] = 0; + _$jscoverage['core/domUtils.js'][942] = 0; + _$jscoverage['core/domUtils.js'][943] = 0; + _$jscoverage['core/domUtils.js'][944] = 0; + _$jscoverage['core/domUtils.js'][958] = 0; + _$jscoverage['core/domUtils.js'][959] = 0; + _$jscoverage['core/domUtils.js'][961] = 0; + _$jscoverage['core/domUtils.js'][962] = 0; + _$jscoverage['core/domUtils.js'][964] = 0; + _$jscoverage['core/domUtils.js'][965] = 0; + _$jscoverage['core/domUtils.js'][967] = 0; + _$jscoverage['core/domUtils.js'][970] = 0; + _$jscoverage['core/domUtils.js'][972] = 0; + _$jscoverage['core/domUtils.js'][974] = 0; + _$jscoverage['core/domUtils.js'][1000] = 0; + _$jscoverage['core/domUtils.js'][1001] = 0; + _$jscoverage['core/domUtils.js'][1002] = 0; + _$jscoverage['core/domUtils.js'][1003] = 0; + _$jscoverage['core/domUtils.js'][1006] = 0; + _$jscoverage['core/domUtils.js'][1007] = 0; + _$jscoverage['core/domUtils.js'][1019] = 0; + _$jscoverage['core/domUtils.js'][1020] = 0; + _$jscoverage['core/domUtils.js'][1021] = 0; + _$jscoverage['core/domUtils.js'][1022] = 0; + _$jscoverage['core/domUtils.js'][1025] = 0; + _$jscoverage['core/domUtils.js'][1026] = 0; + _$jscoverage['core/domUtils.js'][1027] = 0; + _$jscoverage['core/domUtils.js'][1028] = 0; + _$jscoverage['core/domUtils.js'][1029] = 0; + _$jscoverage['core/domUtils.js'][1030] = 0; + _$jscoverage['core/domUtils.js'][1031] = 0; + _$jscoverage['core/domUtils.js'][1034] = 0; + _$jscoverage['core/domUtils.js'][1035] = 0; + _$jscoverage['core/domUtils.js'][1036] = 0; + _$jscoverage['core/domUtils.js'][1037] = 0; + _$jscoverage['core/domUtils.js'][1038] = 0; + _$jscoverage['core/domUtils.js'][1039] = 0; + _$jscoverage['core/domUtils.js'][1040] = 0; + _$jscoverage['core/domUtils.js'][1044] = 0; + _$jscoverage['core/domUtils.js'][1045] = 0; + _$jscoverage['core/domUtils.js'][1047] = 0; + _$jscoverage['core/domUtils.js'][1049] = 0; + _$jscoverage['core/domUtils.js'][1050] = 0; + _$jscoverage['core/domUtils.js'][1061] = 0; + _$jscoverage['core/domUtils.js'][1062] = 0; + _$jscoverage['core/domUtils.js'][1063] = 0; + _$jscoverage['core/domUtils.js'][1065] = 0; + _$jscoverage['core/domUtils.js'][1066] = 0; + _$jscoverage['core/domUtils.js'][1067] = 0; + _$jscoverage['core/domUtils.js'][1068] = 0; + _$jscoverage['core/domUtils.js'][1069] = 0; + _$jscoverage['core/domUtils.js'][1070] = 0; + _$jscoverage['core/domUtils.js'][1071] = 0; + _$jscoverage['core/domUtils.js'][1075] = 0; + _$jscoverage['core/domUtils.js'][1106] = 0; + _$jscoverage['core/domUtils.js'][1107] = 0; + _$jscoverage['core/domUtils.js'][1108] = 0; + _$jscoverage['core/domUtils.js'][1109] = 0; + _$jscoverage['core/domUtils.js'][1111] = 0; + _$jscoverage['core/domUtils.js'][1113] = 0; + _$jscoverage['core/domUtils.js'][1114] = 0; + _$jscoverage['core/domUtils.js'][1115] = 0; + _$jscoverage['core/domUtils.js'][1116] = 0; + _$jscoverage['core/domUtils.js'][1118] = 0; + _$jscoverage['core/domUtils.js'][1120] = 0; + _$jscoverage['core/domUtils.js'][1121] = 0; + _$jscoverage['core/domUtils.js'][1125] = 0; + _$jscoverage['core/domUtils.js'][1126] = 0; + _$jscoverage['core/domUtils.js'][1127] = 0; + _$jscoverage['core/domUtils.js'][1130] = 0; + _$jscoverage['core/domUtils.js'][1189] = 0; + _$jscoverage['core/domUtils.js'][1190] = 0; + _$jscoverage['core/domUtils.js'][1191] = 0; + _$jscoverage['core/domUtils.js'][1192] = 0; + _$jscoverage['core/domUtils.js'][1193] = 0; + _$jscoverage['core/domUtils.js'][1194] = 0; + _$jscoverage['core/domUtils.js'][1196] = 0; + _$jscoverage['core/domUtils.js'][1199] = 0; + _$jscoverage['core/domUtils.js'][1202] = 0; + _$jscoverage['core/domUtils.js'][1203] = 0; + _$jscoverage['core/domUtils.js'][1218] = 0; + _$jscoverage['core/domUtils.js'][1219] = 0; + _$jscoverage['core/domUtils.js'][1221] = 0; + _$jscoverage['core/domUtils.js'][1222] = 0; + _$jscoverage['core/domUtils.js'][1224] = 0; + _$jscoverage['core/domUtils.js'][1225] = 0; + _$jscoverage['core/domUtils.js'][1226] = 0; + _$jscoverage['core/domUtils.js'][1227] = 0; + _$jscoverage['core/domUtils.js'][1232] = 0; + _$jscoverage['core/domUtils.js'][1234] = 0; + _$jscoverage['core/domUtils.js'][1235] = 0; + _$jscoverage['core/domUtils.js'][1239] = 0; + _$jscoverage['core/domUtils.js'][1286] = 0; + _$jscoverage['core/domUtils.js'][1287] = 0; + _$jscoverage['core/domUtils.js'][1288] = 0; + _$jscoverage['core/domUtils.js'][1289] = 0; + _$jscoverage['core/domUtils.js'][1291] = 0; + _$jscoverage['core/domUtils.js'][1292] = 0; + _$jscoverage['core/domUtils.js'][1294] = 0; + _$jscoverage['core/domUtils.js'][1295] = 0; + _$jscoverage['core/domUtils.js'][1297] = 0; + _$jscoverage['core/domUtils.js'][1323] = 0; + _$jscoverage['core/domUtils.js'][1349] = 0; + _$jscoverage['core/domUtils.js'][1350] = 0; + _$jscoverage['core/domUtils.js'][1351] = 0; + _$jscoverage['core/domUtils.js'][1352] = 0; + _$jscoverage['core/domUtils.js'][1355] = 0; + _$jscoverage['core/domUtils.js'][1356] = 0; + _$jscoverage['core/domUtils.js'][1358] = 0; + _$jscoverage['core/domUtils.js'][1359] = 0; + _$jscoverage['core/domUtils.js'][1361] = 0; + _$jscoverage['core/domUtils.js'][1362] = 0; + _$jscoverage['core/domUtils.js'][1364] = 0; + _$jscoverage['core/domUtils.js'][1365] = 0; + _$jscoverage['core/domUtils.js'][1367] = 0; + _$jscoverage['core/domUtils.js'][1371] = 0; + _$jscoverage['core/domUtils.js'][1398] = 0; + _$jscoverage['core/domUtils.js'][1400] = 0; + _$jscoverage['core/domUtils.js'][1401] = 0; + _$jscoverage['core/domUtils.js'][1404] = 0; + _$jscoverage['core/domUtils.js'][1405] = 0; + _$jscoverage['core/domUtils.js'][1408] = 0; + _$jscoverage['core/domUtils.js'][1410] = 0; + _$jscoverage['core/domUtils.js'][1411] = 0; + _$jscoverage['core/domUtils.js'][1412] = 0; + _$jscoverage['core/domUtils.js'][1413] = 0; + _$jscoverage['core/domUtils.js'][1414] = 0; + _$jscoverage['core/domUtils.js'][1415] = 0; + _$jscoverage['core/domUtils.js'][1416] = 0; + _$jscoverage['core/domUtils.js'][1417] = 0; + _$jscoverage['core/domUtils.js'][1419] = 0; + _$jscoverage['core/domUtils.js'][1420] = 0; + _$jscoverage['core/domUtils.js'][1425] = 0; + _$jscoverage['core/domUtils.js'][1427] = 0; + _$jscoverage['core/domUtils.js'][1471] = 0; + _$jscoverage['core/domUtils.js'][1473] = 0; + _$jscoverage['core/domUtils.js'][1474] = 0; + _$jscoverage['core/domUtils.js'][1476] = 0; + _$jscoverage['core/domUtils.js'][1477] = 0; + _$jscoverage['core/domUtils.js'][1478] = 0; + _$jscoverage['core/domUtils.js'][1480] = 0; + _$jscoverage['core/domUtils.js'][1528] = 0; + _$jscoverage['core/domUtils.js'][1529] = 0; + _$jscoverage['core/domUtils.js'][1530] = 0; + _$jscoverage['core/domUtils.js'][1531] = 0; + _$jscoverage['core/domUtils.js'][1532] = 0; + _$jscoverage['core/domUtils.js'][1581] = 0; + _$jscoverage['core/domUtils.js'][1582] = 0; + _$jscoverage['core/domUtils.js'][1584] = 0; + _$jscoverage['core/domUtils.js'][1585] = 0; + _$jscoverage['core/domUtils.js'][1586] = 0; + _$jscoverage['core/domUtils.js'][1587] = 0; + _$jscoverage['core/domUtils.js'][1590] = 0; + _$jscoverage['core/domUtils.js'][1603] = 0; + _$jscoverage['core/domUtils.js'][1628] = 0; + _$jscoverage['core/domUtils.js'][1630] = 0; + _$jscoverage['core/domUtils.js'][1631] = 0; + _$jscoverage['core/domUtils.js'][1633] = 0; + _$jscoverage['core/domUtils.js'][1635] = 0; + _$jscoverage['core/domUtils.js'][1636] = 0; + _$jscoverage['core/domUtils.js'][1638] = 0; + _$jscoverage['core/domUtils.js'][1643] = 0; + _$jscoverage['core/domUtils.js'][1644] = 0; + _$jscoverage['core/domUtils.js'][1673] = 0; + _$jscoverage['core/domUtils.js'][1674] = 0; + _$jscoverage['core/domUtils.js'][1703] = 0; + _$jscoverage['core/domUtils.js'][1704] = 0; + _$jscoverage['core/domUtils.js'][1705] = 0; + _$jscoverage['core/domUtils.js'][1735] = 0; + _$jscoverage['core/domUtils.js'][1736] = 0; + _$jscoverage['core/domUtils.js'][1737] = 0; + _$jscoverage['core/domUtils.js'][1747] = 0; + _$jscoverage['core/domUtils.js'][1748] = 0; + _$jscoverage['core/domUtils.js'][1750] = 0; + _$jscoverage['core/domUtils.js'][1798] = 0; + _$jscoverage['core/domUtils.js'][1799] = 0; + _$jscoverage['core/domUtils.js'][1800] = 0; + _$jscoverage['core/domUtils.js'][1802] = 0; + _$jscoverage['core/domUtils.js'][1803] = 0; + _$jscoverage['core/domUtils.js'][1804] = 0; + _$jscoverage['core/domUtils.js'][1806] = 0; + _$jscoverage['core/domUtils.js'][1808] = 0; + _$jscoverage['core/domUtils.js'][1822] = 0; + _$jscoverage['core/domUtils.js'][1823] = 0; + _$jscoverage['core/domUtils.js'][1839] = 0; + _$jscoverage['core/domUtils.js'][1840] = 0; + _$jscoverage['core/domUtils.js'][1841] = 0; + _$jscoverage['core/domUtils.js'][1853] = 0; + _$jscoverage['core/domUtils.js'][1854] = 0; + _$jscoverage['core/domUtils.js'][1856] = 0; + _$jscoverage['core/domUtils.js'][1862] = 0; + _$jscoverage['core/domUtils.js'][1863] = 0; + _$jscoverage['core/domUtils.js'][1869] = 0; + _$jscoverage['core/domUtils.js'][1870] = 0; + _$jscoverage['core/domUtils.js'][1876] = 0; + _$jscoverage['core/domUtils.js'][1877] = 0; + _$jscoverage['core/domUtils.js'][1878] = 0; + _$jscoverage['core/domUtils.js'][1879] = 0; + _$jscoverage['core/domUtils.js'][1880] = 0; + _$jscoverage['core/domUtils.js'][1882] = 0; + _$jscoverage['core/domUtils.js'][1883] = 0; + _$jscoverage['core/domUtils.js'][1894] = 0; + _$jscoverage['core/domUtils.js'][1905] = 0; + _$jscoverage['core/domUtils.js'][1910] = 0; + _$jscoverage['core/domUtils.js'][1914] = 0; + _$jscoverage['core/domUtils.js'][1915] = 0; + _$jscoverage['core/domUtils.js'][1916] = 0; + _$jscoverage['core/domUtils.js'][1917] = 0; + _$jscoverage['core/domUtils.js'][1918] = 0; + _$jscoverage['core/domUtils.js'][1919] = 0; + _$jscoverage['core/domUtils.js'][1922] = 0; + _$jscoverage['core/domUtils.js'][1923] = 0; + _$jscoverage['core/domUtils.js'][1924] = 0; + _$jscoverage['core/domUtils.js'][1927] = 0; + _$jscoverage['core/domUtils.js'][1928] = 0; + _$jscoverage['core/domUtils.js'][1929] = 0; + _$jscoverage['core/domUtils.js'][1931] = 0; + _$jscoverage['core/domUtils.js'][1932] = 0; + _$jscoverage['core/domUtils.js'][1933] = 0; + _$jscoverage['core/domUtils.js'][1935] = 0; + _$jscoverage['core/domUtils.js'][1936] = 0; + _$jscoverage['core/domUtils.js'][1938] = 0; + _$jscoverage['core/domUtils.js'][1939] = 0; + _$jscoverage['core/domUtils.js'][1940] = 0; + _$jscoverage['core/domUtils.js'][1941] = 0; + _$jscoverage['core/domUtils.js'][1942] = 0; + _$jscoverage['core/domUtils.js'][1944] = 0; + _$jscoverage['core/domUtils.js'][1946] = 0; + _$jscoverage['core/domUtils.js'][1947] = 0; + _$jscoverage['core/domUtils.js'][1949] = 0; + _$jscoverage['core/domUtils.js'][1950] = 0; + _$jscoverage['core/domUtils.js'][1951] = 0; + _$jscoverage['core/domUtils.js'][1953] = 0; + _$jscoverage['core/domUtils.js'][1954] = 0; + _$jscoverage['core/domUtils.js'][1956] = 0; + _$jscoverage['core/domUtils.js'][1960] = 0; + _$jscoverage['core/domUtils.js'][1987] = 0; + _$jscoverage['core/domUtils.js'][1988] = 0; + _$jscoverage['core/domUtils.js'][1989] = 0; + _$jscoverage['core/domUtils.js'][1990] = 0; + _$jscoverage['core/domUtils.js'][1991] = 0; + _$jscoverage['core/domUtils.js'][1993] = 0; + _$jscoverage['core/domUtils.js'][1994] = 0; + _$jscoverage['core/domUtils.js'][1995] = 0; + _$jscoverage['core/domUtils.js'][1998] = 0; + _$jscoverage['core/domUtils.js'][2028] = 0; + _$jscoverage['core/domUtils.js'][2029] = 0; + _$jscoverage['core/domUtils.js'][2030] = 0; + _$jscoverage['core/domUtils.js'][2031] = 0; + _$jscoverage['core/domUtils.js'][2032] = 0; + _$jscoverage['core/domUtils.js'][2033] = 0; + _$jscoverage['core/domUtils.js'][2034] = 0; + _$jscoverage['core/domUtils.js'][2036] = 0; + _$jscoverage['core/domUtils.js'][2037] = 0; + _$jscoverage['core/domUtils.js'][2065] = 0; + _$jscoverage['core/domUtils.js'][2066] = 0; + _$jscoverage['core/domUtils.js'][2067] = 0; + _$jscoverage['core/domUtils.js'][2133] = 0; + _$jscoverage['core/domUtils.js'][2134] = 0; + _$jscoverage['core/domUtils.js'][2135] = 0; + _$jscoverage['core/domUtils.js'][2137] = 0; + _$jscoverage['core/domUtils.js'][2163] = 0; + _$jscoverage['core/domUtils.js'][2174] = 0; + _$jscoverage['core/domUtils.js'][2196] = 0; + _$jscoverage['core/domUtils.js'][2266] = 0; + _$jscoverage['core/domUtils.js'][2267] = 0; + _$jscoverage['core/domUtils.js'][2268] = 0; + _$jscoverage['core/domUtils.js'][2269] = 0; + _$jscoverage['core/domUtils.js'][2270] = 0; + _$jscoverage['core/domUtils.js'][2273] = 0; + _$jscoverage['core/domUtils.js'][2274] = 0; + _$jscoverage['core/domUtils.js'][2276] = 0; + _$jscoverage['core/domUtils.js'][2280] = 0; + _$jscoverage['core/domUtils.js'][2281] = 0; + _$jscoverage['core/domUtils.js'][2282] = 0; + _$jscoverage['core/domUtils.js'][2284] = 0; + _$jscoverage['core/domUtils.js'][2285] = 0; + _$jscoverage['core/domUtils.js'][2287] = 0; + _$jscoverage['core/domUtils.js'][2288] = 0; + _$jscoverage['core/domUtils.js'][2289] = 0; + _$jscoverage['core/domUtils.js'][2290] = 0; + _$jscoverage['core/domUtils.js'][2291] = 0; + _$jscoverage['core/domUtils.js'][2293] = 0; + _$jscoverage['core/domUtils.js'][2296] = 0; + _$jscoverage['core/domUtils.js'][2297] = 0; + _$jscoverage['core/domUtils.js'][2298] = 0; + _$jscoverage['core/domUtils.js'][2299] = 0; + _$jscoverage['core/domUtils.js'][2300] = 0; + _$jscoverage['core/domUtils.js'][2301] = 0; + _$jscoverage['core/domUtils.js'][2304] = 0; + _$jscoverage['core/domUtils.js'][2307] = 0; +} +_$jscoverage['core/domUtils.js'].source = ["/**"," * Dom操作工具包"," * @file"," * @module UE.dom.domUtils"," * @since 1.2.6.1"," */","","/**"," * Dom操作工具包"," * @unfile"," * @module UE.dom.domUtils"," */","","//getNode(node, 'firstChild', 'nextSibling', startFromChild, filterFn, guard);","function getNode( node, start, ltr, startFromChild, fn, guard ) {"," var tmpNode = startFromChild && node[start],"," parent;"," !tmpNode && (tmpNode = node[ltr]);"," while (!tmpNode && (parent = (parent || node).parentNode)) {"," if (parent.tagName == 'BODY' || guard && !guard(parent)) {"," return null;"," }"," tmpNode = parent[ltr];"," }"," if (tmpNode && fn && !fn(tmpNode)) {"," return getNode(tmpNode, start, ltr, false, fn);"," }"," return tmpNode;","}","var attrFix = ie && browser.version < 9 ? {"," tabindex:\"tabIndex\","," readonly:\"readOnly\","," \"for\":\"htmlFor\","," \"class\":\"className\","," maxlength:\"maxLength\","," cellspacing:\"cellSpacing\","," cellpadding:\"cellPadding\","," rowspan:\"rowSpan\","," colspan:\"colSpan\","," usemap:\"useMap\","," frameborder:\"frameBorder\""," } : {"," tabindex:\"tabIndex\","," readonly:\"readOnly\""," },"," styleBlock = utils.listToMap(["," '-webkit-box', '-moz-box', 'block' ,"," 'list-item' , 'table' , 'table-row-group' ,"," 'table-header-group', 'table-footer-group' ,"," 'table-row' , 'table-column-group' , 'table-column' ,"," 'table-cell' , 'table-caption'"," ]);","var domUtils = dom.domUtils = {"," //节点常量"," NODE_ELEMENT:1,"," NODE_DOCUMENT:9,"," NODE_TEXT:3,"," NODE_COMMENT:8,"," NODE_DOCUMENT_FRAGMENT:11,",""," //位置关系"," POSITION_IDENTICAL:0,"," POSITION_DISCONNECTED:1,"," POSITION_FOLLOWING:2,"," POSITION_PRECEDING:4,"," POSITION_IS_CONTAINED:8,"," POSITION_CONTAINS:16,"," //ie6使用其他的会有一段空白出现"," fillChar:ie && browser.version == '6' ? '\\ufeff' : '\\u200B',"," //-------------------------Node部分--------------------------------"," keys:{"," /*Backspace*/ 8:1, /*Delete*/ 46:1,"," /*Shift*/ 16:1, /*Ctrl*/ 17:1, /*Alt*/ 18:1,"," 37:1, 38:1, 39:1, 40:1,"," 13:1 /*enter*/"," },"," /**"," * 获取节点A相对于节点B的位置关系"," * @method getPosition"," * @param { Node } nodeA 需要查询位置关系的节点A"," * @param { Node } nodeB 需要查询位置关系的节点B"," * @return { Number } 节点A与节点B的关系"," * @example"," * ```javascript"," * //output: 20"," * var position = UE.dom.domUtils.getPosition( document.documentElement, document.body );"," *"," * switch ( position ) {"," *"," * case 0:"," * console.log('元素相同');"," * break;"," * case 1:"," * console.log('两个节点在不同的文档中');"," * break;"," * case 2:"," * console.log('节点A在节点B之后');"," * break;"," * case 4;"," * console.log('节点A在节点B之前');"," * break;"," * case 8:"," * console.log('节点A被节点B包含');"," * break;"," * case 10:"," * console.log('节点A被节点B包含且节点A在节点B之后');"," * break;"," * case 16:"," * console.log('节点A包含节点B');"," * break;"," * case 20:"," * console.log('节点A包含节点B且节点A在节点B之前');"," * break;"," *"," * }"," * ```"," */"," getPosition:function (nodeA, nodeB) {"," // 如果两个节点是同一个节点"," if (nodeA === nodeB) {"," // domUtils.POSITION_IDENTICAL"," return 0;"," }"," var node,"," parentsA = [nodeA],"," parentsB = [nodeB];"," node = nodeA;"," while (node = node.parentNode) {"," // 如果nodeB是nodeA的祖先节点"," if (node === nodeB) {"," // domUtils.POSITION_IS_CONTAINED + domUtils.POSITION_FOLLOWING"," return 10;"," }"," parentsA.push(node);"," }"," node = nodeB;"," while (node = node.parentNode) {"," // 如果nodeA是nodeB的祖先节点"," if (node === nodeA) {"," // domUtils.POSITION_CONTAINS + domUtils.POSITION_PRECEDING"," return 20;"," }"," parentsB.push(node);"," }"," parentsA.reverse();"," parentsB.reverse();"," if (parentsA[0] !== parentsB[0]) {"," // domUtils.POSITION_DISCONNECTED"," return 1;"," }"," var i = -1;"," while (i++, parentsA[i] === parentsB[i]) {"," }"," nodeA = parentsA[i];"," nodeB = parentsB[i];"," while (nodeA = nodeA.nextSibling) {"," if (nodeA === nodeB) {"," // domUtils.POSITION_PRECEDING"," return 4"," }"," }"," // domUtils.POSITION_FOLLOWING"," return 2;"," },",""," /**"," * 检测节点node在父节点中的索引位置"," * @method getNodeIndex"," * @param { Node } node 需要检测的节点对象"," * @return { Number } 该节点在父节点中的位置"," */",""," /**"," * 检测节点node在父节点中的索引位置, 根据给定的mergeTextNode参数决定是否要合并多个连续的文本节点为一个节点"," * @method getNodeIndex"," * @param { Node } node 需要检测的节点对象"," * @param { Boolean } ignoreTextNode 是否忽略文本节点"," * @return { Number } 该节点在父节点中的位置"," */"," getNodeIndex:function (node, ignoreTextNode) {"," var preNode = node,"," i = 0;"," while (preNode = preNode.previousSibling) {"," if (ignoreTextNode && preNode.nodeType == 3) {"," if(preNode.nodeType != preNode.nextSibling.nodeType ){"," i++;"," }"," continue;"," }"," i++;"," }"," return i;"," },",""," /**"," * 检测节点node是否在给定doc的树上,实质上是检测该节点是否在给定的dom树上"," * @method inDoc"," * @param { Node } node 需要检测的节点对象"," * @param { DomDocument } doc 需要检测的document对象"," * @return { Boolean } 该节点node是否在给定的document的dom树上"," * @example"," * ```javascript"," *"," * var node = document.createElement(\"div\");"," *"," * //output: false"," * console.log( UE.do.domUtils.inDoc( node, document ) );"," *"," * document.body.appendChild( node );"," *"," * //output: true"," * console.log( UE.do.domUtils.inDoc( node, document ) );"," *"," * ```"," */"," inDoc:function (node, doc) {"," return domUtils.getPosition(node, doc) == 10;"," },",""," /**"," * 根据给定的过滤规则filterFn, 查找符合该过滤规则的node节点的祖先节点,"," * 查找的过程中不包含自身节点。"," * @method findParent"," * @param { Node } node 需要查找的节点"," * @param { Function } filterFn 自定义的过滤方法。"," * @warning 查找的终点是到body节点为止"," * @remind 自定义的过滤方法filterFn接受一个Node对象作为参数, 该对象代表当前执行检测的祖先节点。 如果该"," * 节点满足过滤条件, 则要求返回true, 这时将直接返回该节点作为findParent()的结果, 否则, 请返回false。"," * @return { Node | Null } 如果找到符合过滤条件的节点, 就返回该节点, 否则返回NULL"," * @example"," * ```javascript"," * var filterNode = UE.dom.domUtils.findParent( document.body.firstChild, function ( node ) {"," *"," * //由于查找的终点是body节点, 所以永远也不会匹配当前过滤器的条件, 即这里永远会返回false"," * return node.tagName === \"HTML\";"," *"," * } );"," *"," * //output: true"," * console.log( filterNode === null );"," * ```"," */",""," /**"," * 根据给定的过滤规则filterFn, 查找符合该过滤规则的node节点的祖先节点,"," * 查找的过程中根据includeSelf的值决定是否包含自身节点。"," * @method findParent"," * @param { Node } node 需要查找的节点"," * @param { Function } filterFn 自定义的过滤方法。"," * @param { Boolean } includeSelf 查找过程是否包含自身"," * @warning 查找的终点是到body节点为止"," * @remind 自定义的过滤方法filterFn接受一个Node对象作为参数, 该对象代表当前执行检测的祖先节点。 如果该"," * 节点满足过滤条件, 则要求返回true, 这时将直接返回该节点作为findParent()的结果, 否则, 请返回false。"," * @remind 如果includeSelf为true, 则过滤器第一次执行时的参数会是节点本身。"," * 反之, 过滤器第一次执行时的参数将是该节点的父节点。"," * @return { Node | Null } 如果找到符合过滤条件的节点, 就返回该节点, 否则返回NULL"," * @example"," * ```html"," * <body>"," *"," * <div id=\"test\">"," * </div>"," *"," * <script type=\"text/javascript\">"," *"," * //output: DIV, BODY"," * var filterNode = UE.dom.domUtils.findParent( document.getElementById( \"test\" ), function ( node ) {"," *"," * console.log( node.tagName );"," * return false;"," *"," * }, true );"," *"," * </script>"," * </body>"," * ```"," */"," findParent:function (node, filterFn, includeSelf) {"," if (node && !domUtils.isBody(node)) {"," node = includeSelf ? node : node.parentNode;"," while (node) {"," if (!filterFn || filterFn(node) || domUtils.isBody(node)) {"," return filterFn && !filterFn(node) && domUtils.isBody(node) ? null : node;"," }"," node = node.parentNode;"," }"," }"," return null;"," },",""," /**"," * 查找node的节点名为tagName的祖先节点, 查找过程中不包含node节点自身"," * @method findParentByTagName"," * @param { Node } node 需要查找的节点对象"," * @param { Array } tagNames 需要查找的父节点的名称数组"," * @warning 查找的终点是到body节点为止"," * @return { Node | NULL } 如果找到符合条件的节点, 则返回该节点, 否则返回NULL"," * @example"," * ```javascript"," * var node = UE.dom.domUtils.findParentByTagName( document.getElementsByTagName(\"div\")[0], [ \"BODY\" ] );"," * //output: BODY"," * console.log( node.tagName );"," * ```"," */",""," /**"," * 查找node的节点名为tagName的祖先节点, 查找过程中根据includeSelf的值决定是否包含node节点自身"," * @method findParentByTagName"," * @param { Node } node 需要查找的节点对象"," * @param { Array } tagNames 需要查找的父节点的名称数组"," * @param { Boolean } includeSelf 查找过程是否包含node节点自身"," * @warning 查找的终点是到body节点为止"," * @return { Node | NULL } 如果找到符合条件的节点, 则返回该节点, 否则返回NULL"," * @example"," * ```javascript"," * var queryTarget = document.getElementsByTagName(\"div\")[0];"," * var node = UE.dom.domUtils.findParentByTagName( queryTarget, [ \"DIV\" ], true );"," * //output: true"," * console.log( queryTarget === node );"," * ```"," */",""," /**"," * 查找node的节点名为tagName的祖先节点,并且该祖先节点不满足excludeFn过滤器的过滤要求,"," * 查找过程中根据includeSelf的值决定是否包含node节点自身,"," * @method findParentByTagName"," * @param { Node } node 需要查找的节点对象"," * @param { Array } tagNames 需要查找的父节点的名称数组"," * @param { Boolean } includeSelf 查找过程是否包含node节点自身"," * @param { Function } excludeFn 查找过程中应用的过滤器, 如果该过滤器对给定的节点返回true,"," * 则该节点将被排除在查询结果之外。"," * @remind 查找过滤器excludeFn要求对不应该被匹配的节点应该返回true"," * @warning 查找的终点是到body节点为止"," * @return { Node | NULL } 如果找到符合条件的节点, 则返回该节点, 否则返回NULL"," * @example"," * ```javascript"," * var queryTarget = document.getElementsByTagName(\"div\")[0];"," *"," * //需要查找的节点和过滤器的过滤条件刚好冲突, 执行结果将永远为NULL"," * var node = UE.dom.domUtils.findParentByTagName( queryTarget, [ \"DIV\" ], false, function ( node ) {"," *"," * return node.tagName.toLowerCase() === 'div';"," *"," * } );"," * //output: true"," * console.log( queryTarget === null );"," * ```"," */"," findParentByTagName:function (node, tagNames, includeSelf, excludeFn) {"," tagNames = utils.listToMap(utils.isArray(tagNames) ? tagNames : [tagNames]);"," return domUtils.findParent(node, function (node) {"," return tagNames[node.tagName] && !(excludeFn && excludeFn(node));"," }, includeSelf);"," },",""," /*"," * 查找节点node的祖先节点集合"," * @name findParents"," * @grammar UE.dom.domUtils.findParents(node) => Array //返回一个祖先节点数组集合,不包含自身"," * @grammar UE.dom.domUtils.findParents(node,includeSelf) => Array //返回一个祖先节点数组集合,includeSelf指定是否包含自身"," * @grammar UE.dom.domUtils.findParents(node,includeSelf,filterFn) => Array //返回一个祖先节点数组集合,filterFn指定过滤条件,返回true的node将被选取"," * @grammar UE.dom.domUtils.findParents(node,includeSelf,filterFn,closerFirst) => Array //返回一个祖先节点数组集合,closerFirst为true的话,node的直接父亲节点是数组的第0个"," */"," findParents:function (node, includeSelf, filterFn, closerFirst) {"," var parents = includeSelf && ( filterFn && filterFn(node) || !filterFn ) ? [node] : [];"," while (node = domUtils.findParent(node, filterFn)) {"," parents.push(node);"," }"," return closerFirst ? parents : parents.reverse();"," },",""," /**"," * 在节点node后面插入新节点newNode"," * @method insertAfter"," * @param { Node } node 目标节点"," * @param { Node } newNode 新插入的节点, 该节点将置于目标节点之后"," * @return { Node } 新插入的节点"," */"," insertAfter:function (node, newNode) {"," return node.parentNode.insertBefore(newNode, node.nextSibling);"," },",""," /**"," * 删除节点node及其下属的所有节点"," * @method remove"," * @param { Node } node 需要删除的节点对象"," * @return { Node } 返回刚删除的节点对象"," * @example"," * ```html"," * <div id=\"test\">"," * <div id=\"child\">你好</div>"," * </div>"," * <script>"," * UE.dom.domUtils.remove( document.body, false );"," * //output: false"," * console.log( document.getElementById( \"child\" ) !== null );"," * </script>"," * ```"," */",""," /**"," * 删除节点node,并根据keepChildren的值决定是否保留子节点"," * @method remove"," * @param { Node } node 需要删除的节点对象"," * @param { Boolean } keepChildren 是否需要保留子节点"," * @return { Node } 返回刚删除的节点对象"," * @example"," * ```html"," * <div id=\"test\">"," * <div id=\"child\">你好</div>"," * </div>"," * <script>"," * UE.dom.domUtils.remove( document.body, true );"," * //output: true"," * console.log( document.getElementById( \"child\" ) !== null );"," * </script>"," * ```"," */"," remove:function (node, keepChildren) {"," var parent = node.parentNode,"," child;"," if (parent) {"," if (keepChildren && node.hasChildNodes()) {"," while (child = node.firstChild) {"," parent.insertBefore(child, node);"," }"," }"," parent.removeChild(node);"," }"," return node;"," },",""," /*"," * 取得node节点在dom树上的下一个节点,即多叉树遍历"," */"," getNextNode:function (node, startFromChild, filterFn, guard) {"," return getNode(node, 'firstChild', 'nextSibling', startFromChild, filterFn, guard);"," },",""," /**"," * 检测节点node是否属是UEditor定义的bookmark节点"," * @method isBookmarkNode"," * @param { Node } node 需要检测的节点对象"," * @return { Boolean } 是否是bookmark节点"," * @example"," * ```html"," * <span id=\"_baidu_bookmark_1\"></span>"," * <script>"," * var bookmarkNode = document.getElementById(\"_baidu_bookmark_1\");"," * //output: true"," * console.log( UE.dom.domUtils.isBookmarkNode( bookmarkNode ) );"," * </script>"," * ```"," */"," isBookmarkNode:function (node) {"," return node.nodeType == 1 && node.id && /^_baidu_bookmark_/i.test(node.id);"," },",""," /**"," * 获取节点node所属的window对象"," * @method getWindow"," * @param { Node } node 节点对象"," * @return { Window } 当前节点所属的window对象"," * @example"," * ```javascript"," * //output: true"," * console.log( UE.dom.domUtils.getWindow( document.body ) === window );"," * ```"," */"," getWindow:function (node) {"," var doc = node.ownerDocument || node;"," return doc.defaultView || doc.parentWindow;"," },",""," /**"," * 获取离nodeA与nodeB最近的公共的祖先节点"," * @method getCommonAncestor"," * @param { Node } nodeA 第一个节点"," * @param { Node } nodeB 第二个节点"," * @remind 如果给定的两个节点是同一个节点, 将直接返回该节点。"," * @return { Node | NULL } 如果未找到公共节点, 返回NULL, 否则返回最近的公共祖先节点。"," * @example"," * ```javascript"," * var commonAncestor = UE.dom.domUtils.getCommonAncestor( document.body, document.body.firstChild );"," * //output: true"," * console.log( commonAncestor.tagName.toLowerCase() === 'body' );"," * ```"," */"," getCommonAncestor:function (nodeA, nodeB) {"," if (nodeA === nodeB)"," return nodeA;"," var parentsA = [nodeA] , parentsB = [nodeB], parent = nodeA, i = -1;"," while (parent = parent.parentNode) {"," if (parent === nodeB) {"," return parent;"," }"," parentsA.push(parent);"," }"," parent = nodeB;"," while (parent = parent.parentNode) {"," if (parent === nodeA)"," return parent;"," parentsB.push(parent);"," }"," parentsA.reverse();"," parentsB.reverse();"," while (i++, parentsA[i] === parentsB[i]) {"," }"," return i == 0 ? null : parentsA[i - 1];",""," },",""," /*"," * 清除node节点左右兄弟为空的inline节点"," * @name clearEmptySibling"," * @grammar UE.dom.domUtils.clearEmptySibling(node)"," * @grammar UE.dom.domUtils.clearEmptySibling(node,ignoreNext) //ignoreNext指定是否忽略右边空节点"," * @grammar UE.dom.domUtils.clearEmptySibling(node,ignoreNext,ignorePre) //ignorePre指定是否忽略左边空节点"," * @example"," * <b></b><i></i>xxxx<b>bb</b> --> xxxx<b>bb</b>"," */"," clearEmptySibling:function (node, ignoreNext, ignorePre) {"," function clear(next, dir) {"," var tmpNode;"," while (next && !domUtils.isBookmarkNode(next) && (domUtils.isEmptyInlineElement(next)"," //这里不能把空格算进来会吧空格干掉,出现文字间的空格丢掉了"," || !new RegExp('[^\\t\\n\\r' + domUtils.fillChar + ']').test(next.nodeValue) )) {"," tmpNode = next[dir];"," domUtils.remove(next);"," next = tmpNode;"," }"," }"," !ignoreNext && clear(node.nextSibling, 'nextSibling');"," !ignorePre && clear(node.previousSibling, 'previousSibling');"," },",""," /**"," * 将一个文本节点textNode拆分成两个文本节点,offset指定拆分位置"," * @method split"," * @param { Node } textNode 需要拆分的文本节点对象"," * @param { int } offset 需要拆分的位置, 位置计算从0开始"," * @return { Node } 拆分后形成的新节点"," * @example"," * ```html"," * <div id=\"test\">abcdef</div>"," * <script>"," * var newNode = UE.dom.domUtils.split( document.getElementById( \"test\" ), 3 );"," * //output: def"," * console.log( newNode.nodeValue );"," * </script>"," * ```"," */"," split:function (node, offset) {"," var doc = node.ownerDocument;"," if (browser.ie && offset == node.nodeValue.length) {"," var next = doc.createTextNode('');"," return domUtils.insertAfter(node, next);"," }"," var retval = node.splitText(offset);"," //ie8下splitText不会跟新childNodes,我们手动触发他的更新"," if (browser.ie8) {"," var tmpNode = doc.createTextNode('');"," domUtils.insertAfter(retval, tmpNode);"," domUtils.remove(tmpNode);"," }"," return retval;"," },",""," /**"," * 检测文本节点textNode是否为空节点(包括空格、换行、占位符等字符)"," * @method isWhitespace"," * @param { Node } node 需要检测的节点对象"," * @return { Boolean } 检测的节点是否为空"," * @example"," * ```html"," * <div id=\"test\">"," *"," * </div>"," * <script>"," * //output: true"," * console.log( UE.dom.domUtils.isWhitespace( document.getElementById(\"test\").firstChild ) );"," * </script>"," * ```"," */"," isWhitespace:function (node) {"," return !new RegExp('[^ \\t\\n\\r' + domUtils.fillChar + ']').test(node.nodeValue);"," },",""," /**"," * 获取元素element相对于viewport的位置坐标"," * @method getXY"," * @param { Node } element 需要计算位置的节点对象"," * @return { KeyValueMap } 返回形如{x:left,y:top}的一个key-value映射对象, 其中键x代表水平偏移距离,"," * y代表垂直偏移距离。"," *"," * @example"," * ```javascript"," * var location = UE.dom.domUtils.getXY( document.getElementById(\"test\") );"," * //output: test的坐标为: 12, 24"," * console.log( 'test的坐标为: ', location.x, ',', location.y );"," * ```"," */"," getXY:function (element) {"," var x = 0, y = 0;"," while (element.offsetParent) {"," y += element.offsetTop;"," x += element.offsetLeft;"," element = element.offsetParent;"," }"," return { 'x':x, 'y':y};"," },",""," /**"," * 为元素element绑定原生DOM事件,type为事件类型,handler为处理函数"," * @method on"," * @param { Node } element 需要绑定事件的节点对象"," * @param { String } type 绑定的事件类型"," * @param { Function } handler 事件处理器"," * @example"," * ```javascript"," * UE.dom.domUtils.on(document.body,\"click\",function(e){"," * //e为事件对象,this为被点击元素对戏那个"," * });"," * ```"," */",""," /**"," * 为元素element绑定原生DOM事件,type为事件类型,handler为处理函数"," * @method on"," * @param { Node } element 需要绑定事件的节点对象"," * @param { Array } type 绑定的事件类型数组"," * @param { Function } handler 事件处理器"," * @example"," * ```javascript"," * UE.dom.domUtils.on(document.body,[\"click\",\"mousedown\"],function(evt){"," * //evt为事件对象,this为被点击元素对象"," * });"," * ```"," */"," on:function (element, type, handler) {"," var types = utils.isArray(type) ? type : [type],"," k = types.length;"," if (k) while (k--) {"," type = types[k];"," if (element.addEventListener) {"," element.addEventListener(type, handler, false);"," } else {"," if (!handler._d) {"," handler._d = {"," els : []"," };"," }"," var key = type + handler.toString(),index = utils.indexOf(handler._d.els,element);"," if (!handler._d[key] || index == -1) {"," if(index == -1){"," handler._d.els.push(element);"," }"," if(!handler._d[key]){"," handler._d[key] = function (evt) {"," return handler.call(evt.srcElement, evt || window.event);"," };"," }","",""," element.attachEvent('on' + type, handler._d[key]);"," }"," }"," }"," element = null;"," },",""," /**"," * 解除DOM事件绑定"," * @method un"," * @param { Node } element 需要解除事件绑定的节点对象"," * @param { String } type 需要接触绑定的事件类型"," * @param { Function } handler 对应的事件处理器"," * @example"," * ```javascript"," * UE.dom.domUtils.un(document.body,\"click\",function(evt){"," * //evt为事件对象,this为被点击元素对象"," * });"," * ```"," */",""," /**"," * 解除DOM事件绑定"," * @method un"," * @param { Node } element 需要解除事件绑定的节点对象"," * @param { Array } type 需要接触绑定的事件类型数组"," * @param { Function } handler 对应的事件处理器"," * @example"," * ```javascript"," * UE.dom.domUtils.un(document.body, [\"click\",\"mousedown\"],function(evt){"," * //evt为事件对象,this为被点击元素对象"," * });"," * ```"," */"," un:function (element, type, handler) {"," var types = utils.isArray(type) ? type : [type],"," k = types.length;"," if (k) while (k--) {"," type = types[k];"," if (element.removeEventListener) {"," element.removeEventListener(type, handler, false);"," } else {"," var key = type + handler.toString();"," try{"," element.detachEvent('on' + type, handler._d ? handler._d[key] : handler);"," }catch(e){}"," if (handler._d && handler._d[key]) {"," var index = utils.indexOf(handler._d.els,element);"," if(index!=-1){"," handler._d.els.splice(index,1);"," }"," handler._d.els.length == 0 && delete handler._d[key];"," }"," }"," }"," },",""," /**"," * 比较节点nodeA与节点nodeB是否具有相同的标签名、属性名以及属性值"," * @method isSameElement"," * @param { Node } nodeA 需要比较的节点"," * @param { Node } nodeB 需要比较的节点"," * @return { Boolean } 两个节点是否具有相同的标签名、属性名以及属性值"," * @example"," * ```html"," * <span style=\"font-size:12px\">ssss</span>"," * <span style=\"font-size:12px\">bbbbb</span>"," * <span style=\"font-size:13px\">ssss</span>"," * <span style=\"font-size:14px\">bbbbb</span>"," *"," * <script>"," *"," * var nodes = document.getElementsByTagName( \"span\" );"," *"," * //output: true"," * console.log( UE.dom.domUtils.isSameElement( nodes[0], nodes[1] ) );"," *"," * //output: false"," * console.log( UE.dom.domUtils.isSameElement( nodes[2], nodes[3] ) );"," *"," * </script>"," * ```"," */"," isSameElement:function (nodeA, nodeB) {"," if (nodeA.tagName != nodeB.tagName) {"," return false;"," }"," var thisAttrs = nodeA.attributes,"," otherAttrs = nodeB.attributes;"," if (!ie && thisAttrs.length != otherAttrs.length) {"," return false;"," }"," var attrA, attrB, al = 0, bl = 0;"," for (var i = 0; attrA = thisAttrs[i++];) {"," if (attrA.nodeName == 'style') {"," if (attrA.specified) {"," al++;"," }"," if (domUtils.isSameStyle(nodeA, nodeB)) {"," continue;"," } else {"," return false;"," }"," }"," if (ie) {"," if (attrA.specified) {"," al++;"," attrB = otherAttrs.getNamedItem(attrA.nodeName);"," } else {"," continue;"," }"," } else {"," attrB = nodeB.attributes[attrA.nodeName];"," }"," if (!attrB.specified || attrA.nodeValue != attrB.nodeValue) {"," return false;"," }"," }"," // 有可能attrB的属性包含了attrA的属性之外还有自己的属性"," if (ie) {"," for (i = 0; attrB = otherAttrs[i++];) {"," if (attrB.specified) {"," bl++;"," }"," }"," if (al != bl) {"," return false;"," }"," }"," return true;"," },",""," /**"," * 判断节点nodeA与节点nodeB的元素的style属性是否一致"," * @method isSameStyle"," * @param { Node } nodeA 需要比较的节点"," * @param { Node } nodeB 需要比较的节点"," * @return { Boolean } 两个节点是否具有相同的style属性值"," * @example"," * ```html"," * <span style=\"font-size:12px\">ssss</span>"," * <span style=\"font-size:12px\">bbbbb</span>"," * <span style=\"font-size:13px\">ssss</span>"," * <span style=\"font-size:14px\">bbbbb</span>"," *"," * <script>"," *"," * var nodes = document.getElementsByTagName( \"span\" );"," *"," * //output: true"," * console.log( UE.dom.domUtils.isSameElement( nodes[0], nodes[1] ) );"," *"," * //output: false"," * console.log( UE.dom.domUtils.isSameElement( nodes[2], nodes[3] ) );"," *"," * </script>"," * ```"," */"," isSameStyle:function (nodeA, nodeB) {"," var styleA = nodeA.style.cssText.replace(/( ?; ?)/g, ';').replace(/( ?: ?)/g, ':'),"," styleB = nodeB.style.cssText.replace(/( ?; ?)/g, ';').replace(/( ?: ?)/g, ':');"," if (browser.opera) {"," styleA = nodeA.style;"," styleB = nodeB.style;"," if (styleA.length != styleB.length)"," return false;"," for (var p in styleA) {"," if (/^(\\d+|csstext)$/i.test(p)) {"," continue;"," }"," if (styleA[p] != styleB[p]) {"," return false;"," }"," }"," return true;"," }"," if (!styleA || !styleB) {"," return styleA == styleB;"," }"," styleA = styleA.split(';');"," styleB = styleB.split(';');"," if (styleA.length != styleB.length) {"," return false;"," }"," for (var i = 0, ci; ci = styleA[i++];) {"," if (utils.indexOf(styleB, ci) == -1) {"," return false;"," }"," }"," return true;"," },",""," /**"," * 检查节点node是否为block元素"," * @method isBlockElm"," * @param { Node } node 需要检测的节点对象"," * @return { Boolean } 是否是block元素节点"," * @warning 该方法的判断规则如下: 如果该元素原本是block元素, 则不论该元素当前的css样式是什么都会返回true;"," * 否则,检测该元素的css样式, 如果该元素当前是block元素, 则返回true。 其余情况下都返回false。"," * @example"," * ```html"," * <span id=\"test1\" style=\"display: block\"></span>"," * <span id=\"test2\"></span>"," * <div id=\"test3\" style=\"display: inline\"></div>"," *"," * <script>"," *"," * //output: true"," * console.log( UE.dom.domUtils.isBlockEle( document.getElementById(\"test1\") ) );"," *"," * //output: false"," * console.log( UE.dom.domUtils.isBlockEle( document.getElementById(\"test2\") ) );"," *"," * //output: true"," * console.log( UE.dom.domUtils.isBlockEle( document.getElementById(\"test3\") ) );"," *"," * </script>"," * ```"," */"," isBlockElm:function (node) {"," return node.nodeType == 1 && (dtd.$block[node.tagName] || styleBlock[domUtils.getComputedStyle(node, 'display')]) && !dtd.$nonChild[node.tagName];"," },",""," /**"," * 检测node节点是否为body节点"," * @method isBody"," * @param { Element } node 需要检测的dom元素"," * @return { Boolean } 给定的元素是否是body元素"," * @example"," * ```javascript"," * //output: true"," * console.log( UE.dom.domUtils.isBody( document.body ) );"," * ```"," */"," isBody:function (node) {"," return node && node.nodeType == 1 && node.tagName.toLowerCase() == 'body';"," },",""," /*"," * 以node节点为中心,将该节点的指定祖先节点parent拆分成2块"," * @name breakParent"," * @grammar UE.dom.domUtils.breakParent(node,parent) => node"," * @desc"," * <code type=\"html\"><b>ooo</b>是node节点"," * <p>xxxx<b>ooo</b>xxx</p> ==> <p>xxx</p><b>ooo</b><p>xxx</p>"," * <p>xxxxx<span>xxxx<b>ooo</b>xxxxxx</span></p> => <p>xxxxx<span>xxxx</span></p><b>ooo</b><p><span>xxxxxx</span></p></code>"," */"," breakParent:function (node, parent) {"," var tmpNode,"," parentClone = node,"," clone = node,"," leftNodes,"," rightNodes;"," do {"," parentClone = parentClone.parentNode;"," if (leftNodes) {"," tmpNode = parentClone.cloneNode(false);"," tmpNode.appendChild(leftNodes);"," leftNodes = tmpNode;"," tmpNode = parentClone.cloneNode(false);"," tmpNode.appendChild(rightNodes);"," rightNodes = tmpNode;"," } else {"," leftNodes = parentClone.cloneNode(false);"," rightNodes = leftNodes.cloneNode(false);"," }"," while (tmpNode = clone.previousSibling) {"," leftNodes.insertBefore(tmpNode, leftNodes.firstChild);"," }"," while (tmpNode = clone.nextSibling) {"," rightNodes.appendChild(tmpNode);"," }"," clone = parentClone;"," } while (parent !== parentClone);"," tmpNode = parent.parentNode;"," tmpNode.insertBefore(leftNodes, parent);"," tmpNode.insertBefore(rightNodes, parent);"," tmpNode.insertBefore(node, rightNodes);"," domUtils.remove(parent);"," return node;"," },",""," /*"," * 检查节点node是否是空inline节点"," * @name isEmptyInlineElement"," * @grammar UE.dom.domUtils.isEmptyInlineElement(node) => 1|0"," * @example"," * <b><i></i></b> => 1"," * <b><i></i><u></u></b> => 1"," * <b></b> => 1"," * <b>xx<i></i></b> => 0"," */"," isEmptyInlineElement:function (node) {"," if (node.nodeType != 1 || !dtd.$removeEmpty[ node.tagName ]) {"," return 0;"," }"," node = node.firstChild;"," while (node) {"," //如果是创建的bookmark就跳过"," if (domUtils.isBookmarkNode(node)) {"," return 0;"," }"," if (node.nodeType == 1 && !domUtils.isEmptyInlineElement(node) ||"," node.nodeType == 3 && !domUtils.isWhitespace(node)"," ) {"," return 0;"," }"," node = node.nextSibling;"," }"," return 1;",""," },",""," /**"," * 删除node节点下首尾两端的空白文本子节点"," * @method trimWhiteTextNode"," * @param { Element } node 需要执行删除操作的元素对象"," * @example"," * ```html"," * <div id=\"test\">"," * <div></div>"," * </div>"," *"," * <script>"," * var testNode = document.getElementById(\"test\");"," * //output: 3"," * console.log(testNode.childNodes.length);"," *"," * UE.dom.domUtils.trimWhiteTextNode( testNode );"," * //output: 1"," * console.log(testNode.childNodes.length);"," * </script>"," * ```"," */"," trimWhiteTextNode:function (node) {"," function remove(dir) {"," var child;"," while ((child = node[dir]) && child.nodeType == 3 && domUtils.isWhitespace(child)) {"," node.removeChild(child);"," }"," }"," remove('firstChild');"," remove('lastChild');"," },",""," /*"," * 合并node节点下相同的子节点"," * @method mergeChild"," * @example"," * <p><span style=\"font-size:12px;\">xx<span style=\"font-size:12px;\">aa</span>xx</span></p>"," * ==> UE.dom.domUtils.mergeChild(node,'span')"," * <p><span style=\"font-size:12px;\">xxaaxx</span></p>"," */"," mergeChild:function (node, tagName, attrs) {"," var list = domUtils.getElementsByTagName(node, node.tagName.toLowerCase());"," for (var i = 0, ci; ci = list[i++];) {"," if (!ci.parentNode || domUtils.isBookmarkNode(ci)) {"," continue;"," }"," //span单独处理"," if (ci.tagName.toLowerCase() == 'span') {"," if (node === ci.parentNode) {"," domUtils.trimWhiteTextNode(node);"," if (node.childNodes.length == 1) {"," node.style.cssText = ci.style.cssText + \";\" + node.style.cssText;"," domUtils.remove(ci, true);"," continue;"," }"," }"," ci.style.cssText = node.style.cssText + ';' + ci.style.cssText;"," if (attrs) {"," var style = attrs.style;"," if (style) {"," style = style.split(';');"," for (var j = 0, s; s = style[j++];) {"," ci.style[utils.cssStyleToDomStyle(s.split(':')[0])] = s.split(':')[1];"," }"," }"," }"," if (domUtils.isSameStyle(ci, node)) {"," domUtils.remove(ci, true);"," }"," continue;"," }"," if (domUtils.isSameElement(node, ci)) {"," domUtils.remove(ci, true);"," }"," }"," },",""," /*"," * 原生方法getElementsByTagName的封装"," * @name getElementsByTagName"," * @grammar UE.dom.domUtils.getElementsByTagName(node,tagName) => Array //节点集合数组"," */"," getElementsByTagName:function (node, name,filter) {"," if(filter && utils.isString(filter)){"," var className = filter;"," filter = function(node){return domUtils.hasClass(node,className)}"," }"," name = utils.trim(name).replace(/[ ]{2,}/g,' ').split(' ');"," var arr = [];"," for(var n = 0,ni;ni=name[n++];){"," var list = node.getElementsByTagName(ni);"," for (var i = 0, ci; ci = list[i++];) {"," if(!filter || filter(ci))"," arr.push(ci);"," }"," }",""," return arr;"," },",""," /**"," * 将节点node提取到父节点上"," * @method mergeToParent"," * @param { Element } node 需要提取的元素对象"," * @example"," * ```html"," * <div id=\"parent\">"," * <div id=\"sub\">"," * <span id=\"child\"></span>"," * </div>"," * </div>"," *"," * <script>"," *"," * var child = document.getElementById( \"child\" );"," *"," * //output: sub"," * console.log( child.parentNode.id );"," *"," * UE.dom.domUtils.mergeToParent( child );"," *"," * //output: parent"," * console.log( child.parentNode.id );"," *"," * </script>"," * ```"," */"," mergeToParent:function (node) {"," var parent = node.parentNode;"," while (parent && dtd.$removeEmpty[parent.tagName]) {"," if (parent.tagName == node.tagName || parent.tagName == 'A') {//针对a标签单独处理"," domUtils.trimWhiteTextNode(parent);"," //span需要特殊处理 不处理这样的情况 <span stlye=\"color:#fff\">xxx<span style=\"color:#ccc\">xxx</span>xxx</span>"," if (parent.tagName == 'SPAN' && !domUtils.isSameStyle(parent, node)"," || (parent.tagName == 'A' && node.tagName == 'SPAN')) {"," if (parent.childNodes.length > 1 || parent !== node.parentNode) {"," node.style.cssText = parent.style.cssText + \";\" + node.style.cssText;"," parent = parent.parentNode;"," continue;"," } else {"," parent.style.cssText += \";\" + node.style.cssText;"," //trace:952 a标签要保持下划线"," if (parent.tagName == 'A') {"," parent.style.textDecoration = 'underline';"," }"," }"," }"," if (parent.tagName != 'A') {"," parent === node.parentNode && domUtils.remove(node, true);"," break;"," }"," }"," parent = parent.parentNode;"," }"," },",""," /**"," * 合并节点node的左右兄弟节点"," * @method mergeSibling"," * @param { Element } node 需要合并的目标节点"," * @example"," * ```html"," * <b>xxxx</b><b id=\"test\">ooo</b><b>xxxx</b>"," *"," * <script>"," * var demoNode = document.getElementById(\"test\");"," * UE.dom.domUtils.mergeSibling( demoNode );"," * //output: xxxxoooxxxx"," * console.log( demoNode.innerHTML );"," * </script>"," * ```"," */",""," /**"," * 合并节点node的左右兄弟节点, 可以根据给定的条件选择是否忽略合并左节点。"," * @method mergeSibling"," * @param { Element } node 需要合并的目标节点"," * @param { Boolean } ignorePre 是否忽略合并左节点"," * @example"," * ```html"," * <b>xxxx</b><b id=\"test\">ooo</b><b>xxxx</b>"," *"," * <script>"," * var demoNode = document.getElementById(\"test\");"," * UE.dom.domUtils.mergeSibling( demoNode, true );"," * //output: oooxxxx"," * console.log( demoNode.innerHTML );"," * </script>"," * ```"," */",""," /**"," * 合并节点node的左右兄弟节点,可以根据给定的条件选择是否忽略合并左右节点。"," * @method mergeSibling"," * @param { Element } node 需要合并的目标节点"," * @param { Boolean } ignorePre 是否忽略合并左节点"," * @param { Boolean } ignoreNext 是否忽略合并右节点"," * @remind 如果同时忽略左右节点, 则该操作什么也不会做"," * @example"," * ```html"," * <b>xxxx</b><b id=\"test\">ooo</b><b>xxxx</b>"," *"," * <script>"," * var demoNode = document.getElementById(\"test\");"," * UE.dom.domUtils.mergeSibling( demoNode, false, true );"," * //output: xxxxooo"," * console.log( demoNode.innerHTML );"," * </script>"," * ```"," */"," mergeSibling:function (node, ignorePre, ignoreNext) {"," function merge(rtl, start, node) {"," var next;"," if ((next = node[rtl]) && !domUtils.isBookmarkNode(next) && next.nodeType == 1 && domUtils.isSameElement(node, next)) {"," while (next.firstChild) {"," if (start == 'firstChild') {"," node.insertBefore(next.lastChild, node.firstChild);"," } else {"," node.appendChild(next.firstChild);"," }"," }"," domUtils.remove(next);"," }"," }"," !ignorePre && merge('previousSibling', 'firstChild', node);"," !ignoreNext && merge('nextSibling', 'lastChild', node);"," },",""," /**"," * 设置节点node及其子节点不会被选中"," * @method unSelectable"," * @param { Element } node 需要执行操作的dom元素"," * @remind 执行该操作后的节点, 将不能被鼠标选中"," * @example"," * ```javascript"," * UE.dom.domUtils.unSelectable( document.body );"," * ```"," */"," unSelectable:ie || browser.opera ? function (node) {"," //for ie9"," node.onselectstart = function () {"," return false;"," };"," node.onclick = node.onkeyup = node.onkeydown = function () {"," return false;"," };"," node.unselectable = 'on';"," node.setAttribute(\"unselectable\", \"on\");"," for (var i = 0, ci; ci = node.all[i++];) {"," switch (ci.tagName.toLowerCase()) {"," case 'iframe' :"," case 'textarea' :"," case 'input' :"," case 'select' :"," break;"," default :"," ci.unselectable = 'on';"," node.setAttribute(\"unselectable\", \"on\");"," }"," }"," } : function (node) {"," node.style.MozUserSelect ="," node.style.webkitUserSelect ="," node.style.KhtmlUserSelect = 'none';"," },",""," /**"," * 删除节点node上的指定属性名称的属性"," * @method removeAttributes"," * @param { String } attrNames 可以是空格隔开的多个属性名称,该操作将会依次删除相应的属性"," * @example"," * ```html"," * <div id=\"wrap\">"," * <span style=\"font-size:14px;\" id=\"test\" name=\"followMe\">xxxxx</span>"," * </div>"," *"," * <script>"," *"," * UE.dom.domUtils.removeAttributes( document.getElementById( \"test\" ), \"id name\" );"," *"," * //output: <span style=\"font-size:14px;\">xxxxx</span>"," * console.log( document.getElementById(\"wrap\").innerHTML );"," *"," * </script>"," * ```"," */",""," /**"," * 删除节点node上的指定属性名称的属性"," * @method removeAttributes"," * @param { Array } attrNames 需要删除的属性名数组"," * @example"," * ```html"," * <div id=\"wrap\">"," * <span style=\"font-size:14px;\" id=\"test\" name=\"followMe\">xxxxx</span>"," * </div>"," *"," * <script>"," *"," * UE.dom.domUtils.removeAttributes( document.getElementById( \"test\" ), [\"id\", \"name\"] );"," *"," * //output: <span style=\"font-size:14px;\">xxxxx</span>"," * console.log( document.getElementById(\"wrap\").innerHTML );"," *"," * </script>"," * ```"," */"," removeAttributes:function (node, attrNames) {"," attrNames = utils.isArray(attrNames) ? attrNames : utils.trim(attrNames).replace(/[ ]{2,}/g,' ').split(' ');"," for (var i = 0, ci; ci = attrNames[i++];) {"," ci = attrFix[ci] || ci;"," switch (ci) {"," case 'className':"," node[ci] = '';"," break;"," case 'style':"," node.style.cssText = '';"," !browser.ie && node.removeAttributeNode(node.getAttributeNode('style'))"," }"," node.removeAttribute(ci);"," }"," },",""," /**"," * 在doc下创建一个标签名为tag,属性为attrs的元素"," * @method createElement"," * @param { DomDocument } doc 新创建的元素属于该document节点创建"," * @param { String } tagName 需要创建的元素的标签名"," * @param { KeyValueMap } attrs 新创建的元素的属性key-value集合"," * @return { Element } 新创建的元素对象"," * @example"," * ```javascript"," * var ele = UE.dom.domUtils.createElement( document, 'div', {"," * id: 'test'"," * } );"," *"," * //output: DIV"," * console.log( ele.tagName );"," *"," * //output: test"," * console.log( ele.id );"," *"," * ```"," */"," createElement:function (doc, tag, attrs) {"," return domUtils.setAttributes(doc.createElement(tag), attrs)"," },",""," /**"," * 为节点node添加属性attrs,attrs为属性键值对"," * @method setAttributes"," * @param { Element } node 需要设置属性的元素对象"," * @param { KeyValueMap } attrs 需要设置的属性名-值对"," * @return { Element } 设置属性的元素对象"," * @example"," * ```html"," * <span id=\"test\"></span>"," *"," * <script>"," *"," * var testNode = UE.dom.domUtils.setAttributes( document.getElementById( \"test\" ), {"," * id: 'demo'"," * } );"," *"," * //output: demo"," * console.log( testNode.id );"," *"," * </script>"," *"," */"," setAttributes:function (node, attrs) {"," for (var attr in attrs) {"," if(attrs.hasOwnProperty(attr)){"," var value = attrs[attr];"," switch (attr) {"," case 'class':"," //ie下要这样赋值,setAttribute不起作用"," node.className = value;"," break;"," case 'style' :"," node.style.cssText = node.style.cssText + \";\" + value;"," break;"," case 'innerHTML':"," node[attr] = value;"," break;"," case 'value':"," node.value = value;"," break;"," default:"," node.setAttribute(attrFix[attr] || attr, value);"," }"," }"," }"," return node;"," },",""," /**"," * 获取元素element经过计算后的样式值"," * @method getComputedStyle"," * @param { Element } element 需要获取样式的元素对象"," * @param { String } styleName 需要获取的样式名"," * @return { String } 获取到的样式值"," * @example"," * ```html"," * <style type=\"text/css\">"," * #test {"," * font-size: 15px;"," * }"," * </style>"," *"," * <span id=\"test\"></span>"," *"," * <script>"," * //output: 15px"," * console.log( UE.dom.domUtils.getComputedStyle( document.getElementById( \"test\" ), 'font-size' ) );"," * </script>"," * ```"," */"," getComputedStyle:function (element, styleName) {"," //一下的属性单独处理"," var pros = 'width height top left';",""," if(pros.indexOf(styleName) > -1){"," return element['offset' + styleName.replace(/^\\w/,function(s){return s.toUpperCase()})] + 'px';"," }"," //忽略文本节点"," if (element.nodeType == 3) {"," element = element.parentNode;"," }"," //ie下font-size若body下定义了font-size,则从currentStyle里会取到这个font-size. 取不到实际值,故此修改."," if (browser.ie && browser.version < 9 && styleName == 'font-size' && !element.style.fontSize &&"," !dtd.$empty[element.tagName] && !dtd.$nonChild[element.tagName]) {"," var span = element.ownerDocument.createElement('span');"," span.style.cssText = 'padding:0;border:0;font-family:simsun;';"," span.innerHTML = '.';"," element.appendChild(span);"," var result = span.offsetHeight;"," element.removeChild(span);"," span = null;"," return result + 'px';"," }"," try {"," var value = domUtils.getStyle(element, styleName) ||"," (window.getComputedStyle ? domUtils.getWindow(element).getComputedStyle(element, '').getPropertyValue(styleName) :"," ( element.currentStyle || element.style )[utils.cssStyleToDomStyle(styleName)]);",""," } catch (e) {"," return \"\";"," }"," return utils.transUnitToPx(utils.fixColor(styleName, value));"," },"," /**"," * 删除元素element指定的className"," * @method removeClasses"," * @param { Element } ele 需要删除class的元素节点"," * @param { String } classNames 需要删除的className, 多个className之间以空格分开"," * @example"," * ```html"," * <span id=\"test\" class=\"test1 test2 test3\">xxx</span>"," *"," * <script>"," *"," * var testNode = document.getElementById( \"test\" );"," * UE.dom.domUtils.removeClasses( testNode, \"test1 test2\" );"," *"," * //output: test3"," * console.log( testNode.className );"," *"," * </script>"," * ```"," */",""," /**"," * 删除元素element指定的className"," * @method removeClasses"," * @param { Element } ele 需要删除class的元素节点"," * @param { Array } classNames 需要删除的className数组"," * @example"," * ```html"," * <span id=\"test\" class=\"test1 test2 test3\">xxx</span>"," *"," * <script>"," *"," * var testNode = document.getElementById( \"test\" );"," * UE.dom.domUtils.removeClasses( testNode, [\"test1\", \"test2\"] );"," *"," * //output: test3"," * console.log( testNode.className );"," *"," * </script>"," * ```"," */"," removeClasses:function (elm, classNames) {"," classNames = utils.isArray(classNames) ? classNames :"," utils.trim(classNames).replace(/[ ]{2,}/g,' ').split(' ');"," for(var i = 0,ci,cls = elm.className;ci=classNames[i++];){"," cls = cls.replace(new RegExp('\\\\b' + ci + '\\\\b'),'')"," }"," cls = utils.trim(cls).replace(/[ ]{2,}/g,' ');"," if(cls){"," elm.className = cls;"," }else{"," domUtils.removeAttributes(elm,['class']);"," }"," },",""," /**"," * 给元素element添加className"," * @method addClass"," * @param { Node } ele 需要增加className的元素"," * @param { String } classNames 需要添加的className, 多个className之间以空格分割"," * @remind 相同的类名不会被重复添加"," * @example"," * ```html"," * <span id=\"test\" class=\"cls1 cls2\"></span>"," *"," * <script>"," * var testNode = document.getElementById(\"test\");"," *"," * UE.dom.domUtils.addClass( testNode, \"cls2 cls3 cls4\" );"," *"," * //output: cl1 cls2 cls3 cls4"," * console.log( testNode.className );"," *"," * <script>"," * ```"," */",""," /**"," * 给元素element添加className"," * @method addClass"," * @param { Node } ele 需要增加className的元素"," * @param { Array } classNames 需要添加的className的数组"," * @remind 相同的类名不会被重复添加"," * @example"," * ```html"," * <span id=\"test\" class=\"cls1 cls2\"></span>"," *"," * <script>"," * var testNode = document.getElementById(\"test\");"," *"," * UE.dom.domUtils.addClass( testNode, [\"cls2\", \"cls3\", \"cls4\"] );"," *"," * //output: cl1 cls2 cls3 cls4"," * console.log( testNode.className );"," *"," * <script>"," * ```"," */"," addClass:function (elm, classNames) {"," if(!elm)return;"," classNames = utils.trim(classNames).replace(/[ ]{2,}/g,' ').split(' ');"," for(var i = 0,ci,cls = elm.className;ci=classNames[i++];){"," if(!new RegExp('\\\\b' + ci + '\\\\b').test(cls)){"," elm.className += ' ' + ci;"," }"," }"," },",""," /**"," * 判断元素element是否包含给定的样式类名className"," * @method hasClass"," * @param { Node } ele 需要检测的元素"," * @param { String } classNames 需要检测的className, 多个className之间用空格分割"," * @return { Boolean } 元素是否包含所有给定的className"," * @example"," * ```html"," * <span id=\"test1\" class=\"cls1 cls2\"></span>"," *"," * <script>"," * var test1 = document.getElementById(\"test1\");"," *"," * //output: false"," * console.log( UE.dom.domUtils.hasClass( test1, \"cls2 cls1 cls3\" ) );"," *"," * //output: true"," * console.log( UE.dom.domUtils.hasClass( test1, \"cls2 cls1\" ) );"," * </script>"," * ```"," */",""," /**"," * 判断元素element是否包含给定的样式类名className"," * @method hasClass"," * @param { Node } ele 需要检测的元素"," * @param { Array } classNames 需要检测的className数组"," * @return { Boolean } 元素是否包含所有给定的className"," * @example"," * ```html"," * <span id=\"test1\" class=\"cls1 cls2\"></span>"," *"," * <script>"," * var test1 = document.getElementById(\"test1\");"," *"," * //output: false"," * console.log( UE.dom.domUtils.hasClass( test1, [ \"cls2\", \"cls1\", \"cls3\" ] ) );"," *"," * //output: true"," * console.log( UE.dom.domUtils.hasClass( test1, [ \"cls2\", \"cls1\" ]) );"," * </script>"," * ```"," */"," hasClass:function (element, className) {"," if(utils.isRegExp(className)){"," return className.test(element.className)"," }"," className = utils.trim(className).replace(/[ ]{2,}/g,' ').split(' ');"," for(var i = 0,ci,cls = element.className;ci=className[i++];){"," if(!new RegExp('\\\\b' + ci + '\\\\b','i').test(cls)){"," return false;"," }"," }"," return i - 1 == className.length;"," },",""," /**"," * 阻止事件默认行为"," * @method preventDefault"," * @param { Event } evt 需要阻止默认行为的事件对象"," * @example"," * ```javascript"," * UE.dom.domUtils.preventDefault( evt );"," * ```"," */"," preventDefault:function (evt) {"," evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);"," },",""," /**"," * 删除元素element指定的样式"," * @method removeStyle"," * @param { Element } element 需要删除样式的元素"," * @param { String } styleName 需要删除的样式名"," * @example"," * ```html"," * <span id=\"test\" style=\"color: red; background: blue;\"></span>"," *"," * <script>"," *"," * var testNode = document.getElementById(\"test\");"," *"," * UE.dom.domUtils.removeStyle( testNode, 'color' );"," *"," * //output: background: blue;"," * console.log( testNode.style.cssText );"," *"," * </script>"," * ```"," */"," removeStyle:function (element, name) {"," if(browser.ie ){"," //针对color先单独处理一下"," if(name == 'color'){"," name = '(^|;)' + name;"," }"," element.style.cssText = element.style.cssText.replace(new RegExp(name + '[^:]*:[^;]+;?','ig'),'')"," }else{"," if (element.style.removeProperty) {"," element.style.removeProperty (name);"," }else {"," element.style.removeAttribute (utils.cssStyleToDomStyle(name));"," }"," }","",""," if (!element.style.cssText) {"," domUtils.removeAttributes(element, ['style']);"," }"," },",""," /**"," * 获取元素element的style属性的指定值"," * @method getStyle"," * @param { Element } element 需要获取属性值的元素"," * @param { String } styleName 需要获取的style的名称"," * @warning 该方法仅获取元素style属性中所标明的值"," * @return { String } 该元素包含指定的style属性值"," * @example"," * ```html"," * <div id=\"test\" style=\"color: red;\"></div>"," *"," * <script>"," *"," * var testNode = document.getElementById( \"test\" );"," *"," * //output: red"," * console.log( UE.dom.domUtils.getStyle( testNode, \"color\" ) );"," *"," * //output: \"\""," * console.log( UE.dom.domUtils.getStyle( testNode, \"background\" ) );"," *"," * </script>"," * ```"," */"," getStyle:function (element, name) {"," var value = element.style[ utils.cssStyleToDomStyle(name) ];"," return utils.fixColor(name, value);"," },","",""," /**"," * 为元素element设置样式属性值"," * @method setStyle"," * @param { Element } element 需要设置样式的元素"," * @param { String } styleName 样式名"," * @param { String } styleValue 样式值"," * @example"," * ```html"," * <div id=\"test\"></div>"," *"," * <script>"," *"," * var testNode = document.getElementById( \"test\" );"," *"," * //output: \"\""," * console.log( testNode.style.color );"," *"," * UE.dom.domUtils.setStyle( testNode, 'color', 'red' );"," * //output: \"red\""," * console.log( testNode.style.color );"," *"," * </script>"," * ```"," */"," setStyle:function (element, name, value) {"," element.style[utils.cssStyleToDomStyle(name)] = value;"," if(!utils.trim(element.style.cssText)){"," this.removeAttributes(element,'style')"," }"," },",""," /**"," * 为元素element设置多个样式属性值"," * @method setStyles"," * @param { Element } element 需要设置样式的元素"," * @param { KeyValueMap } styles 样式名值对"," * @example"," * ```html"," * <div id=\"test\"></div>"," *"," * <script>"," *"," * var testNode = document.getElementById( \"test\" );"," *"," * //output: \"\""," * console.log( testNode.style.color );"," *"," * UE.dom.domUtils.setStyles( testNode, {"," * 'color': 'red'"," * } );"," * //output: \"red\""," * console.log( testNode.style.color );"," *"," * </script>"," * ```"," */"," setStyles:function (element, styles) {"," for (var name in styles) {"," if (styles.hasOwnProperty(name)) {"," domUtils.setStyle(element, name, styles[name]);"," }"," }"," },",""," /**"," * 删除_moz_dirty属性"," * @method removeDirtyAttr"," */"," removeDirtyAttr:function (node) {"," for (var i = 0, ci, nodes = node.getElementsByTagName('*'); ci = nodes[i++];) {"," ci.removeAttribute('_moz_dirty');"," }"," node.removeAttribute('_moz_dirty');"," },",""," /**"," * 获取子节点的数量"," * @method getChildCount"," * @param { Element } node 需要检测的元素"," * @return { Number } 给定的node元素的子节点数量"," * @example"," * ```html"," * <div id=\"test\">"," * <span></span>"," * </div>"," *"," * <script>"," *"," * //output: 3"," * console.log( UE.dom.domUtils.getChildCount( document.getElementById(\"test\") ) );"," *"," * </script>"," * ```"," */",""," /**"," * 根据给定的过滤规则, 获取符合条件的子节点的数量"," * @method getChildCount"," * @param { Element } node 需要检测的元素"," * @param { Function } fn 过滤器, 要求对符合条件的子节点返回true, 反之则要求返回false"," * @return { Number } 符合过滤条件的node元素的子节点数量"," * @example"," * ```html"," * <div id=\"test\">"," * <span></span>"," * </div>"," *"," * <script>"," *"," * //output: 1"," * console.log( UE.dom.domUtils.getChildCount( document.getElementById(\"test\"), function ( node ) {"," *"," * return node.nodeType === 1;"," *"," * } ) );"," *"," * </script>"," * ```"," */"," getChildCount:function (node, fn) {"," var count = 0, first = node.firstChild;"," fn = fn || function () {"," return 1;"," };"," while (first) {"," if (fn(first)) {"," count++;"," }"," first = first.nextSibling;"," }"," return count;"," },",""," /**"," * 判断给定节点是否为空节点"," * @method isEmptyNode"," * @param { Node } node 需要检测的节点对象"," * @return { Boolean } 节点是否为空"," * @example"," * ```javascript"," * UE.dom.domUtils.isEmptyNode( document.body );"," * ```"," */"," isEmptyNode:function (node) {"," return !node.firstChild || domUtils.getChildCount(node, function (node) {"," return !domUtils.isBr(node) && !domUtils.isBookmarkNode(node) && !domUtils.isWhitespace(node)"," }) == 0"," },",""," /**"," * 清空给定节点所有的className"," * @method clearSelectedArr"," * @param { Array } nodes 需要清空className的节点的数组集合"," * @example"," * ```javascript"," *"," * UE.dom.domUtils.clearSelectedArr( [ document.body, document.body.firstChild ] );"," *"," * ```"," */"," clearSelectedArr:function (nodes) {"," var node;"," while (node = nodes.pop()) {"," domUtils.removeAttributes(node, ['class']);"," }"," },",""," /**"," * 将显示区域滚动到指定节点的位置"," * @method scrollToView"," * @param {Node} node 节点"," * @param {window} win window对象"," * @param {Number} offsetTop 距离上方的偏移量"," */"," scrollToView:function (node, win, offsetTop) {"," var getViewPaneSize = function () {"," var doc = win.document,"," mode = doc.compatMode == 'CSS1Compat';"," return {"," width:( mode ? doc.documentElement.clientWidth : doc.body.clientWidth ) || 0,"," height:( mode ? doc.documentElement.clientHeight : doc.body.clientHeight ) || 0"," };"," },"," getScrollPosition = function (win) {"," if ('pageXOffset' in win) {"," return {"," x:win.pageXOffset || 0,"," y:win.pageYOffset || 0"," };"," }"," else {"," var doc = win.document;"," return {"," x:doc.documentElement.scrollLeft || doc.body.scrollLeft || 0,"," y:doc.documentElement.scrollTop || doc.body.scrollTop || 0"," };"," }"," };"," var winHeight = getViewPaneSize().height, offset = winHeight * -1 + offsetTop;"," offset += (node.offsetHeight || 0);"," var elementPosition = domUtils.getXY(node);"," offset += elementPosition.y;"," var currentScroll = getScrollPosition(win).y;"," // offset += 50;"," if (offset > currentScroll || offset < currentScroll - winHeight) {"," win.scrollTo(0, offset + (offset < 0 ? -20 : 20));"," }"," },",""," /**"," * 判断给定节点是否为br"," * @method isBr"," * @param { Node } node 需要判断的节点对象"," * @return { Boolean } 给定的节点是否是br节点"," */"," isBr:function (node) {"," return node.nodeType == 1 && node.tagName == 'BR';"," },",""," /**"," * 判断给定的节点是否是一个“填充”节点"," * @method isFillChar"," * @param { Node } node 需要判断的节点"," * @param { Boolean } isInStart 是否从节点内容的开始位置匹配"," * @returns { Boolean } 节点是否是填充节点"," */"," isFillChar:function (node,isInStart) {"," return node.nodeType == 3 && !node.nodeValue.replace(new RegExp((isInStart ? '^' : '' ) + domUtils.fillChar), '').length"," },","",""," isStartInblock:function (range) {"," var tmpRange = range.cloneRange(),"," flag = 0,"," start = tmpRange.startContainer,"," tmp;"," if(start.nodeType == 1 && start.childNodes[tmpRange.startOffset]){"," start = start.childNodes[tmpRange.startOffset];"," var pre = start.previousSibling;"," while(pre && domUtils.isFillChar(pre)){"," start = pre;"," pre = pre.previousSibling;"," }"," }"," if(this.isFillChar(start,true) && tmpRange.startOffset == 1){"," tmpRange.setStartBefore(start);"," start = tmpRange.startContainer;"," }",""," while (start && domUtils.isFillChar(start)) {"," tmp = start;"," start = start.previousSibling"," }"," if (tmp) {"," tmpRange.setStartBefore(tmp);"," start = tmpRange.startContainer;"," }"," if (start.nodeType == 1 && domUtils.isEmptyNode(start) && tmpRange.startOffset == 1) {"," tmpRange.setStart(start, 0).collapse(true);"," }"," while (!tmpRange.startOffset) {"," start = tmpRange.startContainer;"," if (domUtils.isBlockElm(start) || domUtils.isBody(start)) {"," flag = 1;"," break;"," }"," var pre = tmpRange.startContainer.previousSibling,"," tmpNode;"," if (!pre) {"," tmpRange.setStartBefore(tmpRange.startContainer);"," } else {"," while (pre && domUtils.isFillChar(pre)) {"," tmpNode = pre;"," pre = pre.previousSibling;"," }"," if (tmpNode) {"," tmpRange.setStartBefore(tmpNode);"," } else {"," tmpRange.setStartBefore(tmpRange.startContainer);"," }"," }"," }"," return flag && !domUtils.isBody(tmpRange.startContainer) ? 1 : 0;"," },",""," /**"," * 判断给定的元素是否是一个空元素"," * @method isEmptyBlock"," * @param { Element } node 需要判断的元素"," * @return { Boolean } 是否是空元素"," * @example"," * ```html"," * <div id=\"test\"></div>"," *"," * <script>"," * //output: true"," * console.log( UE.dom.domUtils.isEmptyBlock( document.getElementById(\"test\") ) );"," * </script>"," * ```"," */",""," /**"," * 根据指定的判断规则判断给定的元素是否是一个空元素"," * @method isEmptyBlock"," * @param { Element } node 需要判断的元素"," * @param { RegExp } reg 对内容执行判断的正则表达式对象"," * @return { Boolean } 是否是空元素"," */"," isEmptyBlock:function (node,reg) {"," if(node.nodeType != 1)"," return 0;"," reg = reg || new RegExp('[ \\t\\r\\n' + domUtils.fillChar + ']', 'g');"," if (node[browser.ie ? 'innerText' : 'textContent'].replace(reg, '').length > 0) {"," return 0;"," }"," for (var n in dtd.$isNotEmpty) {"," if (node.getElementsByTagName(n).length) {"," return 0;"," }"," }"," return 1;"," },",""," /**"," * 移动元素使得该元素的位置移动指定的偏移量的距离"," * @method setViewportOffset"," * @param { Element } element 需要设置偏移量的元素"," * @param { KeyValueMap } offset 偏移量, 形如{ left: 100, top: 50 }的一个键值对, 表示该元素将在"," * 现有的位置上向水平方向偏移offset.left的距离, 在竖直方向上偏移"," * offset.top的距离"," * @example"," * ```html"," * <div id=\"test\" style=\"top: 100px; left: 50px; position: absolute;\"></div>"," *"," * <script>"," *"," * var testNode = document.getElementById(\"test\");"," *"," * UE.dom.domUtils.setViewportOffset( testNode, {"," * left: 200,"," * top: 50"," * } );"," *"," * //output: top: 300px; left: 100px; position: absolute;"," * console.log( testNode.style.cssText );"," *"," * </script>"," * ```"," */"," setViewportOffset:function (element, offset) {"," var left = parseInt(element.style.left) | 0;"," var top = parseInt(element.style.top) | 0;"," var rect = element.getBoundingClientRect();"," var offsetLeft = offset.left - rect.left;"," var offsetTop = offset.top - rect.top;"," if (offsetLeft) {"," element.style.left = left + offsetLeft + 'px';"," }"," if (offsetTop) {"," element.style.top = top + offsetTop + 'px';"," }"," },",""," /**"," * 用“填充字符”填充节点"," * @method fillNode"," * @param { DomDocument } doc 填充的节点所在的docment对象"," * @param { Node } node 需要填充的节点对象"," * @example"," * ```html"," * <div id=\"test\"></div>"," *"," * <script>"," * var testNode = document.getElementById(\"test\");"," *"," * //output: 0"," * console.log( testNode.childNodes.length );"," *"," * UE.dom.domUtils.fillNode( document, testNode );"," *"," * //output: 1"," * console.log( testNode.childNodes.length );"," *"," * </script>"," * ```"," */"," fillNode:function (doc, node) {"," var tmpNode = browser.ie ? doc.createTextNode(domUtils.fillChar) : doc.createElement('br');"," node.innerHTML = '';"," node.appendChild(tmpNode);"," },",""," /**"," * 把节点src的所有子节点追加到另一个节点tag上去"," * @method moveChild"," * @param { Node } src 源节点, 该节点下的所有子节点将被移除"," * @param { Node } tag 目标节点, 从源节点移除的子节点将被追加到该节点下"," * @example"," * ```html"," * <div id=\"test1\">"," * <span></span>"," * </div>"," * <div id=\"test2\">"," * <div></div>"," * </div>"," *"," * <script>"," *"," * var test1 = document.getElementById(\"test1\"),"," * test2 = document.getElementById(\"test2\");"," *"," * UE.dom.domUtils.moveChild( test1, test2 );"," *"," * //output: \"\"(空字符串)"," * console.log( test1.innerHTML );"," *"," * //output: \"<div></div><span></span>\""," * console.log( test2.innerHTML );"," *"," * </script>"," * ```"," */",""," /**"," * 把节点src的所有子节点移动到另一个节点tag上去, 可以通过dir参数控制附加的行为是“追加”还是“插入顶部”"," * @method moveChild"," * @param { Node } src 源节点, 该节点下的所有子节点将被移除"," * @param { Node } tag 目标节点, 从源节点移除的子节点将被附加到该节点下"," * @param { Boolean } dir 附加方式, 如果为true, 则附加进去的节点将被放到目标节点的顶部, 反之,则放到末尾"," * @example"," * ```html"," * <div id=\"test1\">"," * <span></span>"," * </div>"," * <div id=\"test2\">"," * <div></div>"," * </div>"," *"," * <script>"," *"," * var test1 = document.getElementById(\"test1\"),"," * test2 = document.getElementById(\"test2\");"," *"," * UE.dom.domUtils.moveChild( test1, test2, true );"," *"," * //output: \"\"(空字符串)"," * console.log( test1.innerHTML );"," *"," * //output: \"<span></span><div></div>\""," * console.log( test2.innerHTML );"," *"," * </script>"," * ```"," */"," moveChild:function (src, tag, dir) {"," while (src.firstChild) {"," if (dir && tag.firstChild) {"," tag.insertBefore(src.lastChild, tag.firstChild);"," } else {"," tag.appendChild(src.firstChild);"," }"," }"," },",""," /**"," * 判断节点的标签上是否不存在任何属性"," * @method hasNoAttributes"," * @param { Node } node 需要检测的节点对象"," * @return { Boolean } 节点是否不包含任何属性"," * @example"," * ```html"," * <div id=\"test\"><span>xxxx</span></div>"," *"," * <script>"," *"," * //output: false"," * console.log( UE.dom.domUtils.hasNoAttributes( document.getElementById(\"test\") ) );"," *"," * //output: true"," * console.log( UE.dom.domUtils.hasNoAttributes( document.getElementById(\"test\").firstChild ) );"," *"," * </script>"," * ```"," */"," hasNoAttributes:function (node) {"," return browser.ie ? /^<\\w+\\s*?>/.test(node.outerHTML) : node.attributes.length == 0;"," },",""," /**"," * 检测节点是否是UEditor所使用的辅助节点"," * @method isCustomeNode"," * @param { Node } node 需要检测的节点"," * @remind 辅助节点是指编辑器要完成工作临时添加的节点, 在输出的时候将会从编辑器内移除, 不会影响最终的结果。"," * @return { Boolean } 给定的节点是否是一个辅助节点"," */"," isCustomeNode:function (node) {"," return node.nodeType == 1 && node.getAttribute('_ue_custom_node_');"," },",""," /**"," * 检测节点的标签是否是给定的标签"," * @method isTagNode"," * @param { Node } node 需要检测的节点对象"," * @param { String } tagName 标签"," * @return { Boolean } 节点的标签是否是给定的标签"," * @example"," * ```html"," * <div id=\"test\"></div>"," *"," * <script>"," *"," * //output: true"," * console.log( UE.dom.domUtils.isTagNode( document.getElementById(\"test\"), \"div\" ) );"," *"," * </script>"," * ```"," */"," isTagNode:function (node, tagName) {"," return node.nodeType == 1 && new RegExp('^' + node.tagName + '$','i').test(tagName)"," },",""," /**"," * 给定一个节点数组,在通过指定的过滤器过滤后, 获取其中满足过滤条件的第一个节点"," * @method filterNodeList"," * @param { Array } nodeList 需要过滤的节点数组"," * @param { Function } fn 过滤器, 对符合条件的节点, 执行结果返回true, 反之则返回false"," * @return { Node | NULL } 如果找到符合过滤条件的节点, 则返回该节点, 否则返回NULL"," * @example"," * ```javascript"," * var divNodes = document.getElementsByTagName(\"div\");"," * divNodes = [].slice.call( divNodes, 0 );"," *"," * //output: null"," * console.log( UE.dom.domUtils.filterNodeList( divNodes, function ( node ) {"," * return node.tagName.toLowerCase() !== 'div';"," * } ) );"," * ```"," */",""," /**"," * 给定一个节点数组nodeList和一组标签名tagNames, 获取其中能够匹配标签名的节点集合中的第一个节点"," * @method filterNodeList"," * @param { Array } nodeList 需要过滤的节点数组"," * @param { String } tagNames 需要匹配的标签名, 多个标签名之间用空格分割"," * @return { Node | NULL } 如果找到标签名匹配的节点, 则返回该节点, 否则返回NULL"," * @example"," * ```javascript"," * var divNodes = document.getElementsByTagName(\"div\");"," * divNodes = [].slice.call( divNodes, 0 );"," *"," * //output: null"," * console.log( UE.dom.domUtils.filterNodeList( divNodes, 'a span' ) );"," * ```"," */",""," /**"," * 给定一个节点数组,在通过指定的过滤器过滤后, 如果参数forAll为true, 则会返回所有满足过滤"," * 条件的节点集合, 否则, 返回满足条件的节点集合中的第一个节点"," * @method filterNodeList"," * @param { Array } nodeList 需要过滤的节点数组"," * @param { Function } fn 过滤器, 对符合条件的节点, 执行结果返回true, 反之则返回false"," * @param { Boolean } forAll 是否返回整个节点数组, 如果该参数为false, 则返回节点集合中的第一个节点"," * @return { Array | Node | NULL } 如果找到符合过滤条件的节点, 则根据参数forAll的值决定返回满足"," * 过滤条件的节点数组或第一个节点, 否则返回NULL"," * @example"," * ```javascript"," * var divNodes = document.getElementsByTagName(\"div\");"," * divNodes = [].slice.call( divNodes, 0 );"," *"," * //output: 3(假定有3个div)"," * console.log( divNodes.length );"," *"," * var nodes = UE.dom.domUtils.filterNodeList( divNodes, function ( node ) {"," * return node.tagName.toLowerCase() === 'div';"," * }, true );"," *"," * //output: 3"," * console.log( nodes.length );"," *"," * var node = UE.dom.domUtils.filterNodeList( divNodes, function ( node ) {"," * return node.tagName.toLowerCase() === 'div';"," * }, false );"," *"," * //output: div"," * console.log( node.nodeName );"," * ```"," */"," filterNodeList : function(nodelist,filter,forAll){"," var results = [];"," if(!utils .isFunction(filter)){"," var str = filter;"," filter = function(n){"," return utils.indexOf(utils.isArray(str) ? str:str.split(' '), n.tagName.toLowerCase()) != -1"," };"," }"," utils.each(nodelist,function(n){"," filter(n) && results.push(n)"," });"," return results.length == 0 ? null : results.length == 1 || !forAll ? results[0] : results"," },",""," isInNodeEndBoundary : function (rng,node){"," var start = rng.startContainer;"," if(start.nodeType == 3 && rng.startOffset != start.nodeValue.length){"," return 0;"," }"," if(start.nodeType == 1 && rng.startOffset != start.childNodes.length){"," return 0;"," }"," while(start !== node){"," if(start.nextSibling){"," return 0"," };"," start = start.parentNode;"," }"," return 1;"," },"," isBoundaryNode : function (node,dir){"," var tmp;"," while(!domUtils.isBody(node)){"," tmp = node;"," node = node.parentNode;"," if(tmp !== node[dir]){"," return false;"," }"," }"," return true;"," }","};","var fillCharReg = new RegExp(domUtils.fillChar, 'g');"]; +_$jscoverage['core/domUtils.js'][15]++; +function getNode(node, start, ltr, startFromChild, fn, guard) { + _$jscoverage['core/domUtils.js'][16]++; + var tmpNode = (startFromChild && node[start]), parent; + _$jscoverage['core/domUtils.js'][18]++; + ((! tmpNode) && (tmpNode = node[ltr])); + _$jscoverage['core/domUtils.js'][19]++; + while (((! tmpNode) && (parent = (parent || node).parentNode))) { + _$jscoverage['core/domUtils.js'][20]++; + if (((parent.tagName == "BODY") || (guard && (! guard(parent))))) { + _$jscoverage['core/domUtils.js'][21]++; + return null; + } + _$jscoverage['core/domUtils.js'][23]++; + tmpNode = parent[ltr]; +} + _$jscoverage['core/domUtils.js'][25]++; + if ((tmpNode && fn && (! fn(tmpNode)))) { + _$jscoverage['core/domUtils.js'][26]++; + return getNode(tmpNode, start, ltr, false, fn); + } + _$jscoverage['core/domUtils.js'][28]++; + return tmpNode; +} +_$jscoverage['core/domUtils.js'][30]++; +var attrFix = ((ie && (browser.version < 9))? {tabindex: "tabIndex", readonly: "readOnly", "for": "htmlFor", "class": "className", maxlength: "maxLength", cellspacing: "cellSpacing", cellpadding: "cellPadding", rowspan: "rowSpan", colspan: "colSpan", usemap: "useMap", frameborder: "frameBorder"}: {tabindex: "tabIndex", readonly: "readOnly"}), styleBlock = utils.listToMap(["-webkit-box", "-moz-box", "block", "list-item", "table", "table-row-group", "table-header-group", "table-footer-group", "table-row", "table-column-group", "table-column", "table-cell", "table-caption"]); +_$jscoverage['core/domUtils.js'][53]++; +var domUtils = (dom.domUtils = {NODE_ELEMENT: 1, NODE_DOCUMENT: 9, NODE_TEXT: 3, NODE_COMMENT: 8, NODE_DOCUMENT_FRAGMENT: 11, POSITION_IDENTICAL: 0, POSITION_DISCONNECTED: 1, POSITION_FOLLOWING: 2, POSITION_PRECEDING: 4, POSITION_IS_CONTAINED: 8, POSITION_CONTAINS: 16, fillChar: ((ie && (browser.version == "6"))? "\ufeff": "\u200b"), keys: {8: 1, 46: 1, 16: 1, 17: 1, 18: 1, 37: 1, 38: 1, 39: 1, 40: 1, 13: 1}, getPosition: (function (nodeA, nodeB) { + _$jscoverage['core/domUtils.js'][120]++; + if ((nodeA === nodeB)) { + _$jscoverage['core/domUtils.js'][122]++; + return 0; + } + _$jscoverage['core/domUtils.js'][124]++; + var node, parentsA = [nodeA], parentsB = [nodeB]; + _$jscoverage['core/domUtils.js'][127]++; + node = nodeA; + _$jscoverage['core/domUtils.js'][128]++; + while ((node = node.parentNode)) { + _$jscoverage['core/domUtils.js'][130]++; + if ((node === nodeB)) { + _$jscoverage['core/domUtils.js'][132]++; + return 10; + } + _$jscoverage['core/domUtils.js'][134]++; + parentsA.push(node); +} + _$jscoverage['core/domUtils.js'][136]++; + node = nodeB; + _$jscoverage['core/domUtils.js'][137]++; + while ((node = node.parentNode)) { + _$jscoverage['core/domUtils.js'][139]++; + if ((node === nodeA)) { + _$jscoverage['core/domUtils.js'][141]++; + return 20; + } + _$jscoverage['core/domUtils.js'][143]++; + parentsB.push(node); +} + _$jscoverage['core/domUtils.js'][145]++; + parentsA.reverse(); + _$jscoverage['core/domUtils.js'][146]++; + parentsB.reverse(); + _$jscoverage['core/domUtils.js'][147]++; + if ((parentsA[0] !== parentsB[0])) { + _$jscoverage['core/domUtils.js'][149]++; + return 1; + } + _$jscoverage['core/domUtils.js'][151]++; + var i = -1; + _$jscoverage['core/domUtils.js'][152]++; + while (((i++), (parentsA[i] === parentsB[i]))) { +} + _$jscoverage['core/domUtils.js'][154]++; + nodeA = parentsA[i]; + _$jscoverage['core/domUtils.js'][155]++; + nodeB = parentsB[i]; + _$jscoverage['core/domUtils.js'][156]++; + while ((nodeA = nodeA.nextSibling)) { + _$jscoverage['core/domUtils.js'][157]++; + if ((nodeA === nodeB)) { + _$jscoverage['core/domUtils.js'][159]++; + return 4; + } +} + _$jscoverage['core/domUtils.js'][163]++; + return 2; +}), getNodeIndex: (function (node, ignoreTextNode) { + _$jscoverage['core/domUtils.js'][181]++; + var preNode = node, i = 0; + _$jscoverage['core/domUtils.js'][183]++; + while ((preNode = preNode.previousSibling)) { + _$jscoverage['core/domUtils.js'][184]++; + if ((ignoreTextNode && (preNode.nodeType == 3))) { + _$jscoverage['core/domUtils.js'][185]++; + if ((preNode.nodeType != preNode.nextSibling.nodeType)) { + _$jscoverage['core/domUtils.js'][186]++; + (i++); + } + _$jscoverage['core/domUtils.js'][188]++; + continue; + } + _$jscoverage['core/domUtils.js'][190]++; + (i++); +} + _$jscoverage['core/domUtils.js'][192]++; + return i; +}), inDoc: (function (node, doc) { + _$jscoverage['core/domUtils.js'][217]++; + return (domUtils.getPosition(node, doc) == 10); +}), findParent: (function (node, filterFn, includeSelf) { + _$jscoverage['core/domUtils.js'][279]++; + if ((node && (! domUtils.isBody(node)))) { + _$jscoverage['core/domUtils.js'][280]++; + node = (includeSelf? node: node.parentNode); + _$jscoverage['core/domUtils.js'][281]++; + while (node) { + _$jscoverage['core/domUtils.js'][282]++; + if (((! filterFn) || filterFn(node) || domUtils.isBody(node))) { + _$jscoverage['core/domUtils.js'][283]++; + return ((filterFn && (! filterFn(node)) && domUtils.isBody(node))? null: node); + } + _$jscoverage['core/domUtils.js'][285]++; + node = node.parentNode; +} + } + _$jscoverage['core/domUtils.js'][288]++; + return null; +}), findParentByTagName: (function (node, tagNames, includeSelf, excludeFn) { + _$jscoverage['core/domUtils.js'][350]++; + tagNames = utils.listToMap((utils.isArray(tagNames)? tagNames: [tagNames])); + _$jscoverage['core/domUtils.js'][351]++; + return domUtils.findParent(node, (function (node) { + _$jscoverage['core/domUtils.js'][352]++; + return (tagNames[node.tagName] && (! (excludeFn && excludeFn(node)))); +}), includeSelf); +}), findParents: (function (node, includeSelf, filterFn, closerFirst) { + _$jscoverage['core/domUtils.js'][365]++; + var parents = ((includeSelf && ((filterFn && filterFn(node)) || (! filterFn)))? [node]: []); + _$jscoverage['core/domUtils.js'][366]++; + while ((node = domUtils.findParent(node, filterFn))) { + _$jscoverage['core/domUtils.js'][367]++; + parents.push(node); +} + _$jscoverage['core/domUtils.js'][369]++; + return (closerFirst? parents: parents.reverse()); +}), insertAfter: (function (node, newNode) { + _$jscoverage['core/domUtils.js'][380]++; + return node.parentNode.insertBefore(newNode, node.nextSibling); +}), remove: (function (node, keepChildren) { + _$jscoverage['core/domUtils.js'][420]++; + var parent = node.parentNode, child; + _$jscoverage['core/domUtils.js'][422]++; + if (parent) { + _$jscoverage['core/domUtils.js'][423]++; + if ((keepChildren && node.hasChildNodes())) { + _$jscoverage['core/domUtils.js'][424]++; + while ((child = node.firstChild)) { + _$jscoverage['core/domUtils.js'][425]++; + parent.insertBefore(child, node); +} + } + _$jscoverage['core/domUtils.js'][428]++; + parent.removeChild(node); + } + _$jscoverage['core/domUtils.js'][430]++; + return node; +}), getNextNode: (function (node, startFromChild, filterFn, guard) { + _$jscoverage['core/domUtils.js'][437]++; + return getNode(node, "firstChild", "nextSibling", startFromChild, filterFn, guard); +}), isBookmarkNode: (function (node) { + _$jscoverage['core/domUtils.js'][456]++; + return ((node.nodeType == 1) && node.id && /^_baidu_bookmark_/i.test(node.id)); +}), getWindow: (function (node) { + _$jscoverage['core/domUtils.js'][471]++; + var doc = (node.ownerDocument || node); + _$jscoverage['core/domUtils.js'][472]++; + return (doc.defaultView || doc.parentWindow); +}), getCommonAncestor: (function (nodeA, nodeB) { + _$jscoverage['core/domUtils.js'][490]++; + if ((nodeA === nodeB)) { + _$jscoverage['core/domUtils.js'][491]++; + return nodeA; + } + _$jscoverage['core/domUtils.js'][492]++; + var parentsA = [nodeA], parentsB = [nodeB], parent = nodeA, i = -1; + _$jscoverage['core/domUtils.js'][493]++; + while ((parent = parent.parentNode)) { + _$jscoverage['core/domUtils.js'][494]++; + if ((parent === nodeB)) { + _$jscoverage['core/domUtils.js'][495]++; + return parent; + } + _$jscoverage['core/domUtils.js'][497]++; + parentsA.push(parent); +} + _$jscoverage['core/domUtils.js'][499]++; + parent = nodeB; + _$jscoverage['core/domUtils.js'][500]++; + while ((parent = parent.parentNode)) { + _$jscoverage['core/domUtils.js'][501]++; + if ((parent === nodeA)) { + _$jscoverage['core/domUtils.js'][502]++; + return parent; + } + _$jscoverage['core/domUtils.js'][503]++; + parentsB.push(parent); +} + _$jscoverage['core/domUtils.js'][505]++; + parentsA.reverse(); + _$jscoverage['core/domUtils.js'][506]++; + parentsB.reverse(); + _$jscoverage['core/domUtils.js'][507]++; + while (((i++), (parentsA[i] === parentsB[i]))) { +} + _$jscoverage['core/domUtils.js'][509]++; + return ((i == 0)? null: parentsA[(i - 1)]); +}), clearEmptySibling: (function (node, ignoreNext, ignorePre) { + _$jscoverage['core/domUtils.js'][523]++; + function clear(next, dir) { + _$jscoverage['core/domUtils.js'][524]++; + var tmpNode; + _$jscoverage['core/domUtils.js'][525]++; + while ((next && (! domUtils.isBookmarkNode(next)) && (domUtils.isEmptyInlineElement(next) || (! new RegExp(("[^\t\n\r" + domUtils.fillChar + "]")).test(next.nodeValue))))) { + _$jscoverage['core/domUtils.js'][528]++; + tmpNode = next[dir]; + _$jscoverage['core/domUtils.js'][529]++; + domUtils.remove(next); + _$jscoverage['core/domUtils.js'][530]++; + next = tmpNode; +} +} + _$jscoverage['core/domUtils.js'][533]++; + ((! ignoreNext) && clear(node.nextSibling, "nextSibling")); + _$jscoverage['core/domUtils.js'][534]++; + ((! ignorePre) && clear(node.previousSibling, "previousSibling")); +}), split: (function (node, offset) { + _$jscoverage['core/domUtils.js'][554]++; + var doc = node.ownerDocument; + _$jscoverage['core/domUtils.js'][555]++; + if ((browser.ie && (offset == node.nodeValue.length))) { + _$jscoverage['core/domUtils.js'][556]++; + var next = doc.createTextNode(""); + _$jscoverage['core/domUtils.js'][557]++; + return domUtils.insertAfter(node, next); + } + _$jscoverage['core/domUtils.js'][559]++; + var retval = node.splitText(offset); + _$jscoverage['core/domUtils.js'][561]++; + if (browser.ie8) { + _$jscoverage['core/domUtils.js'][562]++; + var tmpNode = doc.createTextNode(""); + _$jscoverage['core/domUtils.js'][563]++; + domUtils.insertAfter(retval, tmpNode); + _$jscoverage['core/domUtils.js'][564]++; + domUtils.remove(tmpNode); + } + _$jscoverage['core/domUtils.js'][566]++; + return retval; +}), isWhitespace: (function (node) { + _$jscoverage['core/domUtils.js'][586]++; + return (! new RegExp(("[^ \t\n\r" + domUtils.fillChar + "]")).test(node.nodeValue)); +}), getXY: (function (element) { + _$jscoverage['core/domUtils.js'][604]++; + var x = 0, y = 0; + _$jscoverage['core/domUtils.js'][605]++; + while (element.offsetParent) { + _$jscoverage['core/domUtils.js'][606]++; + y += element.offsetTop; + _$jscoverage['core/domUtils.js'][607]++; + x += element.offsetLeft; + _$jscoverage['core/domUtils.js'][608]++; + element = element.offsetParent; +} + _$jscoverage['core/domUtils.js'][610]++; + return ({"x": x, "y": y}); +}), on: (function (element, type, handler) { + _$jscoverage['core/domUtils.js'][641]++; + var types = (utils.isArray(type)? type: [type]), k = types.length; + _$jscoverage['core/domUtils.js'][643]++; + if (k) { + _$jscoverage['core/domUtils.js'][643]++; + while ((k--)) { + _$jscoverage['core/domUtils.js'][644]++; + type = types[k]; + _$jscoverage['core/domUtils.js'][645]++; + if (element.addEventListener) { + _$jscoverage['core/domUtils.js'][646]++; + element.addEventListener(type, handler, false); + } + else { + _$jscoverage['core/domUtils.js'][648]++; + if ((! handler._d)) { + _$jscoverage['core/domUtils.js'][649]++; + handler._d = {els: []}; + } + _$jscoverage['core/domUtils.js'][653]++; + var key = (type + handler.toString()), index = utils.indexOf(handler._d.els, element); + _$jscoverage['core/domUtils.js'][654]++; + if (((! handler._d[key]) || (index == -1))) { + _$jscoverage['core/domUtils.js'][655]++; + if ((index == -1)) { + _$jscoverage['core/domUtils.js'][656]++; + handler._d.els.push(element); + } + _$jscoverage['core/domUtils.js'][658]++; + if ((! handler._d[key])) { + _$jscoverage['core/domUtils.js'][659]++; + handler._d[key] = (function (evt) { + _$jscoverage['core/domUtils.js'][660]++; + return handler.call(evt.srcElement, (evt || window.event)); +}); + } + _$jscoverage['core/domUtils.js'][665]++; + element.attachEvent(("on" + type), handler._d[key]); + } + } +} + } + _$jscoverage['core/domUtils.js'][669]++; + element = null; +}), un: (function (element, type, handler) { + _$jscoverage['core/domUtils.js'][700]++; + var types = (utils.isArray(type)? type: [type]), k = types.length; + _$jscoverage['core/domUtils.js'][702]++; + if (k) { + _$jscoverage['core/domUtils.js'][702]++; + while ((k--)) { + _$jscoverage['core/domUtils.js'][703]++; + type = types[k]; + _$jscoverage['core/domUtils.js'][704]++; + if (element.removeEventListener) { + _$jscoverage['core/domUtils.js'][705]++; + element.removeEventListener(type, handler, false); + } + else { + _$jscoverage['core/domUtils.js'][707]++; + var key = (type + handler.toString()); + _$jscoverage['core/domUtils.js'][708]++; + try { + _$jscoverage['core/domUtils.js'][709]++; + element.detachEvent(("on" + type), (handler._d? handler._d[key]: handler)); + } + catch (e) { + } + _$jscoverage['core/domUtils.js'][711]++; + if ((handler._d && handler._d[key])) { + _$jscoverage['core/domUtils.js'][712]++; + var index = utils.indexOf(handler._d.els, element); + _$jscoverage['core/domUtils.js'][713]++; + if ((index != -1)) { + _$jscoverage['core/domUtils.js'][714]++; + handler._d.els.splice(index, 1); + } + _$jscoverage['core/domUtils.js'][716]++; + ((handler._d.els.length == 0) && (delete handler._d[key])); + } + } +} + } +}), isSameElement: (function (nodeA, nodeB) { + _$jscoverage['core/domUtils.js'][749]++; + if ((nodeA.tagName != nodeB.tagName)) { + _$jscoverage['core/domUtils.js'][750]++; + return false; + } + _$jscoverage['core/domUtils.js'][752]++; + var thisAttrs = nodeA.attributes, otherAttrs = nodeB.attributes; + _$jscoverage['core/domUtils.js'][754]++; + if (((! ie) && (thisAttrs.length != otherAttrs.length))) { + _$jscoverage['core/domUtils.js'][755]++; + return false; + } + _$jscoverage['core/domUtils.js'][757]++; + var attrA, attrB, al = 0, bl = 0; + _$jscoverage['core/domUtils.js'][758]++; + for (var i = 0; (attrA = thisAttrs[(i++)]);) { + _$jscoverage['core/domUtils.js'][759]++; + if ((attrA.nodeName == "style")) { + _$jscoverage['core/domUtils.js'][760]++; + if (attrA.specified) { + _$jscoverage['core/domUtils.js'][761]++; + (al++); + } + _$jscoverage['core/domUtils.js'][763]++; + if (domUtils.isSameStyle(nodeA, nodeB)) { + _$jscoverage['core/domUtils.js'][764]++; + continue; + } + else { + _$jscoverage['core/domUtils.js'][766]++; + return false; + } + } + _$jscoverage['core/domUtils.js'][769]++; + if (ie) { + _$jscoverage['core/domUtils.js'][770]++; + if (attrA.specified) { + _$jscoverage['core/domUtils.js'][771]++; + (al++); + _$jscoverage['core/domUtils.js'][772]++; + attrB = otherAttrs.getNamedItem(attrA.nodeName); + } + else { + _$jscoverage['core/domUtils.js'][774]++; + continue; + } + } + else { + _$jscoverage['core/domUtils.js'][777]++; + attrB = nodeB.attributes[attrA.nodeName]; + } + _$jscoverage['core/domUtils.js'][779]++; + if (((! attrB.specified) || (attrA.nodeValue != attrB.nodeValue))) { + _$jscoverage['core/domUtils.js'][780]++; + return false; + } +} + _$jscoverage['core/domUtils.js'][784]++; + if (ie) { + _$jscoverage['core/domUtils.js'][785]++; + for (i = 0; (attrB = otherAttrs[(i++)]);) { + _$jscoverage['core/domUtils.js'][786]++; + if (attrB.specified) { + _$jscoverage['core/domUtils.js'][787]++; + (bl++); + } +} + _$jscoverage['core/domUtils.js'][790]++; + if ((al != bl)) { + _$jscoverage['core/domUtils.js'][791]++; + return false; + } + } + _$jscoverage['core/domUtils.js'][794]++; + return true; +}), isSameStyle: (function (nodeA, nodeB) { + _$jscoverage['core/domUtils.js'][824]++; + var styleA = nodeA.style.cssText.replace(/( ?; ?)/g, ";").replace(/( ?: ?)/g, ":"), styleB = nodeB.style.cssText.replace(/( ?; ?)/g, ";").replace(/( ?: ?)/g, ":"); + _$jscoverage['core/domUtils.js'][826]++; + if (browser.opera) { + _$jscoverage['core/domUtils.js'][827]++; + styleA = nodeA.style; + _$jscoverage['core/domUtils.js'][828]++; + styleB = nodeB.style; + _$jscoverage['core/domUtils.js'][829]++; + if ((styleA.length != styleB.length)) { + _$jscoverage['core/domUtils.js'][830]++; + return false; + } + _$jscoverage['core/domUtils.js'][831]++; + for (var p in styleA) { + _$jscoverage['core/domUtils.js'][832]++; + if (/^(\d+|csstext)$/i.test(p)) { + _$jscoverage['core/domUtils.js'][833]++; + continue; + } + _$jscoverage['core/domUtils.js'][835]++; + if ((styleA[p] != styleB[p])) { + _$jscoverage['core/domUtils.js'][836]++; + return false; + } +} + _$jscoverage['core/domUtils.js'][839]++; + return true; + } + _$jscoverage['core/domUtils.js'][841]++; + if (((! styleA) || (! styleB))) { + _$jscoverage['core/domUtils.js'][842]++; + return (styleA == styleB); + } + _$jscoverage['core/domUtils.js'][844]++; + styleA = styleA.split(";"); + _$jscoverage['core/domUtils.js'][845]++; + styleB = styleB.split(";"); + _$jscoverage['core/domUtils.js'][846]++; + if ((styleA.length != styleB.length)) { + _$jscoverage['core/domUtils.js'][847]++; + return false; + } + _$jscoverage['core/domUtils.js'][849]++; + for (var i = 0, ci; (ci = styleA[(i++)]);) { + _$jscoverage['core/domUtils.js'][850]++; + if ((utils.indexOf(styleB, ci) == -1)) { + _$jscoverage['core/domUtils.js'][851]++; + return false; + } +} + _$jscoverage['core/domUtils.js'][854]++; + return true; +}), isBlockElm: (function (node) { + _$jscoverage['core/domUtils.js'][885]++; + return ((node.nodeType == 1) && (dtd.$block[node.tagName] || styleBlock[domUtils.getComputedStyle(node, "display")]) && (! dtd.$nonChild[node.tagName])); +}), isBody: (function (node) { + _$jscoverage['core/domUtils.js'][900]++; + return (node && (node.nodeType == 1) && (node.tagName.toLowerCase() == "body")); +}), breakParent: (function (node, parent) { + _$jscoverage['core/domUtils.js'][913]++; + var tmpNode, parentClone = node, clone = node, leftNodes, rightNodes; + _$jscoverage['core/domUtils.js'][918]++; + do { + _$jscoverage['core/domUtils.js'][919]++; + parentClone = parentClone.parentNode; + _$jscoverage['core/domUtils.js'][920]++; + if (leftNodes) { + _$jscoverage['core/domUtils.js'][921]++; + tmpNode = parentClone.cloneNode(false); + _$jscoverage['core/domUtils.js'][922]++; + tmpNode.appendChild(leftNodes); + _$jscoverage['core/domUtils.js'][923]++; + leftNodes = tmpNode; + _$jscoverage['core/domUtils.js'][924]++; + tmpNode = parentClone.cloneNode(false); + _$jscoverage['core/domUtils.js'][925]++; + tmpNode.appendChild(rightNodes); + _$jscoverage['core/domUtils.js'][926]++; + rightNodes = tmpNode; + } + else { + _$jscoverage['core/domUtils.js'][928]++; + leftNodes = parentClone.cloneNode(false); + _$jscoverage['core/domUtils.js'][929]++; + rightNodes = leftNodes.cloneNode(false); + } + _$jscoverage['core/domUtils.js'][931]++; + while ((tmpNode = clone.previousSibling)) { + _$jscoverage['core/domUtils.js'][932]++; + leftNodes.insertBefore(tmpNode, leftNodes.firstChild); +} + _$jscoverage['core/domUtils.js'][934]++; + while ((tmpNode = clone.nextSibling)) { + _$jscoverage['core/domUtils.js'][935]++; + rightNodes.appendChild(tmpNode); +} + _$jscoverage['core/domUtils.js'][937]++; + clone = parentClone; +} + while ((parent !== parentClone)); + _$jscoverage['core/domUtils.js'][939]++; + tmpNode = parent.parentNode; + _$jscoverage['core/domUtils.js'][940]++; + tmpNode.insertBefore(leftNodes, parent); + _$jscoverage['core/domUtils.js'][941]++; + tmpNode.insertBefore(rightNodes, parent); + _$jscoverage['core/domUtils.js'][942]++; + tmpNode.insertBefore(node, rightNodes); + _$jscoverage['core/domUtils.js'][943]++; + domUtils.remove(parent); + _$jscoverage['core/domUtils.js'][944]++; + return node; +}), isEmptyInlineElement: (function (node) { + _$jscoverage['core/domUtils.js'][958]++; + if (((node.nodeType != 1) || (! dtd.$removeEmpty[node.tagName]))) { + _$jscoverage['core/domUtils.js'][959]++; + return 0; + } + _$jscoverage['core/domUtils.js'][961]++; + node = node.firstChild; + _$jscoverage['core/domUtils.js'][962]++; + while (node) { + _$jscoverage['core/domUtils.js'][964]++; + if (domUtils.isBookmarkNode(node)) { + _$jscoverage['core/domUtils.js'][965]++; + return 0; + } + _$jscoverage['core/domUtils.js'][967]++; + if ((((node.nodeType == 1) && (! domUtils.isEmptyInlineElement(node))) || ((node.nodeType == 3) && (! domUtils.isWhitespace(node))))) { + _$jscoverage['core/domUtils.js'][970]++; + return 0; + } + _$jscoverage['core/domUtils.js'][972]++; + node = node.nextSibling; +} + _$jscoverage['core/domUtils.js'][974]++; + return 1; +}), trimWhiteTextNode: (function (node) { + _$jscoverage['core/domUtils.js'][1000]++; + function remove(dir) { + _$jscoverage['core/domUtils.js'][1001]++; + var child; + _$jscoverage['core/domUtils.js'][1002]++; + while (((child = node[dir]) && (child.nodeType == 3) && domUtils.isWhitespace(child))) { + _$jscoverage['core/domUtils.js'][1003]++; + node.removeChild(child); +} +} + _$jscoverage['core/domUtils.js'][1006]++; + remove("firstChild"); + _$jscoverage['core/domUtils.js'][1007]++; + remove("lastChild"); +}), mergeChild: (function (node, tagName, attrs) { + _$jscoverage['core/domUtils.js'][1019]++; + var list = domUtils.getElementsByTagName(node, node.tagName.toLowerCase()); + _$jscoverage['core/domUtils.js'][1020]++; + for (var i = 0, ci; (ci = list[(i++)]);) { + _$jscoverage['core/domUtils.js'][1021]++; + if (((! ci.parentNode) || domUtils.isBookmarkNode(ci))) { + _$jscoverage['core/domUtils.js'][1022]++; + continue; + } + _$jscoverage['core/domUtils.js'][1025]++; + if ((ci.tagName.toLowerCase() == "span")) { + _$jscoverage['core/domUtils.js'][1026]++; + if ((node === ci.parentNode)) { + _$jscoverage['core/domUtils.js'][1027]++; + domUtils.trimWhiteTextNode(node); + _$jscoverage['core/domUtils.js'][1028]++; + if ((node.childNodes.length == 1)) { + _$jscoverage['core/domUtils.js'][1029]++; + node.style.cssText = (ci.style.cssText + ";" + node.style.cssText); + _$jscoverage['core/domUtils.js'][1030]++; + domUtils.remove(ci, true); + _$jscoverage['core/domUtils.js'][1031]++; + continue; + } + } + _$jscoverage['core/domUtils.js'][1034]++; + ci.style.cssText = (node.style.cssText + ";" + ci.style.cssText); + _$jscoverage['core/domUtils.js'][1035]++; + if (attrs) { + _$jscoverage['core/domUtils.js'][1036]++; + var style = attrs.style; + _$jscoverage['core/domUtils.js'][1037]++; + if (style) { + _$jscoverage['core/domUtils.js'][1038]++; + style = style.split(";"); + _$jscoverage['core/domUtils.js'][1039]++; + for (var j = 0, s; (s = style[(j++)]);) { + _$jscoverage['core/domUtils.js'][1040]++; + ci.style[utils.cssStyleToDomStyle(s.split(":")[0])] = s.split(":")[1]; +} + } + } + _$jscoverage['core/domUtils.js'][1044]++; + if (domUtils.isSameStyle(ci, node)) { + _$jscoverage['core/domUtils.js'][1045]++; + domUtils.remove(ci, true); + } + _$jscoverage['core/domUtils.js'][1047]++; + continue; + } + _$jscoverage['core/domUtils.js'][1049]++; + if (domUtils.isSameElement(node, ci)) { + _$jscoverage['core/domUtils.js'][1050]++; + domUtils.remove(ci, true); + } +} +}), getElementsByTagName: (function (node, name, filter) { + _$jscoverage['core/domUtils.js'][1061]++; + if ((filter && utils.isString(filter))) { + _$jscoverage['core/domUtils.js'][1062]++; + var className = filter; + _$jscoverage['core/domUtils.js'][1063]++; + filter = (function (node) { + _$jscoverage['core/domUtils.js'][1063]++; + return domUtils.hasClass(node, className); +}); + } + _$jscoverage['core/domUtils.js'][1065]++; + name = utils.trim(name).replace(/[ ]{2,}/g, " ").split(" "); + _$jscoverage['core/domUtils.js'][1066]++; + var arr = []; + _$jscoverage['core/domUtils.js'][1067]++; + for (var n = 0, ni; (ni = name[(n++)]);) { + _$jscoverage['core/domUtils.js'][1068]++; + var list = node.getElementsByTagName(ni); + _$jscoverage['core/domUtils.js'][1069]++; + for (var i = 0, ci; (ci = list[(i++)]);) { + _$jscoverage['core/domUtils.js'][1070]++; + if (((! filter) || filter(ci))) { + _$jscoverage['core/domUtils.js'][1071]++; + arr.push(ci); + } +} +} + _$jscoverage['core/domUtils.js'][1075]++; + return arr; +}), mergeToParent: (function (node) { + _$jscoverage['core/domUtils.js'][1106]++; + var parent = node.parentNode; + _$jscoverage['core/domUtils.js'][1107]++; + while ((parent && dtd.$removeEmpty[parent.tagName])) { + _$jscoverage['core/domUtils.js'][1108]++; + if (((parent.tagName == node.tagName) || (parent.tagName == "A"))) { + _$jscoverage['core/domUtils.js'][1109]++; + domUtils.trimWhiteTextNode(parent); + _$jscoverage['core/domUtils.js'][1111]++; + if ((((parent.tagName == "SPAN") && (! domUtils.isSameStyle(parent, node))) || ((parent.tagName == "A") && (node.tagName == "SPAN")))) { + _$jscoverage['core/domUtils.js'][1113]++; + if (((parent.childNodes.length > 1) || (parent !== node.parentNode))) { + _$jscoverage['core/domUtils.js'][1114]++; + node.style.cssText = (parent.style.cssText + ";" + node.style.cssText); + _$jscoverage['core/domUtils.js'][1115]++; + parent = parent.parentNode; + _$jscoverage['core/domUtils.js'][1116]++; + continue; + } + else { + _$jscoverage['core/domUtils.js'][1118]++; + parent.style.cssText += (";" + node.style.cssText); + _$jscoverage['core/domUtils.js'][1120]++; + if ((parent.tagName == "A")) { + _$jscoverage['core/domUtils.js'][1121]++; + parent.style.textDecoration = "underline"; + } + } + } + _$jscoverage['core/domUtils.js'][1125]++; + if ((parent.tagName != "A")) { + _$jscoverage['core/domUtils.js'][1126]++; + ((parent === node.parentNode) && domUtils.remove(node, true)); + _$jscoverage['core/domUtils.js'][1127]++; + break; + } + } + _$jscoverage['core/domUtils.js'][1130]++; + parent = parent.parentNode; +} +}), mergeSibling: (function (node, ignorePre, ignoreNext) { + _$jscoverage['core/domUtils.js'][1189]++; + function merge(rtl, start, node) { + _$jscoverage['core/domUtils.js'][1190]++; + var next; + _$jscoverage['core/domUtils.js'][1191]++; + if (((next = node[rtl]) && (! domUtils.isBookmarkNode(next)) && (next.nodeType == 1) && domUtils.isSameElement(node, next))) { + _$jscoverage['core/domUtils.js'][1192]++; + while (next.firstChild) { + _$jscoverage['core/domUtils.js'][1193]++; + if ((start == "firstChild")) { + _$jscoverage['core/domUtils.js'][1194]++; + node.insertBefore(next.lastChild, node.firstChild); + } + else { + _$jscoverage['core/domUtils.js'][1196]++; + node.appendChild(next.firstChild); + } +} + _$jscoverage['core/domUtils.js'][1199]++; + domUtils.remove(next); + } +} + _$jscoverage['core/domUtils.js'][1202]++; + ((! ignorePre) && merge("previousSibling", "firstChild", node)); + _$jscoverage['core/domUtils.js'][1203]++; + ((! ignoreNext) && merge("nextSibling", "lastChild", node)); +}), unSelectable: ((ie || browser.opera)? (function (node) { + _$jscoverage['core/domUtils.js'][1218]++; + node.onselectstart = (function () { + _$jscoverage['core/domUtils.js'][1219]++; + return false; +}); + _$jscoverage['core/domUtils.js'][1221]++; + node.onclick = (node.onkeyup = (node.onkeydown = (function () { + _$jscoverage['core/domUtils.js'][1222]++; + return false; +}))); + _$jscoverage['core/domUtils.js'][1224]++; + node.unselectable = "on"; + _$jscoverage['core/domUtils.js'][1225]++; + node.setAttribute("unselectable", "on"); + _$jscoverage['core/domUtils.js'][1226]++; + for (var i = 0, ci; (ci = node.all[(i++)]);) { + _$jscoverage['core/domUtils.js'][1227]++; + switch (ci.tagName.toLowerCase()) { + case "iframe": + case "textarea": + case "input": + case "select": + _$jscoverage['core/domUtils.js'][1232]++; + break; + default: + _$jscoverage['core/domUtils.js'][1234]++; + ci.unselectable = "on"; + _$jscoverage['core/domUtils.js'][1235]++; + node.setAttribute("unselectable", "on"); + } +} +}): (function (node) { + _$jscoverage['core/domUtils.js'][1239]++; + node.style.MozUserSelect = (node.style.webkitUserSelect = (node.style.KhtmlUserSelect = "none")); +})), removeAttributes: (function (node, attrNames) { + _$jscoverage['core/domUtils.js'][1286]++; + attrNames = (utils.isArray(attrNames)? attrNames: utils.trim(attrNames).replace(/[ ]{2,}/g, " ").split(" ")); + _$jscoverage['core/domUtils.js'][1287]++; + for (var i = 0, ci; (ci = attrNames[(i++)]);) { + _$jscoverage['core/domUtils.js'][1288]++; + ci = (attrFix[ci] || ci); + _$jscoverage['core/domUtils.js'][1289]++; + switch (ci) { + case "className": + _$jscoverage['core/domUtils.js'][1291]++; + node[ci] = ""; + _$jscoverage['core/domUtils.js'][1292]++; + break; + case "style": + _$jscoverage['core/domUtils.js'][1294]++; + node.style.cssText = ""; + _$jscoverage['core/domUtils.js'][1295]++; + ((! browser.ie) && node.removeAttributeNode(node.getAttributeNode("style"))); + } + _$jscoverage['core/domUtils.js'][1297]++; + node.removeAttribute(ci); +} +}), createElement: (function (doc, tag, attrs) { + _$jscoverage['core/domUtils.js'][1323]++; + return domUtils.setAttributes(doc.createElement(tag), attrs); +}), setAttributes: (function (node, attrs) { + _$jscoverage['core/domUtils.js'][1349]++; + for (var attr in attrs) { + _$jscoverage['core/domUtils.js'][1350]++; + if (attrs.hasOwnProperty(attr)) { + _$jscoverage['core/domUtils.js'][1351]++; + var value = attrs[attr]; + _$jscoverage['core/domUtils.js'][1352]++; + switch (attr) { + case "class": + _$jscoverage['core/domUtils.js'][1355]++; + node.className = value; + _$jscoverage['core/domUtils.js'][1356]++; + break; + case "style": + _$jscoverage['core/domUtils.js'][1358]++; + node.style.cssText = (node.style.cssText + ";" + value); + _$jscoverage['core/domUtils.js'][1359]++; + break; + case "innerHTML": + _$jscoverage['core/domUtils.js'][1361]++; + node[attr] = value; + _$jscoverage['core/domUtils.js'][1362]++; + break; + case "value": + _$jscoverage['core/domUtils.js'][1364]++; + node.value = value; + _$jscoverage['core/domUtils.js'][1365]++; + break; + default: + _$jscoverage['core/domUtils.js'][1367]++; + node.setAttribute((attrFix[attr] || attr), value); + } + } +} + _$jscoverage['core/domUtils.js'][1371]++; + return node; +}), getComputedStyle: (function (element, styleName) { + _$jscoverage['core/domUtils.js'][1398]++; + var pros = "width height top left"; + _$jscoverage['core/domUtils.js'][1400]++; + if ((pros.indexOf(styleName) > -1)) { + _$jscoverage['core/domUtils.js'][1401]++; + return (element[("offset" + styleName.replace(/^\w/, (function (s) { + _$jscoverage['core/domUtils.js'][1401]++; + return s.toUpperCase(); +})))] + "px"); + } + _$jscoverage['core/domUtils.js'][1404]++; + if ((element.nodeType == 3)) { + _$jscoverage['core/domUtils.js'][1405]++; + element = element.parentNode; + } + _$jscoverage['core/domUtils.js'][1408]++; + if ((browser.ie && (browser.version < 9) && (styleName == "font-size") && (! element.style.fontSize) && (! dtd.$empty[element.tagName]) && (! dtd.$nonChild[element.tagName]))) { + _$jscoverage['core/domUtils.js'][1410]++; + var span = element.ownerDocument.createElement("span"); + _$jscoverage['core/domUtils.js'][1411]++; + span.style.cssText = "padding:0;border:0;font-family:simsun;"; + _$jscoverage['core/domUtils.js'][1412]++; + span.innerHTML = "."; + _$jscoverage['core/domUtils.js'][1413]++; + element.appendChild(span); + _$jscoverage['core/domUtils.js'][1414]++; + var result = span.offsetHeight; + _$jscoverage['core/domUtils.js'][1415]++; + element.removeChild(span); + _$jscoverage['core/domUtils.js'][1416]++; + span = null; + _$jscoverage['core/domUtils.js'][1417]++; + return (result + "px"); + } + _$jscoverage['core/domUtils.js'][1419]++; + try { + _$jscoverage['core/domUtils.js'][1420]++; + var value = (domUtils.getStyle(element, styleName) || (window.getComputedStyle? domUtils.getWindow(element).getComputedStyle(element, "").getPropertyValue(styleName): (element.currentStyle || element.style)[utils.cssStyleToDomStyle(styleName)])); + } + catch (e) { + _$jscoverage['core/domUtils.js'][1425]++; + return ""; + } + _$jscoverage['core/domUtils.js'][1427]++; + return utils.transUnitToPx(utils.fixColor(styleName, value)); +}), removeClasses: (function (elm, classNames) { + _$jscoverage['core/domUtils.js'][1471]++; + classNames = (utils.isArray(classNames)? classNames: utils.trim(classNames).replace(/[ ]{2,}/g, " ").split(" ")); + _$jscoverage['core/domUtils.js'][1473]++; + for (var i = 0, ci, cls = elm.className; (ci = classNames[(i++)]);) { + _$jscoverage['core/domUtils.js'][1474]++; + cls = cls.replace(new RegExp(("\\b" + ci + "\\b")), ""); +} + _$jscoverage['core/domUtils.js'][1476]++; + cls = utils.trim(cls).replace(/[ ]{2,}/g, " "); + _$jscoverage['core/domUtils.js'][1477]++; + if (cls) { + _$jscoverage['core/domUtils.js'][1478]++; + elm.className = cls; + } + else { + _$jscoverage['core/domUtils.js'][1480]++; + domUtils.removeAttributes(elm, ["class"]); + } +}), addClass: (function (elm, classNames) { + _$jscoverage['core/domUtils.js'][1528]++; + if ((! elm)) { + _$jscoverage['core/domUtils.js'][1528]++; + return; + } + _$jscoverage['core/domUtils.js'][1529]++; + classNames = utils.trim(classNames).replace(/[ ]{2,}/g, " ").split(" "); + _$jscoverage['core/domUtils.js'][1530]++; + for (var i = 0, ci, cls = elm.className; (ci = classNames[(i++)]);) { + _$jscoverage['core/domUtils.js'][1531]++; + if ((! new RegExp(("\\b" + ci + "\\b")).test(cls))) { + _$jscoverage['core/domUtils.js'][1532]++; + elm.className += (" " + ci); + } +} +}), hasClass: (function (element, className) { + _$jscoverage['core/domUtils.js'][1581]++; + if (utils.isRegExp(className)) { + _$jscoverage['core/domUtils.js'][1582]++; + return className.test(element.className); + } + _$jscoverage['core/domUtils.js'][1584]++; + className = utils.trim(className).replace(/[ ]{2,}/g, " ").split(" "); + _$jscoverage['core/domUtils.js'][1585]++; + for (var i = 0, ci, cls = element.className; (ci = className[(i++)]);) { + _$jscoverage['core/domUtils.js'][1586]++; + if ((! new RegExp(("\\b" + ci + "\\b"), "i").test(cls))) { + _$jscoverage['core/domUtils.js'][1587]++; + return false; + } +} + _$jscoverage['core/domUtils.js'][1590]++; + return ((i - 1) == className.length); +}), preventDefault: (function (evt) { + _$jscoverage['core/domUtils.js'][1603]++; + (evt.preventDefault? evt.preventDefault(): (evt.returnValue = false)); +}), removeStyle: (function (element, name) { + _$jscoverage['core/domUtils.js'][1628]++; + if (browser.ie) { + _$jscoverage['core/domUtils.js'][1630]++; + if ((name == "color")) { + _$jscoverage['core/domUtils.js'][1631]++; + name = ("(^|;)" + name); + } + _$jscoverage['core/domUtils.js'][1633]++; + element.style.cssText = element.style.cssText.replace(new RegExp((name + "[^:]*:[^;]+;?"), "ig"), ""); + } + else { + _$jscoverage['core/domUtils.js'][1635]++; + if (element.style.removeProperty) { + _$jscoverage['core/domUtils.js'][1636]++; + element.style.removeProperty(name); + } + else { + _$jscoverage['core/domUtils.js'][1638]++; + element.style.removeAttribute(utils.cssStyleToDomStyle(name)); + } + } + _$jscoverage['core/domUtils.js'][1643]++; + if ((! element.style.cssText)) { + _$jscoverage['core/domUtils.js'][1644]++; + domUtils.removeAttributes(element, ["style"]); + } +}), getStyle: (function (element, name) { + _$jscoverage['core/domUtils.js'][1673]++; + var value = element.style[utils.cssStyleToDomStyle(name)]; + _$jscoverage['core/domUtils.js'][1674]++; + return utils.fixColor(name, value); +}), setStyle: (function (element, name, value) { + _$jscoverage['core/domUtils.js'][1703]++; + element.style[utils.cssStyleToDomStyle(name)] = value; + _$jscoverage['core/domUtils.js'][1704]++; + if ((! utils.trim(element.style.cssText))) { + _$jscoverage['core/domUtils.js'][1705]++; + this.removeAttributes(element, "style"); + } +}), setStyles: (function (element, styles) { + _$jscoverage['core/domUtils.js'][1735]++; + for (var name in styles) { + _$jscoverage['core/domUtils.js'][1736]++; + if (styles.hasOwnProperty(name)) { + _$jscoverage['core/domUtils.js'][1737]++; + domUtils.setStyle(element, name, styles[name]); + } +} +}), removeDirtyAttr: (function (node) { + _$jscoverage['core/domUtils.js'][1747]++; + for (var i = 0, ci, nodes = node.getElementsByTagName("*"); (ci = nodes[(i++)]);) { + _$jscoverage['core/domUtils.js'][1748]++; + ci.removeAttribute("_moz_dirty"); +} + _$jscoverage['core/domUtils.js'][1750]++; + node.removeAttribute("_moz_dirty"); +}), getChildCount: (function (node, fn) { + _$jscoverage['core/domUtils.js'][1798]++; + var count = 0, first = node.firstChild; + _$jscoverage['core/domUtils.js'][1799]++; + fn = (fn || (function () { + _$jscoverage['core/domUtils.js'][1800]++; + return 1; +})); + _$jscoverage['core/domUtils.js'][1802]++; + while (first) { + _$jscoverage['core/domUtils.js'][1803]++; + if (fn(first)) { + _$jscoverage['core/domUtils.js'][1804]++; + (count++); + } + _$jscoverage['core/domUtils.js'][1806]++; + first = first.nextSibling; +} + _$jscoverage['core/domUtils.js'][1808]++; + return count; +}), isEmptyNode: (function (node) { + _$jscoverage['core/domUtils.js'][1822]++; + return ((! node.firstChild) || (domUtils.getChildCount(node, (function (node) { + _$jscoverage['core/domUtils.js'][1823]++; + return ((! domUtils.isBr(node)) && (! domUtils.isBookmarkNode(node)) && (! domUtils.isWhitespace(node))); +})) == 0)); +}), clearSelectedArr: (function (nodes) { + _$jscoverage['core/domUtils.js'][1839]++; + var node; + _$jscoverage['core/domUtils.js'][1840]++; + while ((node = nodes.pop())) { + _$jscoverage['core/domUtils.js'][1841]++; + domUtils.removeAttributes(node, ["class"]); +} +}), scrollToView: (function (node, win, offsetTop) { + _$jscoverage['core/domUtils.js'][1853]++; + var getViewPaneSize = (function () { + _$jscoverage['core/domUtils.js'][1854]++; + var doc = win.document, mode = (doc.compatMode == "CSS1Compat"); + _$jscoverage['core/domUtils.js'][1856]++; + return ({width: ((mode? doc.documentElement.clientWidth: doc.body.clientWidth) || 0), height: ((mode? doc.documentElement.clientHeight: doc.body.clientHeight) || 0)}); +}), getScrollPosition = (function (win) { + _$jscoverage['core/domUtils.js'][1862]++; + if (("pageXOffset" in win)) { + _$jscoverage['core/domUtils.js'][1863]++; + return ({x: (win.pageXOffset || 0), y: (win.pageYOffset || 0)}); + } + else { + _$jscoverage['core/domUtils.js'][1869]++; + var doc = win.document; + _$jscoverage['core/domUtils.js'][1870]++; + return ({x: (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0), y: (doc.documentElement.scrollTop || doc.body.scrollTop || 0)}); + } +}); + _$jscoverage['core/domUtils.js'][1876]++; + var winHeight = getViewPaneSize().height, offset = ((winHeight * -1) + offsetTop); + _$jscoverage['core/domUtils.js'][1877]++; + offset += (node.offsetHeight || 0); + _$jscoverage['core/domUtils.js'][1878]++; + var elementPosition = domUtils.getXY(node); + _$jscoverage['core/domUtils.js'][1879]++; + offset += elementPosition.y; + _$jscoverage['core/domUtils.js'][1880]++; + var currentScroll = getScrollPosition(win).y; + _$jscoverage['core/domUtils.js'][1882]++; + if (((offset > currentScroll) || (offset < (currentScroll - winHeight)))) { + _$jscoverage['core/domUtils.js'][1883]++; + win.scrollTo(0, (offset + ((offset < 0)? -20: 20))); + } +}), isBr: (function (node) { + _$jscoverage['core/domUtils.js'][1894]++; + return ((node.nodeType == 1) && (node.tagName == "BR")); +}), isFillChar: (function (node, isInStart) { + _$jscoverage['core/domUtils.js'][1905]++; + return ((node.nodeType == 3) && (! node.nodeValue.replace(new RegExp(((isInStart? "^": "") + domUtils.fillChar)), "").length)); +}), isStartInblock: (function (range) { + _$jscoverage['core/domUtils.js'][1910]++; + var tmpRange = range.cloneRange(), flag = 0, start = tmpRange.startContainer, tmp; + _$jscoverage['core/domUtils.js'][1914]++; + if (((start.nodeType == 1) && start.childNodes[tmpRange.startOffset])) { + _$jscoverage['core/domUtils.js'][1915]++; + start = start.childNodes[tmpRange.startOffset]; + _$jscoverage['core/domUtils.js'][1916]++; + var pre = start.previousSibling; + _$jscoverage['core/domUtils.js'][1917]++; + while ((pre && domUtils.isFillChar(pre))) { + _$jscoverage['core/domUtils.js'][1918]++; + start = pre; + _$jscoverage['core/domUtils.js'][1919]++; + pre = pre.previousSibling; +} + } + _$jscoverage['core/domUtils.js'][1922]++; + if ((this.isFillChar(start, true) && (tmpRange.startOffset == 1))) { + _$jscoverage['core/domUtils.js'][1923]++; + tmpRange.setStartBefore(start); + _$jscoverage['core/domUtils.js'][1924]++; + start = tmpRange.startContainer; + } + _$jscoverage['core/domUtils.js'][1927]++; + while ((start && domUtils.isFillChar(start))) { + _$jscoverage['core/domUtils.js'][1928]++; + tmp = start; + _$jscoverage['core/domUtils.js'][1929]++; + start = start.previousSibling; +} + _$jscoverage['core/domUtils.js'][1931]++; + if (tmp) { + _$jscoverage['core/domUtils.js'][1932]++; + tmpRange.setStartBefore(tmp); + _$jscoverage['core/domUtils.js'][1933]++; + start = tmpRange.startContainer; + } + _$jscoverage['core/domUtils.js'][1935]++; + if (((start.nodeType == 1) && domUtils.isEmptyNode(start) && (tmpRange.startOffset == 1))) { + _$jscoverage['core/domUtils.js'][1936]++; + tmpRange.setStart(start, 0).collapse(true); + } + _$jscoverage['core/domUtils.js'][1938]++; + while ((! tmpRange.startOffset)) { + _$jscoverage['core/domUtils.js'][1939]++; + start = tmpRange.startContainer; + _$jscoverage['core/domUtils.js'][1940]++; + if ((domUtils.isBlockElm(start) || domUtils.isBody(start))) { + _$jscoverage['core/domUtils.js'][1941]++; + flag = 1; + _$jscoverage['core/domUtils.js'][1942]++; + break; + } + _$jscoverage['core/domUtils.js'][1944]++; + var pre = tmpRange.startContainer.previousSibling, tmpNode; + _$jscoverage['core/domUtils.js'][1946]++; + if ((! pre)) { + _$jscoverage['core/domUtils.js'][1947]++; + tmpRange.setStartBefore(tmpRange.startContainer); + } + else { + _$jscoverage['core/domUtils.js'][1949]++; + while ((pre && domUtils.isFillChar(pre))) { + _$jscoverage['core/domUtils.js'][1950]++; + tmpNode = pre; + _$jscoverage['core/domUtils.js'][1951]++; + pre = pre.previousSibling; +} + _$jscoverage['core/domUtils.js'][1953]++; + if (tmpNode) { + _$jscoverage['core/domUtils.js'][1954]++; + tmpRange.setStartBefore(tmpNode); + } + else { + _$jscoverage['core/domUtils.js'][1956]++; + tmpRange.setStartBefore(tmpRange.startContainer); + } + } +} + _$jscoverage['core/domUtils.js'][1960]++; + return ((flag && (! domUtils.isBody(tmpRange.startContainer)))? 1: 0); +}), isEmptyBlock: (function (node, reg) { + _$jscoverage['core/domUtils.js'][1987]++; + if ((node.nodeType != 1)) { + _$jscoverage['core/domUtils.js'][1988]++; + return 0; + } + _$jscoverage['core/domUtils.js'][1989]++; + reg = (reg || new RegExp(("[ \t\r\n" + domUtils.fillChar + "]"), "g")); + _$jscoverage['core/domUtils.js'][1990]++; + if ((node[(browser.ie? "innerText": "textContent")].replace(reg, "").length > 0)) { + _$jscoverage['core/domUtils.js'][1991]++; + return 0; + } + _$jscoverage['core/domUtils.js'][1993]++; + for (var n in dtd.$isNotEmpty) { + _$jscoverage['core/domUtils.js'][1994]++; + if (node.getElementsByTagName(n).length) { + _$jscoverage['core/domUtils.js'][1995]++; + return 0; + } +} + _$jscoverage['core/domUtils.js'][1998]++; + return 1; +}), setViewportOffset: (function (element, offset) { + _$jscoverage['core/domUtils.js'][2028]++; + var left = (parseInt(element.style.left) | 0); + _$jscoverage['core/domUtils.js'][2029]++; + var top = (parseInt(element.style.top) | 0); + _$jscoverage['core/domUtils.js'][2030]++; + var rect = element.getBoundingClientRect(); + _$jscoverage['core/domUtils.js'][2031]++; + var offsetLeft = (offset.left - rect.left); + _$jscoverage['core/domUtils.js'][2032]++; + var offsetTop = (offset.top - rect.top); + _$jscoverage['core/domUtils.js'][2033]++; + if (offsetLeft) { + _$jscoverage['core/domUtils.js'][2034]++; + element.style.left = (left + offsetLeft + "px"); + } + _$jscoverage['core/domUtils.js'][2036]++; + if (offsetTop) { + _$jscoverage['core/domUtils.js'][2037]++; + element.style.top = (top + offsetTop + "px"); + } +}), fillNode: (function (doc, node) { + _$jscoverage['core/domUtils.js'][2065]++; + var tmpNode = (browser.ie? doc.createTextNode(domUtils.fillChar): doc.createElement("br")); + _$jscoverage['core/domUtils.js'][2066]++; + node.innerHTML = ""; + _$jscoverage['core/domUtils.js'][2067]++; + node.appendChild(tmpNode); +}), moveChild: (function (src, tag, dir) { + _$jscoverage['core/domUtils.js'][2133]++; + while (src.firstChild) { + _$jscoverage['core/domUtils.js'][2134]++; + if ((dir && tag.firstChild)) { + _$jscoverage['core/domUtils.js'][2135]++; + tag.insertBefore(src.lastChild, tag.firstChild); + } + else { + _$jscoverage['core/domUtils.js'][2137]++; + tag.appendChild(src.firstChild); + } +} +}), hasNoAttributes: (function (node) { + _$jscoverage['core/domUtils.js'][2163]++; + return (browser.ie? /^<\w+\s*?>/.test(node.outerHTML): (node.attributes.length == 0)); +}), isCustomeNode: (function (node) { + _$jscoverage['core/domUtils.js'][2174]++; + return ((node.nodeType == 1) && node.getAttribute("_ue_custom_node_")); +}), isTagNode: (function (node, tagName) { + _$jscoverage['core/domUtils.js'][2196]++; + return ((node.nodeType == 1) && new RegExp(("^" + node.tagName + "$"), "i").test(tagName)); +}), filterNodeList: (function (nodelist, filter, forAll) { + _$jscoverage['core/domUtils.js'][2266]++; + var results = []; + _$jscoverage['core/domUtils.js'][2267]++; + if ((! utils.isFunction(filter))) { + _$jscoverage['core/domUtils.js'][2268]++; + var str = filter; + _$jscoverage['core/domUtils.js'][2269]++; + filter = (function (n) { + _$jscoverage['core/domUtils.js'][2270]++; + return (utils.indexOf((utils.isArray(str)? str: str.split(" ")), n.tagName.toLowerCase()) != -1); +}); + } + _$jscoverage['core/domUtils.js'][2273]++; + utils.each(nodelist, (function (n) { + _$jscoverage['core/domUtils.js'][2274]++; + (filter(n) && results.push(n)); +})); + _$jscoverage['core/domUtils.js'][2276]++; + return ((results.length == 0)? null: (((results.length == 1) || (! forAll))? results[0]: results)); +}), isInNodeEndBoundary: (function (rng, node) { + _$jscoverage['core/domUtils.js'][2280]++; + var start = rng.startContainer; + _$jscoverage['core/domUtils.js'][2281]++; + if (((start.nodeType == 3) && (rng.startOffset != start.nodeValue.length))) { + _$jscoverage['core/domUtils.js'][2282]++; + return 0; + } + _$jscoverage['core/domUtils.js'][2284]++; + if (((start.nodeType == 1) && (rng.startOffset != start.childNodes.length))) { + _$jscoverage['core/domUtils.js'][2285]++; + return 0; + } + _$jscoverage['core/domUtils.js'][2287]++; + while ((start !== node)) { + _$jscoverage['core/domUtils.js'][2288]++; + if (start.nextSibling) { + _$jscoverage['core/domUtils.js'][2289]++; + return 0; + } + _$jscoverage['core/domUtils.js'][2290]++; + ; + _$jscoverage['core/domUtils.js'][2291]++; + start = start.parentNode; +} + _$jscoverage['core/domUtils.js'][2293]++; + return 1; +}), isBoundaryNode: (function (node, dir) { + _$jscoverage['core/domUtils.js'][2296]++; + var tmp; + _$jscoverage['core/domUtils.js'][2297]++; + while ((! domUtils.isBody(node))) { + _$jscoverage['core/domUtils.js'][2298]++; + tmp = node; + _$jscoverage['core/domUtils.js'][2299]++; + node = node.parentNode; + _$jscoverage['core/domUtils.js'][2300]++; + if ((tmp !== node[dir])) { + _$jscoverage['core/domUtils.js'][2301]++; + return false; + } +} + _$jscoverage['core/domUtils.js'][2304]++; + return true; +})}); +_$jscoverage['core/domUtils.js'][2307]++; +var fillCharReg = new RegExp(domUtils.fillChar, "g"); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/dtd.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/dtd.js new file mode 100644 index 000000000..866a73c3f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/dtd.js @@ -0,0 +1,73 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['core/dtd.js']) { + _$jscoverage['core/dtd.js'] = []; + _$jscoverage['core/dtd.js'][9] = 0; + _$jscoverage['core/dtd.js'][10] = 0; + _$jscoverage['core/dtd.js'][11] = 0; + _$jscoverage['core/dtd.js'][12] = 0; + _$jscoverage['core/dtd.js'][14] = 0; + _$jscoverage['core/dtd.js'][16] = 0; + _$jscoverage['core/dtd.js'][17] = 0; + _$jscoverage['core/dtd.js'][41] = 0; + _$jscoverage['core/dtd.js'][45] = 0; +} +_$jscoverage['core/dtd.js'].source = ["///import editor.js","///import core/dom/dom.js","///import core/utils.js","/*"," * dtd html语义化的体现类"," * @constructor"," * @namespace dtd"," */","var dtd = dom.dtd = (function() {"," function _( s ) {"," for (var k in s) {"," s[k.toUpperCase()] = s[k];"," }"," return s;"," }"," var X = utils.extend2;"," var A = _({isindex:1,fieldset:1}),"," B = _({input:1,button:1,select:1,textarea:1,label:1}),"," C = X( _({a:1}), B ),"," D = X( {iframe:1}, C ),"," E = _({hr:1,ul:1,menu:1,div:1,blockquote:1,noscript:1,table:1,center:1,address:1,dir:1,pre:1,h5:1,dl:1,h4:1,noframes:1,h6:1,ol:1,h1:1,h3:1,h2:1}),"," F = _({ins:1,del:1,script:1,style:1}),"," G = X( _({b:1,acronym:1,bdo:1,'var':1,'#':1,abbr:1,code:1,br:1,i:1,cite:1,kbd:1,u:1,strike:1,s:1,tt:1,strong:1,q:1,samp:1,em:1,dfn:1,span:1}), F ),"," H = X( _({sub:1,img:1,embed:1,object:1,sup:1,basefont:1,map:1,applet:1,font:1,big:1,small:1}), G ),"," I = X( _({p:1}), H ),"," J = X( _({iframe:1}), H, B ),"," K = _({img:1,embed:1,noscript:1,br:1,kbd:1,center:1,button:1,basefont:1,h5:1,h4:1,samp:1,h6:1,ol:1,h1:1,h3:1,h2:1,form:1,font:1,'#':1,select:1,menu:1,ins:1,abbr:1,label:1,code:1,table:1,script:1,cite:1,input:1,iframe:1,strong:1,textarea:1,noframes:1,big:1,small:1,span:1,hr:1,sub:1,bdo:1,'var':1,div:1,object:1,sup:1,strike:1,dir:1,map:1,dl:1,applet:1,del:1,isindex:1,fieldset:1,ul:1,b:1,acronym:1,a:1,blockquote:1,i:1,u:1,s:1,tt:1,address:1,q:1,pre:1,p:1,em:1,dfn:1}),",""," L = X( _({a:0}), J ),//a不能被切开,所以把他"," M = _({tr:1}),"," N = _({'#':1}),"," O = X( _({param:1}), K ),"," P = X( _({form:1}), A, D, E, I ),"," Q = _({li:1,ol:1,ul:1}),"," R = _({style:1,script:1}),"," S = _({base:1,link:1,meta:1,title:1}),"," T = X( S, R ),"," U = _({head:1,body:1}),"," V = _({html:1});",""," var block = _({address:1,blockquote:1,center:1,dir:1,div:1,dl:1,fieldset:1,form:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,hr:1,isindex:1,menu:1,noframes:1,ol:1,p:1,pre:1,table:1,ul:1}),",""," empty = _({area:1,base:1,basefont:1,br:1,col:1,command:1,dialog:1,embed:1,hr:1,img:1,input:1,isindex:1,keygen:1,link:1,meta:1,param:1,source:1,track:1,wbr:1});",""," return _({",""," // $ 表示自定的属性",""," // body外的元素列表."," $nonBodyContent: X( V, U, S ),",""," //块结构元素列表"," $block : block,",""," //内联元素列表"," $inline : L,",""," $inlineWithA : X(_({a:1}),L),",""," $body : X( _({script:1,style:1}), block ),",""," $cdata : _({script:1,style:1}),",""," //自闭和元素"," $empty : empty,",""," //不是自闭合,但不能让range选中里边"," $nonChild : _({iframe:1,textarea:1}),"," //列表元素列表"," $listItem : _({dd:1,dt:1,li:1}),",""," //列表根元素列表"," $list: _({ul:1,ol:1,dl:1}),",""," //不能认为是空的元素"," $isNotEmpty : _({table:1,ul:1,ol:1,dl:1,iframe:1,area:1,base:1,col:1,hr:1,img:1,embed:1,input:1,link:1,meta:1,param:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1}),",""," //如果没有子节点就可以删除的元素列表,像span,a"," $removeEmpty : _({a:1,abbr:1,acronym:1,address:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,s:1,samp:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,tt:1,u:1,'var':1}),",""," $removeEmptyBlock : _({'p':1,'div':1}),",""," //在table元素里的元素列表"," $tableContent : _({caption:1,col:1,colgroup:1,tbody:1,td:1,tfoot:1,th:1,thead:1,tr:1,table:1}),"," //不转换的标签"," $notTransContent : _({pre:1,script:1,style:1,textarea:1}),"," html: U,"," head: T,"," style: N,"," script: N,"," body: P,"," base: {},"," link: {},"," meta: {},"," title: N,"," col : {},"," tr : _({td:1,th:1}),"," img : {},"," embed: {},"," colgroup : _({thead:1,col:1,tbody:1,tr:1,tfoot:1}),"," noscript : P,"," td : P,"," br : {},"," th : P,"," center : P,"," kbd : L,"," button : X( I, E ),"," basefont : {},"," h5 : L,"," h4 : L,"," samp : L,"," h6 : L,"," ol : Q,"," h1 : L,"," h3 : L,"," option : N,"," h2 : L,"," form : X( A, D, E, I ),"," select : _({optgroup:1,option:1}),"," font : L,"," ins : L,"," menu : Q,"," abbr : L,"," label : L,"," table : _({thead:1,col:1,tbody:1,tr:1,colgroup:1,caption:1,tfoot:1}),"," code : L,"," tfoot : M,"," cite : L,"," li : P,"," input : {},"," iframe : P,"," strong : L,"," textarea : N,"," noframes : P,"," big : L,"," small : L,"," //trace:"," span :_({'#':1,br:1,b:1,strong:1,u:1,i:1,em:1,sub:1,sup:1,strike:1,span:1}),"," hr : L,"," dt : L,"," sub : L,"," optgroup : _({option:1}),"," param : {},"," bdo : L,"," 'var' : L,"," div : P,"," object : O,"," sup : L,"," dd : P,"," strike : L,"," area : {},"," dir : Q,"," map : X( _({area:1,form:1,p:1}), A, F, E ),"," applet : O,"," dl : _({dt:1,dd:1}),"," del : L,"," isindex : {},"," fieldset : X( _({legend:1}), K ),"," thead : M,"," ul : Q,"," acronym : L,"," b : L,"," a : X( _({a:1}), J ),"," blockquote :X(_({td:1,tr:1,tbody:1,li:1}),P),"," caption : L,"," i : L,"," u : L,"," tbody : M,"," s : L,"," address : X( D, I ),"," tt : L,"," legend : L,"," q : L,"," pre : X( G, C ),"," p : X(_({'a':1}),L),"," em :L,"," dfn : L"," });","})();"]; +_$jscoverage['core/dtd.js'][9]++; +var dtd = (dom.dtd = (function () { + _$jscoverage['core/dtd.js'][10]++; + function _(s) { + _$jscoverage['core/dtd.js'][11]++; + for (var k in s) { + _$jscoverage['core/dtd.js'][12]++; + s[k.toUpperCase()] = s[k]; +} + _$jscoverage['core/dtd.js'][14]++; + return s; +} + _$jscoverage['core/dtd.js'][16]++; + var X = utils.extend2; + _$jscoverage['core/dtd.js'][17]++; + var A = _({isindex: 1, fieldset: 1}), B = _({input: 1, button: 1, select: 1, textarea: 1, label: 1}), C = X(_({a: 1}), B), D = X({iframe: 1}, C), E = _({hr: 1, ul: 1, menu: 1, div: 1, blockquote: 1, noscript: 1, table: 1, center: 1, address: 1, dir: 1, pre: 1, h5: 1, dl: 1, h4: 1, noframes: 1, h6: 1, ol: 1, h1: 1, h3: 1, h2: 1}), F = _({ins: 1, del: 1, script: 1, style: 1}), G = X(_({b: 1, acronym: 1, bdo: 1, "var": 1, "#": 1, abbr: 1, code: 1, br: 1, i: 1, cite: 1, kbd: 1, u: 1, strike: 1, s: 1, tt: 1, strong: 1, q: 1, samp: 1, em: 1, dfn: 1, span: 1}), F), H = X(_({sub: 1, img: 1, embed: 1, object: 1, sup: 1, basefont: 1, map: 1, applet: 1, font: 1, big: 1, small: 1}), G), I = X(_({p: 1}), H), J = X(_({iframe: 1}), H, B), K = _({img: 1, embed: 1, noscript: 1, br: 1, kbd: 1, center: 1, button: 1, basefont: 1, h5: 1, h4: 1, samp: 1, h6: 1, ol: 1, h1: 1, h3: 1, h2: 1, form: 1, font: 1, "#": 1, select: 1, menu: 1, ins: 1, abbr: 1, label: 1, code: 1, table: 1, script: 1, cite: 1, input: 1, iframe: 1, strong: 1, textarea: 1, noframes: 1, big: 1, small: 1, span: 1, hr: 1, sub: 1, bdo: 1, "var": 1, div: 1, object: 1, sup: 1, strike: 1, dir: 1, map: 1, dl: 1, applet: 1, del: 1, isindex: 1, fieldset: 1, ul: 1, b: 1, acronym: 1, a: 1, blockquote: 1, i: 1, u: 1, s: 1, tt: 1, address: 1, q: 1, pre: 1, p: 1, em: 1, dfn: 1}), L = X(_({a: 0}), J), M = _({tr: 1}), N = _({"#": 1}), O = X(_({param: 1}), K), P = X(_({form: 1}), A, D, E, I), Q = _({li: 1, ol: 1, ul: 1}), R = _({style: 1, script: 1}), S = _({base: 1, link: 1, meta: 1, title: 1}), T = X(S, R), U = _({head: 1, body: 1}), V = _({html: 1}); + _$jscoverage['core/dtd.js'][41]++; + var block = _({address: 1, blockquote: 1, center: 1, dir: 1, div: 1, dl: 1, fieldset: 1, form: 1, h1: 1, h2: 1, h3: 1, h4: 1, h5: 1, h6: 1, hr: 1, isindex: 1, menu: 1, noframes: 1, ol: 1, p: 1, pre: 1, table: 1, ul: 1}), empty = _({area: 1, base: 1, basefont: 1, br: 1, col: 1, command: 1, dialog: 1, embed: 1, hr: 1, img: 1, input: 1, isindex: 1, keygen: 1, link: 1, meta: 1, param: 1, source: 1, track: 1, wbr: 1}); + _$jscoverage['core/dtd.js'][45]++; + return _({$nonBodyContent: X(V, U, S), $block: block, $inline: L, $inlineWithA: X(_({a: 1}), L), $body: X(_({script: 1, style: 1}), block), $cdata: _({script: 1, style: 1}), $empty: empty, $nonChild: _({iframe: 1, textarea: 1}), $listItem: _({dd: 1, dt: 1, li: 1}), $list: _({ul: 1, ol: 1, dl: 1}), $isNotEmpty: _({table: 1, ul: 1, ol: 1, dl: 1, iframe: 1, area: 1, base: 1, col: 1, hr: 1, img: 1, embed: 1, input: 1, link: 1, meta: 1, param: 1, h1: 1, h2: 1, h3: 1, h4: 1, h5: 1, h6: 1}), $removeEmpty: _({a: 1, abbr: 1, acronym: 1, address: 1, b: 1, bdo: 1, big: 1, cite: 1, code: 1, del: 1, dfn: 1, em: 1, font: 1, i: 1, ins: 1, label: 1, kbd: 1, q: 1, s: 1, samp: 1, small: 1, span: 1, strike: 1, strong: 1, sub: 1, sup: 1, tt: 1, u: 1, "var": 1}), $removeEmptyBlock: _({"p": 1, "div": 1}), $tableContent: _({caption: 1, col: 1, colgroup: 1, tbody: 1, td: 1, tfoot: 1, th: 1, thead: 1, tr: 1, table: 1}), $notTransContent: _({pre: 1, script: 1, style: 1, textarea: 1}), html: U, head: T, style: N, script: N, body: P, base: {}, link: {}, meta: {}, title: N, col: {}, tr: _({td: 1, th: 1}), img: {}, embed: {}, colgroup: _({thead: 1, col: 1, tbody: 1, tr: 1, tfoot: 1}), noscript: P, td: P, br: {}, th: P, center: P, kbd: L, button: X(I, E), basefont: {}, h5: L, h4: L, samp: L, h6: L, ol: Q, h1: L, h3: L, option: N, h2: L, form: X(A, D, E, I), select: _({optgroup: 1, option: 1}), font: L, ins: L, menu: Q, abbr: L, label: L, table: _({thead: 1, col: 1, tbody: 1, tr: 1, colgroup: 1, caption: 1, tfoot: 1}), code: L, tfoot: M, cite: L, li: P, input: {}, iframe: P, strong: L, textarea: N, noframes: P, big: L, small: L, span: _({"#": 1, br: 1, b: 1, strong: 1, u: 1, i: 1, em: 1, sub: 1, sup: 1, strike: 1, span: 1}), hr: L, dt: L, sub: L, optgroup: _({option: 1}), param: {}, bdo: L, "var": L, div: P, object: O, sup: L, dd: P, strike: L, area: {}, dir: Q, map: X(_({area: 1, form: 1, p: 1}), A, F, E), applet: O, dl: _({dt: 1, dd: 1}), del: L, isindex: {}, fieldset: X(_({legend: 1}), K), thead: M, ul: Q, acronym: L, b: L, a: X(_({a: 1}), J), blockquote: X(_({td: 1, tr: 1, tbody: 1, li: 1}), P), caption: L, i: L, u: L, tbody: M, s: L, address: X(D, I), tt: L, legend: L, q: L, pre: X(G, C), p: X(_({"a": 1}), L), em: L, dfn: L}); +})()); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/filternode.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/filternode.js new file mode 100644 index 000000000..5b17d9ac6 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/filternode.js @@ -0,0 +1,275 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['core/filternode.js']) { + _$jscoverage['core/filternode.js'] = []; + _$jscoverage['core/filternode.js'][24] = 0; + _$jscoverage['core/filternode.js'][25] = 0; + _$jscoverage['core/filternode.js'][26] = 0; + _$jscoverage['core/filternode.js'][28] = 0; + _$jscoverage['core/filternode.js'][30] = 0; + _$jscoverage['core/filternode.js'][31] = 0; + _$jscoverage['core/filternode.js'][32] = 0; + _$jscoverage['core/filternode.js'][33] = 0; + _$jscoverage['core/filternode.js'][34] = 0; + _$jscoverage['core/filternode.js'][35] = 0; + _$jscoverage['core/filternode.js'][37] = 0; + _$jscoverage['core/filternode.js'][38] = 0; + _$jscoverage['core/filternode.js'][39] = 0; + _$jscoverage['core/filternode.js'][40] = 0; + _$jscoverage['core/filternode.js'][41] = 0; + _$jscoverage['core/filternode.js'][42] = 0; + _$jscoverage['core/filternode.js'][43] = 0; + _$jscoverage['core/filternode.js'][48] = 0; + _$jscoverage['core/filternode.js'][49] = 0; + _$jscoverage['core/filternode.js'][50] = 0; + _$jscoverage['core/filternode.js'][51] = 0; + _$jscoverage['core/filternode.js'][58] = 0; + _$jscoverage['core/filternode.js'][59] = 0; + _$jscoverage['core/filternode.js'][60] = 0; + _$jscoverage['core/filternode.js'][61] = 0; + _$jscoverage['core/filternode.js'][62] = 0; + _$jscoverage['core/filternode.js'][64] = 0; + _$jscoverage['core/filternode.js'][65] = 0; + _$jscoverage['core/filternode.js'][66] = 0; + _$jscoverage['core/filternode.js'][67] = 0; + _$jscoverage['core/filternode.js'][68] = 0; + _$jscoverage['core/filternode.js'][69] = 0; + _$jscoverage['core/filternode.js'][72] = 0; + _$jscoverage['core/filternode.js'][74] = 0; + _$jscoverage['core/filternode.js'][75] = 0; + _$jscoverage['core/filternode.js'][79] = 0; + _$jscoverage['core/filternode.js'][81] = 0; + _$jscoverage['core/filternode.js'][82] = 0; + _$jscoverage['core/filternode.js'][83] = 0; + _$jscoverage['core/filternode.js'][84] = 0; + _$jscoverage['core/filternode.js'][85] = 0; + _$jscoverage['core/filternode.js'][92] = 0; + _$jscoverage['core/filternode.js'][93] = 0; + _$jscoverage['core/filternode.js'][95] = 0; + _$jscoverage['core/filternode.js'][97] = 0; + _$jscoverage['core/filternode.js'][98] = 0; + _$jscoverage['core/filternode.js'][99] = 0; + _$jscoverage['core/filternode.js'][100] = 0; + _$jscoverage['core/filternode.js'][101] = 0; + _$jscoverage['core/filternode.js'][106] = 0; + _$jscoverage['core/filternode.js'][108] = 0; + _$jscoverage['core/filternode.js'][112] = 0; + _$jscoverage['core/filternode.js'][113] = 0; + _$jscoverage['core/filternode.js'][114] = 0; + _$jscoverage['core/filternode.js'][116] = 0; + _$jscoverage['core/filternode.js'][117] = 0; + _$jscoverage['core/filternode.js'][118] = 0; + _$jscoverage['core/filternode.js'][119] = 0; + _$jscoverage['core/filternode.js'][122] = 0; + _$jscoverage['core/filternode.js'][123] = 0; + _$jscoverage['core/filternode.js'][124] = 0; + _$jscoverage['core/filternode.js'][125] = 0; + _$jscoverage['core/filternode.js'][128] = 0; +} +_$jscoverage['core/filternode.js'].source = ["/**"," * UE过滤节点的静态方法"," * @file"," */","","/**"," * UEditor公用空间,UEditor所有的功能都挂载在该空间下"," * @module UE"," */","","","/**"," * 根据传入节点和过滤规则过滤相应节点"," * @module UE"," * @since 1.2.6.1"," * @method filterNode"," * @param { Object } root 指定root节点"," * @param { Object } rules 过滤规则json对象"," * @example"," * ```javascript"," * UE.filterNode(root,editor.options.filterRules);"," * ```"," */","var filterNode = UE.filterNode = function () {"," function filterNode(node,rules){"," switch (node.type) {"," case 'text':"," break;"," case 'element':"," var val;"," if(val = rules[node.tagName]){"," if(val === '-'){"," node.parentNode.removeChild(node)"," }else if(utils.isFunction(val)){"," var parentNode = node.parentNode,"," index = node.getIndex();"," val(node);"," if(node.parentNode){"," if(node.children){"," for(var i = 0,ci;ci=node.children[i];){"," filterNode(ci,rules);"," if(ci.parentNode){"," i++;"," }"," }"," }"," }else{"," for(var i = index,ci;ci=parentNode.children[i];){"," filterNode(ci,rules);"," if(ci.parentNode){"," i++;"," }"," }"," }","",""," }else{"," var attrs = val['$'];"," if(attrs && node.attrs){"," var tmpAttrs = {},tmpVal;"," for(var a in attrs){"," tmpVal = node.getAttr(a);"," //todo 只先对style单独处理"," if(a == 'style' && utils.isArray(attrs[a])){"," var tmpCssStyle = [];"," utils.each(attrs[a],function(v){"," var tmp;"," if(tmp = node.getStyle(v)){"," tmpCssStyle.push(v + ':' + tmp);"," }"," });"," tmpVal = tmpCssStyle.join(';')"," }"," if(tmpVal){"," tmpAttrs[a] = tmpVal;"," }",""," }"," node.attrs = tmpAttrs;"," }"," if(node.children){"," for(var i = 0,ci;ci=node.children[i];){"," filterNode(ci,rules);"," if(ci.parentNode){"," i++;"," }"," }"," }"," }"," }else{"," //如果不在名单里扣出子节点并删除该节点,cdata除外"," if(dtd.$cdata[node.tagName]){"," node.parentNode.removeChild(node)"," }else{"," var parentNode = node.parentNode,"," index = node.getIndex();"," node.parentNode.removeChild(node,true);"," for(var i = index,ci;ci=parentNode.children[i];){"," filterNode(ci,rules);"," if(ci.parentNode){"," i++;"," }"," }"," }"," }"," break;"," case 'comment':"," node.parentNode.removeChild(node)"," }",""," }"," return function(root,rules){"," if(utils.isEmptyObject(rules)){"," return root;"," }"," var val;"," if(val = rules['-']){"," utils.each(val.split(' '),function(k){"," rules[k] = '-'"," })"," }"," for(var i= 0,ci;ci=root.children[i];){"," filterNode(ci,rules);"," if(ci.parentNode){"," i++;"," }"," }"," return root;"," }","}();"]; +_$jscoverage['core/filternode.js'][24]++; +var filterNode = (UE.filterNode = (function () { + _$jscoverage['core/filternode.js'][25]++; + function filterNode(node, rules) { + _$jscoverage['core/filternode.js'][26]++; + switch (node.type) { + case "text": + _$jscoverage['core/filternode.js'][28]++; + break; + case "element": + _$jscoverage['core/filternode.js'][30]++; + var val; + _$jscoverage['core/filternode.js'][31]++; + if ((val = rules[node.tagName])) { + _$jscoverage['core/filternode.js'][32]++; + if ((val === "-")) { + _$jscoverage['core/filternode.js'][33]++; + node.parentNode.removeChild(node); + } + else { + _$jscoverage['core/filternode.js'][34]++; + if (utils.isFunction(val)) { + _$jscoverage['core/filternode.js'][35]++; + var parentNode = node.parentNode, index = node.getIndex(); + _$jscoverage['core/filternode.js'][37]++; + val(node); + _$jscoverage['core/filternode.js'][38]++; + if (node.parentNode) { + _$jscoverage['core/filternode.js'][39]++; + if (node.children) { + _$jscoverage['core/filternode.js'][40]++; + for (var i = 0, ci; (ci = node.children[i]);) { + _$jscoverage['core/filternode.js'][41]++; + filterNode(ci, rules); + _$jscoverage['core/filternode.js'][42]++; + if (ci.parentNode) { + _$jscoverage['core/filternode.js'][43]++; + (i++); + } +} + } + } + else { + _$jscoverage['core/filternode.js'][48]++; + for (var i = index, ci = ci; (ci = parentNode.children[i]);) { + _$jscoverage['core/filternode.js'][49]++; + filterNode(ci, rules); + _$jscoverage['core/filternode.js'][50]++; + if (ci.parentNode) { + _$jscoverage['core/filternode.js'][51]++; + (i++); + } +} + } + } + else { + _$jscoverage['core/filternode.js'][58]++; + var attrs = val.$; + _$jscoverage['core/filternode.js'][59]++; + if ((attrs && node.attrs)) { + _$jscoverage['core/filternode.js'][60]++; + var tmpAttrs = {}, tmpVal; + _$jscoverage['core/filternode.js'][61]++; + for (var a in attrs) { + _$jscoverage['core/filternode.js'][62]++; + tmpVal = node.getAttr(a); + _$jscoverage['core/filternode.js'][64]++; + if (((a == "style") && utils.isArray(attrs[a]))) { + _$jscoverage['core/filternode.js'][65]++; + var tmpCssStyle = []; + _$jscoverage['core/filternode.js'][66]++; + utils.each(attrs[a], (function (v) { + _$jscoverage['core/filternode.js'][67]++; + var tmp; + _$jscoverage['core/filternode.js'][68]++; + if ((tmp = node.getStyle(v))) { + _$jscoverage['core/filternode.js'][69]++; + tmpCssStyle.push((v + ":" + tmp)); + } +})); + _$jscoverage['core/filternode.js'][72]++; + tmpVal = tmpCssStyle.join(";"); + } + _$jscoverage['core/filternode.js'][74]++; + if (tmpVal) { + _$jscoverage['core/filternode.js'][75]++; + tmpAttrs[a] = tmpVal; + } +} + _$jscoverage['core/filternode.js'][79]++; + node.attrs = tmpAttrs; + } + _$jscoverage['core/filternode.js'][81]++; + if (node.children) { + _$jscoverage['core/filternode.js'][82]++; + for (var i = 0, ci = ci; (ci = node.children[i]);) { + _$jscoverage['core/filternode.js'][83]++; + filterNode(ci, rules); + _$jscoverage['core/filternode.js'][84]++; + if (ci.parentNode) { + _$jscoverage['core/filternode.js'][85]++; + (i++); + } +} + } + } + } + } + else { + _$jscoverage['core/filternode.js'][92]++; + if (dtd.$cdata[node.tagName]) { + _$jscoverage['core/filternode.js'][93]++; + node.parentNode.removeChild(node); + } + else { + _$jscoverage['core/filternode.js'][95]++; + var parentNode = node.parentNode, index = node.getIndex(); + _$jscoverage['core/filternode.js'][97]++; + node.parentNode.removeChild(node, true); + _$jscoverage['core/filternode.js'][98]++; + for (var i = index, ci = ci; (ci = parentNode.children[i]);) { + _$jscoverage['core/filternode.js'][99]++; + filterNode(ci, rules); + _$jscoverage['core/filternode.js'][100]++; + if (ci.parentNode) { + _$jscoverage['core/filternode.js'][101]++; + (i++); + } +} + } + } + _$jscoverage['core/filternode.js'][106]++; + break; + case "comment": + _$jscoverage['core/filternode.js'][108]++; + node.parentNode.removeChild(node); + } +} + _$jscoverage['core/filternode.js'][112]++; + return (function (root, rules) { + _$jscoverage['core/filternode.js'][113]++; + if (utils.isEmptyObject(rules)) { + _$jscoverage['core/filternode.js'][114]++; + return root; + } + _$jscoverage['core/filternode.js'][116]++; + var val; + _$jscoverage['core/filternode.js'][117]++; + if ((val = rules["-"])) { + _$jscoverage['core/filternode.js'][118]++; + utils.each(val.split(" "), (function (k) { + _$jscoverage['core/filternode.js'][119]++; + rules[k] = "-"; +})); + } + _$jscoverage['core/filternode.js'][122]++; + for (var i = 0, ci; (ci = root.children[i]);) { + _$jscoverage['core/filternode.js'][123]++; + filterNode(ci, rules); + _$jscoverage['core/filternode.js'][124]++; + if (ci.parentNode) { + _$jscoverage['core/filternode.js'][125]++; + (i++); + } +} + _$jscoverage['core/filternode.js'][128]++; + return root; +}); +})()); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/filterword.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/filterword.js new file mode 100644 index 000000000..44e9086c6 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/filterword.js @@ -0,0 +1,266 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['core/filterword.js']) { + _$jscoverage['core/filterword.js'] = []; + _$jscoverage['core/filterword.js'][23] = 0; + _$jscoverage['core/filterword.js'][26] = 0; + _$jscoverage['core/filterword.js'][27] = 0; + _$jscoverage['core/filterword.js'][30] = 0; + _$jscoverage['core/filterword.js'][31] = 0; + _$jscoverage['core/filterword.js'][32] = 0; + _$jscoverage['core/filterword.js'][34] = 0; + _$jscoverage['core/filterword.js'][37] = 0; + _$jscoverage['core/filterword.js'][38] = 0; + _$jscoverage['core/filterword.js'][43] = 0; + _$jscoverage['core/filterword.js'][44] = 0; + _$jscoverage['core/filterword.js'][46] = 0; + _$jscoverage['core/filterword.js'][47] = 0; + _$jscoverage['core/filterword.js'][50] = 0; + _$jscoverage['core/filterword.js'][52] = 0; + _$jscoverage['core/filterword.js'][64] = 0; + _$jscoverage['core/filterword.js'][70] = 0; + _$jscoverage['core/filterword.js'][76] = 0; + _$jscoverage['core/filterword.js'][78] = 0; + _$jscoverage['core/filterword.js'][81] = 0; + _$jscoverage['core/filterword.js'][82] = 0; + _$jscoverage['core/filterword.js'][83] = 0; + _$jscoverage['core/filterword.js'][84] = 0; + _$jscoverage['core/filterword.js'][88] = 0; + _$jscoverage['core/filterword.js'][91] = 0; + _$jscoverage['core/filterword.js'][108] = 0; + _$jscoverage['core/filterword.js'][109] = 0; + _$jscoverage['core/filterword.js'][110] = 0; + _$jscoverage['core/filterword.js'][112] = 0; + _$jscoverage['core/filterword.js'][113] = 0; + _$jscoverage['core/filterword.js'][116] = 0; + _$jscoverage['core/filterword.js'][117] = 0; + _$jscoverage['core/filterword.js'][121] = 0; + _$jscoverage['core/filterword.js'][122] = 0; + _$jscoverage['core/filterword.js'][126] = 0; + _$jscoverage['core/filterword.js'][127] = 0; + _$jscoverage['core/filterword.js'][130] = 0; + _$jscoverage['core/filterword.js'][131] = 0; + _$jscoverage['core/filterword.js'][134] = 0; + _$jscoverage['core/filterword.js'][135] = 0; + _$jscoverage['core/filterword.js'][138] = 0; + _$jscoverage['core/filterword.js'][139] = 0; + _$jscoverage['core/filterword.js'][142] = 0; + _$jscoverage['core/filterword.js'][143] = 0; + _$jscoverage['core/filterword.js'][145] = 0; + _$jscoverage['core/filterword.js'][147] = 0; + _$jscoverage['core/filterword.js'][148] = 0; + _$jscoverage['core/filterword.js'][150] = 0; + _$jscoverage['core/filterword.js'][152] = 0; + _$jscoverage['core/filterword.js'][154] = 0; + _$jscoverage['core/filterword.js'][155] = 0; + _$jscoverage['core/filterword.js'][160] = 0; + _$jscoverage['core/filterword.js'][164] = 0; + _$jscoverage['core/filterword.js'][167] = 0; + _$jscoverage['core/filterword.js'][170] = 0; + _$jscoverage['core/filterword.js'][173] = 0; + _$jscoverage['core/filterword.js'][178] = 0; + _$jscoverage['core/filterword.js'][179] = 0; +} +_$jscoverage['core/filterword.js'].source = ["/**"," * UE过滤word的静态方法"," * @file"," */","","/**"," * UEditor公用空间,UEditor所有的功能都挂载在该空间下"," * @module UE"," */","","","/**"," * 根据传入html字符串过滤word"," * @module UE"," * @since 1.2.6.1"," * @method filterWord"," * @param { String } html html字符串"," * @example"," * ```javascript"," * UE.filterWord(html);"," * ```"," */","var filterWord = UE.filterWord = function () {",""," //是否是word过来的内容"," function isWordDocument( str ) {"," return /(class=\"?Mso|style=\"[^\"]*\\bmso\\-|w:WordDocument|<v:)/ig.test( str );"," }"," //去掉小数"," function transUnit( v ) {"," v = v.replace( /[\\d.]+\\w+/g, function ( m ) {"," return utils.transUnitToPx(m);"," } );"," return v;"," }",""," function filterPasteWord( str ) {"," return str.replace( /[\\t\\r\\n]+/g, \"\" )"," .replace( /<!--[\\s\\S]*?-->/ig, \"\" )"," //转换图片"," .replace(/<v:shape [^>]*>[\\s\\S]*?.<\\/v:shape>/gi,function(str){"," //opera能自己解析出image所这里直接返回空"," if(browser.opera){"," return '';"," }"," try{"," var width = str.match(/width:([ \\d.]*p[tx])/i)[1],"," height = str.match(/height:([ \\d.]*p[tx])/i)[1],"," src = str.match(/src=\\s*\"([^\"]*)\"/i)[1];"," return '<img width=\"'+ transUnit(width) +'\" height=\"'+transUnit(height) +'\" src=\"' + src + '\" />';"," } catch(e){"," return '';"," }"," })"," //针对wps添加的多余标签处理"," .replace(/<\\/?div[^>]*>/g,'')"," //去掉多余的属性"," .replace( /v:\\w+=([\"']?)[^'\"]+\\1/g, '' )"," .replace( /<(!|script[^>]*>.*?<\\/script(?=[>\\s])|\\/?(\\?xml(:\\w+)?|xml|meta|link|style|\\w+:\\w+)(?=[\\s\\/>]))[^>]*>/gi, \"\" )"," .replace( /<p [^>]*class=\"?MsoHeading\"?[^>]*>(.*?)<\\/p>/gi, \"<p><strong>$1</strong></p>\" )"," //去掉多余的属性"," .replace( /\\s+(class|lang|align)\\s*=\\s*(['\"]?)([\\w-]+)\\2/ig, function(str,name,marks,val){"," //保留list的标示"," return name == 'class' && val == 'MsoListParagraph' ? str : ''"," })"," //清除多余的font/span不能匹配&nbsp;有可能是空格"," .replace( /<(font|span)[^>]*>\\s*<\\/\\1>/gi, '' )"," //处理style的问题"," .replace( /(<[a-z][^>]*)\\sstyle=([\"'])([^\\2]*?)\\2/gi, function( str, tag, tmp, style ) {"," var n = [],"," s = style.replace( /^\\s+|\\s+$/, '' )"," .replace(/&#39;/g,'\\'')"," .replace( /&quot;/gi, \"'\" )"," .split( /;\\s*/g );",""," for ( var i = 0,v; v = s[i];i++ ) {",""," var name, value,"," parts = v.split( \":\" );",""," if ( parts.length == 2 ) {"," name = parts[0].toLowerCase();"," value = parts[1].toLowerCase();"," if(/^(background)\\w*/.test(name) && value.replace(/(initial|\\s)/g,'').length == 0"," ||"," /^(margin)\\w*/.test(name) && /^0\\w+$/.test(value)"," ){"," continue;"," }",""," switch ( name ) {"," case \"mso-padding-alt\":"," case \"mso-padding-top-alt\":"," case \"mso-padding-right-alt\":"," case \"mso-padding-bottom-alt\":"," case \"mso-padding-left-alt\":"," case \"mso-margin-alt\":"," case \"mso-margin-top-alt\":"," case \"mso-margin-right-alt\":"," case \"mso-margin-bottom-alt\":"," case \"mso-margin-left-alt\":"," //ie下会出现挤到一起的情况"," //case \"mso-table-layout-alt\":"," case \"mso-height\":"," case \"mso-width\":"," case \"mso-vertical-align-alt\":"," //trace:1819 ff下会解析出padding在table上"," if(!/<table/.test(tag))"," n[i] = name.replace( /^mso-|-alt$/g, \"\" ) + \":\" + transUnit( value );"," continue;"," case \"horiz-align\":"," n[i] = \"text-align:\" + value;"," continue;",""," case \"vert-align\":"," n[i] = \"vertical-align:\" + value;"," continue;",""," case \"font-color\":"," case \"mso-foreground\":"," n[i] = \"color:\" + value;"," continue;",""," case \"mso-background\":"," case \"mso-highlight\":"," n[i] = \"background:\" + value;"," continue;",""," case \"mso-default-height\":"," n[i] = \"min-height:\" + transUnit( value );"," continue;",""," case \"mso-default-width\":"," n[i] = \"min-width:\" + transUnit( value );"," continue;",""," case \"mso-padding-between-alt\":"," n[i] = \"border-collapse:separate;border-spacing:\" + transUnit( value );"," continue;",""," case \"text-line-through\":"," if ( (value == \"single\") || (value == \"double\") ) {"," n[i] = \"text-decoration:line-through\";"," }"," continue;"," case \"mso-zero-height\":"," if ( value == \"yes\" ) {"," n[i] = \"display:none\";"," }"," continue;"," case 'background':"," break;"," case 'margin':"," if ( !/[1-9]/.test( value ) ) {"," continue;"," }",""," }",""," if ( /^(mso|column|font-emph|lang|layout|line-break|list-image|nav|panose|punct|row|ruby|sep|size|src|tab-|table-border|text-(?:decor|trans)|top-bar|version|vnd|word-break)/.test( name )"," ||"," /text\\-indent|padding|margin/.test(name) && /\\-[\\d.]+/.test(value)"," ) {"," continue;"," }",""," n[i] = name + \":\" + parts[1];"," }"," }"," return tag + (n.length ? ' style=\"' + n.join( ';').replace(/;{2,}/g,';') + '\"' : '');"," })"," .replace(/[\\d.]+(cm|pt)/g,function(str){"," return utils.transUnitToPx(str)"," })",""," }",""," return function ( html ) {"," return (isWordDocument( html ) ? filterPasteWord( html ) : html);"," };","}();"]; +_$jscoverage['core/filterword.js'][23]++; +var filterWord = (UE.filterWord = (function () { + _$jscoverage['core/filterword.js'][26]++; + function isWordDocument(str) { + _$jscoverage['core/filterword.js'][27]++; + return /(class="?Mso|style="[^"]*\bmso\-|w:WordDocument|/gi, "").replace(/]*>[\s\S]*?.<\/v:shape>/gi, (function (str) { + _$jscoverage['core/filterword.js'][43]++; + if (browser.opera) { + _$jscoverage['core/filterword.js'][44]++; + return ""; + } + _$jscoverage['core/filterword.js'][46]++; + try { + _$jscoverage['core/filterword.js'][47]++; + var width = str.match(/width:([ \d.]*p[tx])/i)[1], height = str.match(/height:([ \d.]*p[tx])/i)[1], src = str.match(/src=\s*"([^"]*)"/i)[1]; + _$jscoverage['core/filterword.js'][50]++; + return (""); + } + catch (e) { + _$jscoverage['core/filterword.js'][52]++; + return ""; + } +})).replace(/<\/?div[^>]*>/g, "").replace(/v:\w+=(["']?)[^'"]+\1/g, "").replace(/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|xml|meta|link|style|\w+:\w+)(?=[\s\/>]))[^>]*>/gi, "").replace(/

    ]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi, "

    $1

    ").replace(/\s+(class|lang|align)\s*=\s*(['"]?)([\w-]+)\2/gi, (function (str, name, marks, val) { + _$jscoverage['core/filterword.js'][64]++; + return (((name == "class") && (val == "MsoListParagraph"))? str: ""); +})).replace(/<(font|span)[^>]*>\s*<\/\1>/gi, "").replace(/(<[a-z][^>]*)\sstyle=(["'])([^\2]*?)\2/gi, (function (str, tag, tmp, style) { + _$jscoverage['core/filterword.js'][70]++; + var n = [], s = style.replace(/^\s+|\s+$/, "").replace(/'/g, "'").replace(/"/gi, "'").split(/;\s*/g); + _$jscoverage['core/filterword.js'][76]++; + for (var i = 0, v; (v = s[i]); (i++)) { + _$jscoverage['core/filterword.js'][78]++; + var name, value, parts = v.split(":"); + _$jscoverage['core/filterword.js'][81]++; + if ((parts.length == 2)) { + _$jscoverage['core/filterword.js'][82]++; + name = parts[0].toLowerCase(); + _$jscoverage['core/filterword.js'][83]++; + value = parts[1].toLowerCase(); + _$jscoverage['core/filterword.js'][84]++; + if (((/^(background)\w*/.test(name) && (value.replace(/(initial|\s)/g, "").length == 0)) || (/^(margin)\w*/.test(name) && /^0\w+$/.test(value)))) { + _$jscoverage['core/filterword.js'][88]++; + continue; + } + _$jscoverage['core/filterword.js'][91]++; + switch (name) { + case "mso-padding-alt": + case "mso-padding-top-alt": + case "mso-padding-right-alt": + case "mso-padding-bottom-alt": + case "mso-padding-left-alt": + case "mso-margin-alt": + case "mso-margin-top-alt": + case "mso-margin-right-alt": + case "mso-margin-bottom-alt": + case "mso-margin-left-alt": + case "mso-height": + case "mso-width": + case "mso-vertical-align-alt": + _$jscoverage['core/filterword.js'][108]++; + if ((! //**"," * html字符串转换成uNode节点"," * @file"," * @module UE"," * @since 1.2.6.1"," */","","/**"," * UEditor公用空间,UEditor所有的功能都挂载在该空间下"," * @unfile"," * @module UE"," */","","/**"," * html字符串转换成uNode节点的静态方法"," * @method htmlparser"," * @param { String } htmlstr 要转换的html代码"," * @param { Boolean } ignoreBlank 若设置为true,转换的时候忽略\\n\\r\\t等空白字符"," * @example"," * ```javascript"," * var root = UE.htmlparser('<p><b>htmlparser</b></p>', true);"," * ```"," */","","var htmlparser = UE.htmlparser =function(htmlstr,ignoreBlank){"," var re_tag =/<(?:(?:\\/([^>]+)>)|(?:!--([\\S|\\s]*?)-->)|(?:([^\\s\\/>]+)\\s*((?:(?:\"[^\"]*\")|(?:'[^']*')|[^\"'<>])*)\\/?>))/g,"," re_attr =/([\\w\\-:.]+)(?:(?:\\s*=\\s*(?:(?:\"([^\"]*)\")|(?:'([^']*)')|([^\\s>]+)))|(?=\\s|$))/g;",""," //ie下取得的html可能会有\\n存在,要去掉,在处理replace(/[\\t\\r\\n]*/g,'');代码高量的\\n不能去除"," var allowEmptyTags ={"," b:1,code:1,i:1,u:1,strike:1,s:1,tt:1,strong:1,q:1,samp:1,em:1,span:1,"," sub:1,img:1,sup:1,font:1,big:1,small:1,iframe:1,a:1,br:1,pre:1"," };"," htmlstr = htmlstr.replace(new RegExp(domUtils.fillChar,'g'),'');"," if(!ignoreBlank){"," htmlstr = htmlstr.replace(new RegExp('[\\\\r\\\\t\\\\n'+(ignoreBlank?'':' ')+']*<\\/?(\\\\w+)\\\\s*(?:[^>]*)>[\\\\r\\\\t\\\\n'+(ignoreBlank?'':' ')+']*','g'),function(a,b){"," //br暂时单独处理"," if(b && allowEmptyTags[b.toLowerCase()]){"," return a.replace(/(^[\\n\\r]+)|([\\n\\r]+$)/g,'');"," }"," return a.replace(new RegExp('^[\\\\r\\\\n'+(ignoreBlank?'':' ')+']+'),'').replace(new RegExp('[\\\\r\\\\n'+(ignoreBlank?'':' ')+']+$'),'');"," });"," }","",""," var uNode = UE.uNode,"," needParentNode ={"," 'td':'tr',"," 'tr':['tbody','thead','tfoot'],"," 'tbody':'table',"," 'th':'tr',"," 'thead':'table',"," 'tfoot':'table',"," 'caption':'table',"," 'li':['ul','ol'],"," 'dt':'dl',"," 'dd':'dl',"," 'option':'select'"," },"," needChild ={"," 'ol':'li',"," 'ul':'li'"," };",""," function text(parent, data){",""," if(needChild[parent.tagName]){"," var tmpNode = uNode.createElement(needChild[parent.tagName]);"," parent.appendChild(tmpNode);"," tmpNode.appendChild(uNode.createText(data));"," parent = tmpNode;"," }else{",""," parent.appendChild(uNode.createText(data));"," }"," }",""," function element(parent, tagName, htmlattr){"," var needParentTag;"," if(needParentTag = needParentNode[tagName]){"," var tmpParent = parent,hasParent;"," while(tmpParent.type !='root'){"," if(utils.isArray(needParentTag)? utils.indexOf(needParentTag, tmpParent.tagName)!=-1: needParentTag == tmpParent.tagName){"," parent = tmpParent;"," hasParent =true;"," break;"," }"," tmpParent = tmpParent.parentNode;"," }"," if(!hasParent){"," parent = element(parent, utils.isArray(needParentTag)? needParentTag[0]: needParentTag)"," }"," }"," //按dtd处理嵌套","// if(parent.type != 'root' && !dtd[parent.tagName][tagName])","// parent = parent.parentNode;"," var elm =new uNode({"," parentNode:parent,"," type:'element',"," tagName:tagName.toLowerCase(),"," //是自闭合的处理一下"," children:dtd.$empty[tagName]?null:[]"," });"," //如果属性存在,处理属性"," if(htmlattr){"," var attrs ={}, match;"," while(match = re_attr.exec(htmlattr)){"," attrs[match[1].toLowerCase()]= utils.unhtml(match[2]|| match[3]|| match[4])"," }"," elm.attrs = attrs;"," }",""," parent.children.push(elm);"," //如果是自闭合节点返回父亲节点"," return dtd.$empty[tagName]? parent : elm"," }",""," function comment(parent, data){"," parent.children.push(new uNode({"," type:'comment',"," data:data,"," parentNode:parent"," }));"," }",""," var match, currentIndex =0, nextIndex =0;"," //设置根节点"," var root =new uNode({"," type:'root',"," children:[]"," });"," var currentParent = root;"," while(match = re_tag.exec(htmlstr)){"," currentIndex = match.index;"," try{"," if(currentIndex > nextIndex){"," //text node"," text(currentParent, htmlstr.slice(nextIndex, currentIndex));"," }"," if(match[3]){"," //start tag"," currentParent = element(currentParent, match[3].toLowerCase(), match[4]);",""," }elseif(match[1]){"," if(currentParent.type !='root'){"," var tmpParent = currentParent;"," while(currentParent.type =='element'&& currentParent.tagName != match[1].toLowerCase()){"," currentParent = currentParent.parentNode;"," if(currentParent.type =='root'){"," currentParent = tmpParent;"," throw'break'"," }"," }"," //end tag"," currentParent = currentParent.parentNode;"," }",""," }elseif(match[2]){"," //comment"," comment(currentParent, match[2])"," }"," }catch(e){}",""," nextIndex = re_tag.lastIndex;",""," }"," //如果结束是文本,就有可能丢掉,所以这里手动判断一下"," //例如 <li>sdfsdfsdf<li>sdfsdfsdfsdf"," if(nextIndex < htmlstr.length){"," text(currentParent, htmlstr.slice(nextIndex));"," }"," return root;","};"]; +_$jscoverage['core/htmlparser.js'][25]++; +var htmlparser = (UE.htmlparser = (function (htmlstr, ignoreBlank) { + _$jscoverage['core/htmlparser.js'][26]++; + var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\s\/>]+)\s*((?:(?:"[^"]*")|(?:'[^']*')|[^"'<>])*)\/?>))/g, re_attr = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g; + _$jscoverage['core/htmlparser.js'][30]++; + var allowEmptyTags = {b: 1, code: 1, i: 1, u: 1, strike: 1, s: 1, tt: 1, strong: 1, q: 1, samp: 1, em: 1, span: 1, sub: 1, img: 1, sup: 1, font: 1, big: 1, small: 1, iframe: 1, a: 1, br: 1, pre: 1}; + _$jscoverage['core/htmlparser.js'][34]++; + htmlstr = htmlstr.replace(new RegExp(domUtils.fillChar, "g"), ""); + _$jscoverage['core/htmlparser.js'][35]++; + if ((! ignoreBlank)) { + _$jscoverage['core/htmlparser.js'][36]++; + htmlstr = htmlstr.replace(new RegExp(("[\\r\\t\\n" + (ignoreBlank? "": " ") + "]*]*)>[\\r\\t\\n" + (ignoreBlank? "": " ") + "]*"), "g"), (function (a, b) { + _$jscoverage['core/htmlparser.js'][38]++; + if ((b && allowEmptyTags[b.toLowerCase()])) { + _$jscoverage['core/htmlparser.js'][39]++; + return a.replace(/(^[\n\r]+)|([\n\r]+$)/g, ""); + } + _$jscoverage['core/htmlparser.js'][41]++; + return a.replace(new RegExp(("^[\\r\\n" + (ignoreBlank? "": " ") + "]+")), "").replace(new RegExp(("[\\r\\n" + (ignoreBlank? "": " ") + "]+$")), ""); +})); + } + _$jscoverage['core/htmlparser.js'][46]++; + var uNode = UE.uNode, needParentNode = {"td": "tr", "tr": ["tbody", "thead", "tfoot"], "tbody": "table", "th": "tr", "thead": "table", "tfoot": "table", "caption": "table", "li": ["ul", "ol"], "dt": "dl", "dd": "dl", "option": "select"}, needChild = {"ol": "li", "ul": "li"}; + _$jscoverage['core/htmlparser.js'][65]++; + function text(parent, data) { + _$jscoverage['core/htmlparser.js'][67]++; + if (needChild[parent.tagName]) { + _$jscoverage['core/htmlparser.js'][68]++; + var tmpNode = uNode.createElement(needChild[parent.tagName]); + _$jscoverage['core/htmlparser.js'][69]++; + parent.appendChild(tmpNode); + _$jscoverage['core/htmlparser.js'][70]++; + tmpNode.appendChild(uNode.createText(data)); + _$jscoverage['core/htmlparser.js'][71]++; + parent = tmpNode; + } + else { + _$jscoverage['core/htmlparser.js'][74]++; + parent.appendChild(uNode.createText(data)); + } +} + _$jscoverage['core/htmlparser.js'][78]++; + function element(parent, tagName, htmlattr) { + _$jscoverage['core/htmlparser.js'][79]++; + var needParentTag; + _$jscoverage['core/htmlparser.js'][80]++; + if ((needParentTag = needParentNode[tagName])) { + _$jscoverage['core/htmlparser.js'][81]++; + var tmpParent = parent, hasParent; + _$jscoverage['core/htmlparser.js'][82]++; + while ((tmpParent.type != "root")) { + _$jscoverage['core/htmlparser.js'][83]++; + if ((utils.isArray(needParentTag)? (utils.indexOf(needParentTag, tmpParent.tagName) != -1): (needParentTag == tmpParent.tagName))) { + _$jscoverage['core/htmlparser.js'][84]++; + parent = tmpParent; + _$jscoverage['core/htmlparser.js'][85]++; + hasParent = true; + _$jscoverage['core/htmlparser.js'][86]++; + break; + } + _$jscoverage['core/htmlparser.js'][88]++; + tmpParent = tmpParent.parentNode; +} + _$jscoverage['core/htmlparser.js'][90]++; + if ((! hasParent)) { + _$jscoverage['core/htmlparser.js'][91]++; + parent = element(parent, (utils.isArray(needParentTag)? needParentTag[0]: needParentTag)); + } + } + _$jscoverage['core/htmlparser.js'][97]++; + var elm = new uNode({parentNode: parent, type: "element", tagName: tagName.toLowerCase(), children: (dtd.$empty[tagName]? null: [])}); + _$jscoverage['core/htmlparser.js'][105]++; + if (htmlattr) { + _$jscoverage['core/htmlparser.js'][106]++; + var attrs = {}, match; + _$jscoverage['core/htmlparser.js'][107]++; + while ((match = re_attr.exec(htmlattr))) { + _$jscoverage['core/htmlparser.js'][108]++; + attrs[match[1].toLowerCase()] = utils.unhtml((match[2] || match[3] || match[4])); +} + _$jscoverage['core/htmlparser.js'][110]++; + elm.attrs = attrs; + } + _$jscoverage['core/htmlparser.js'][113]++; + parent.children.push(elm); + _$jscoverage['core/htmlparser.js'][115]++; + return (dtd.$empty[tagName]? parent: elm); +} + _$jscoverage['core/htmlparser.js'][118]++; + function comment(parent, data) { + _$jscoverage['core/htmlparser.js'][119]++; + parent.children.push(new uNode({type: "comment", data: data, parentNode: parent})); +} + _$jscoverage['core/htmlparser.js'][126]++; + var match, currentIndex = 0, nextIndex = 0; + _$jscoverage['core/htmlparser.js'][128]++; + var root = new uNode({type: "root", children: []}); + _$jscoverage['core/htmlparser.js'][132]++; + var currentParent = root; + _$jscoverage['core/htmlparser.js'][133]++; + while ((match = re_tag.exec(htmlstr))) { + _$jscoverage['core/htmlparser.js'][134]++; + currentIndex = match.index; + _$jscoverage['core/htmlparser.js'][135]++; + try { + _$jscoverage['core/htmlparser.js'][136]++; + if ((currentIndex > nextIndex)) { + _$jscoverage['core/htmlparser.js'][138]++; + text(currentParent, htmlstr.slice(nextIndex, currentIndex)); + } + _$jscoverage['core/htmlparser.js'][140]++; + if (match[3]) { + _$jscoverage['core/htmlparser.js'][142]++; + currentParent = element(currentParent, match[3].toLowerCase(), match[4]); + } + else { + _$jscoverage['core/htmlparser.js'][144]++; + if (match[1]) { + _$jscoverage['core/htmlparser.js'][145]++; + if ((currentParent.type != "root")) { + _$jscoverage['core/htmlparser.js'][146]++; + var tmpParent = currentParent; + _$jscoverage['core/htmlparser.js'][147]++; + while (((currentParent.type == "element") && (currentParent.tagName != match[1].toLowerCase()))) { + _$jscoverage['core/htmlparser.js'][148]++; + currentParent = currentParent.parentNode; + _$jscoverage['core/htmlparser.js'][149]++; + if ((currentParent.type == "root")) { + _$jscoverage['core/htmlparser.js'][150]++; + currentParent = tmpParent; + _$jscoverage['core/htmlparser.js'][151]++; + throw "break"; + } +} + _$jscoverage['core/htmlparser.js'][155]++; + currentParent = currentParent.parentNode; + } + } + else { + _$jscoverage['core/htmlparser.js'][158]++; + if (match[2]) { + _$jscoverage['core/htmlparser.js'][160]++; + comment(currentParent, match[2]); + } + } + } + } + catch (e) { + } + _$jscoverage['core/htmlparser.js'][164]++; + nextIndex = re_tag.lastIndex; +} + _$jscoverage['core/htmlparser.js'][169]++; + if ((nextIndex < htmlstr.length)) { + _$jscoverage['core/htmlparser.js'][170]++; + text(currentParent, htmlstr.slice(nextIndex)); + } + _$jscoverage['core/htmlparser.js'][172]++; + return root; +})); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/node.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/node.js new file mode 100644 index 000000000..3c76035f0 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/node.js @@ -0,0 +1,874 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['core/node.js']) { + _$jscoverage['core/node.js'] = []; + _$jscoverage['core/node.js'][15] = 0; + _$jscoverage['core/node.js'][37] = 0; + _$jscoverage['core/node.js'][38] = 0; + _$jscoverage['core/node.js'][39] = 0; + _$jscoverage['core/node.js'][40] = 0; + _$jscoverage['core/node.js'][41] = 0; + _$jscoverage['core/node.js'][42] = 0; + _$jscoverage['core/node.js'][43] = 0; + _$jscoverage['core/node.js'][45] = 0; + _$jscoverage['core/node.js'][48] = 0; + _$jscoverage['core/node.js'][49] = 0; + _$jscoverage['core/node.js'][50] = 0; + _$jscoverage['core/node.js'][53] = 0; + _$jscoverage['core/node.js'][55] = 0; + _$jscoverage['core/node.js'][56] = 0; + _$jscoverage['core/node.js'][62] = 0; + _$jscoverage['core/node.js'][63] = 0; + _$jscoverage['core/node.js'][64] = 0; + _$jscoverage['core/node.js'][66] = 0; + _$jscoverage['core/node.js'][73] = 0; + _$jscoverage['core/node.js'][74] = 0; + _$jscoverage['core/node.js'][79] = 0; + _$jscoverage['core/node.js'][80] = 0; + _$jscoverage['core/node.js'][82] = 0; + _$jscoverage['core/node.js'][84] = 0; + _$jscoverage['core/node.js'][85] = 0; + _$jscoverage['core/node.js'][86] = 0; + _$jscoverage['core/node.js'][88] = 0; + _$jscoverage['core/node.js'][90] = 0; + _$jscoverage['core/node.js'][92] = 0; + _$jscoverage['core/node.js'][93] = 0; + _$jscoverage['core/node.js'][95] = 0; + _$jscoverage['core/node.js'][96] = 0; + _$jscoverage['core/node.js'][98] = 0; + _$jscoverage['core/node.js'][100] = 0; + _$jscoverage['core/node.js'][103] = 0; + _$jscoverage['core/node.js'][104] = 0; + _$jscoverage['core/node.js'][107] = 0; + _$jscoverage['core/node.js'][108] = 0; + _$jscoverage['core/node.js'][109] = 0; + _$jscoverage['core/node.js'][110] = 0; + _$jscoverage['core/node.js'][111] = 0; + _$jscoverage['core/node.js'][112] = 0; + _$jscoverage['core/node.js'][113] = 0; + _$jscoverage['core/node.js'][115] = 0; + _$jscoverage['core/node.js'][117] = 0; + _$jscoverage['core/node.js'][122] = 0; + _$jscoverage['core/node.js'][123] = 0; + _$jscoverage['core/node.js'][124] = 0; + _$jscoverage['core/node.js'][125] = 0; + _$jscoverage['core/node.js'][129] = 0; + _$jscoverage['core/node.js'][130] = 0; + _$jscoverage['core/node.js'][131] = 0; + _$jscoverage['core/node.js'][132] = 0; + _$jscoverage['core/node.js'][133] = 0; + _$jscoverage['core/node.js'][135] = 0; + _$jscoverage['core/node.js'][138] = 0; + _$jscoverage['core/node.js'][139] = 0; + _$jscoverage['core/node.js'][141] = 0; + _$jscoverage['core/node.js'][142] = 0; + _$jscoverage['core/node.js'][143] = 0; + _$jscoverage['core/node.js'][146] = 0; + _$jscoverage['core/node.js'][151] = 0; + _$jscoverage['core/node.js'][152] = 0; + _$jscoverage['core/node.js'][155] = 0; + _$jscoverage['core/node.js'][156] = 0; + _$jscoverage['core/node.js'][157] = 0; + _$jscoverage['core/node.js'][158] = 0; + _$jscoverage['core/node.js'][160] = 0; + _$jscoverage['core/node.js'][161] = 0; + _$jscoverage['core/node.js'][162] = 0; + _$jscoverage['core/node.js'][163] = 0; + _$jscoverage['core/node.js'][169] = 0; + _$jscoverage['core/node.js'][170] = 0; + _$jscoverage['core/node.js'][171] = 0; + _$jscoverage['core/node.js'][173] = 0; + _$jscoverage['core/node.js'][174] = 0; + _$jscoverage['core/node.js'][175] = 0; + _$jscoverage['core/node.js'][180] = 0; + _$jscoverage['core/node.js'][181] = 0; + _$jscoverage['core/node.js'][182] = 0; + _$jscoverage['core/node.js'][183] = 0; + _$jscoverage['core/node.js'][185] = 0; + _$jscoverage['core/node.js'][186] = 0; + _$jscoverage['core/node.js'][187] = 0; + _$jscoverage['core/node.js'][189] = 0; + _$jscoverage['core/node.js'][193] = 0; + _$jscoverage['core/node.js'][198] = 0; + _$jscoverage['core/node.js'][221] = 0; + _$jscoverage['core/node.js'][222] = 0; + _$jscoverage['core/node.js'][223] = 0; + _$jscoverage['core/node.js'][249] = 0; + _$jscoverage['core/node.js'][250] = 0; + _$jscoverage['core/node.js'][252] = 0; + _$jscoverage['core/node.js'][253] = 0; + _$jscoverage['core/node.js'][254] = 0; + _$jscoverage['core/node.js'][255] = 0; + _$jscoverage['core/node.js'][258] = 0; + _$jscoverage['core/node.js'][259] = 0; + _$jscoverage['core/node.js'][260] = 0; + _$jscoverage['core/node.js'][261] = 0; + _$jscoverage['core/node.js'][262] = 0; + _$jscoverage['core/node.js'][264] = 0; + _$jscoverage['core/node.js'][266] = 0; + _$jscoverage['core/node.js'][270] = 0; + _$jscoverage['core/node.js'][297] = 0; + _$jscoverage['core/node.js'][298] = 0; + _$jscoverage['core/node.js'][300] = 0; + _$jscoverage['core/node.js'][301] = 0; + _$jscoverage['core/node.js'][302] = 0; + _$jscoverage['core/node.js'][303] = 0; + _$jscoverage['core/node.js'][306] = 0; + _$jscoverage['core/node.js'][307] = 0; + _$jscoverage['core/node.js'][308] = 0; + _$jscoverage['core/node.js'][310] = 0; + _$jscoverage['core/node.js'][324] = 0; + _$jscoverage['core/node.js'][325] = 0; + _$jscoverage['core/node.js'][326] = 0; + _$jscoverage['core/node.js'][342] = 0; + _$jscoverage['core/node.js'][358] = 0; + _$jscoverage['core/node.js'][371] = 0; + _$jscoverage['core/node.js'][372] = 0; + _$jscoverage['core/node.js'][373] = 0; + _$jscoverage['core/node.js'][374] = 0; + _$jscoverage['core/node.js'][390] = 0; + _$jscoverage['core/node.js'][391] = 0; + _$jscoverage['core/node.js'][392] = 0; + _$jscoverage['core/node.js'][393] = 0; + _$jscoverage['core/node.js'][410] = 0; + _$jscoverage['core/node.js'][411] = 0; + _$jscoverage['core/node.js'][412] = 0; + _$jscoverage['core/node.js'][414] = 0; + _$jscoverage['core/node.js'][415] = 0; + _$jscoverage['core/node.js'][416] = 0; + _$jscoverage['core/node.js'][417] = 0; + _$jscoverage['core/node.js'][418] = 0; + _$jscoverage['core/node.js'][419] = 0; + _$jscoverage['core/node.js'][436] = 0; + _$jscoverage['core/node.js'][437] = 0; + _$jscoverage['core/node.js'][438] = 0; + _$jscoverage['core/node.js'][440] = 0; + _$jscoverage['core/node.js'][441] = 0; + _$jscoverage['core/node.js'][443] = 0; + _$jscoverage['core/node.js'][444] = 0; + _$jscoverage['core/node.js'][445] = 0; + _$jscoverage['core/node.js'][446] = 0; + _$jscoverage['core/node.js'][449] = 0; + _$jscoverage['core/node.js'][450] = 0; + _$jscoverage['core/node.js'][451] = 0; + _$jscoverage['core/node.js'][469] = 0; + _$jscoverage['core/node.js'][470] = 0; + _$jscoverage['core/node.js'][471] = 0; + _$jscoverage['core/node.js'][473] = 0; + _$jscoverage['core/node.js'][474] = 0; + _$jscoverage['core/node.js'][475] = 0; + _$jscoverage['core/node.js'][476] = 0; + _$jscoverage['core/node.js'][477] = 0; + _$jscoverage['core/node.js'][496] = 0; + _$jscoverage['core/node.js'][497] = 0; + _$jscoverage['core/node.js'][498] = 0; + _$jscoverage['core/node.js'][500] = 0; + _$jscoverage['core/node.js'][501] = 0; + _$jscoverage['core/node.js'][502] = 0; + _$jscoverage['core/node.js'][503] = 0; + _$jscoverage['core/node.js'][504] = 0; + _$jscoverage['core/node.js'][523] = 0; + _$jscoverage['core/node.js'][524] = 0; + _$jscoverage['core/node.js'][525] = 0; + _$jscoverage['core/node.js'][526] = 0; + _$jscoverage['core/node.js'][527] = 0; + _$jscoverage['core/node.js'][528] = 0; + _$jscoverage['core/node.js'][529] = 0; + _$jscoverage['core/node.js'][530] = 0; + _$jscoverage['core/node.js'][531] = 0; + _$jscoverage['core/node.js'][535] = 0; + _$jscoverage['core/node.js'][552] = 0; + _$jscoverage['core/node.js'][567] = 0; + _$jscoverage['core/node.js'][568] = 0; + _$jscoverage['core/node.js'][569] = 0; + _$jscoverage['core/node.js'][571] = 0; + _$jscoverage['core/node.js'][572] = 0; + _$jscoverage['core/node.js'][574] = 0; + _$jscoverage['core/node.js'][575] = 0; + _$jscoverage['core/node.js'][576] = 0; + _$jscoverage['core/node.js'][577] = 0; + _$jscoverage['core/node.js'][579] = 0; + _$jscoverage['core/node.js'][583] = 0; + _$jscoverage['core/node.js'][584] = 0; + _$jscoverage['core/node.js'][586] = 0; + _$jscoverage['core/node.js'][602] = 0; + _$jscoverage['core/node.js'][603] = 0; + _$jscoverage['core/node.js'][604] = 0; + _$jscoverage['core/node.js'][605] = 0; + _$jscoverage['core/node.js'][608] = 0; + _$jscoverage['core/node.js'][622] = 0; + _$jscoverage['core/node.js'][623] = 0; + _$jscoverage['core/node.js'][624] = 0; + _$jscoverage['core/node.js'][625] = 0; + _$jscoverage['core/node.js'][626] = 0; + _$jscoverage['core/node.js'][643] = 0; + _$jscoverage['core/node.js'][644] = 0; + _$jscoverage['core/node.js'][645] = 0; + _$jscoverage['core/node.js'][646] = 0; + _$jscoverage['core/node.js'][647] = 0; + _$jscoverage['core/node.js'][648] = 0; + _$jscoverage['core/node.js'][652] = 0; + _$jscoverage['core/node.js'][666] = 0; + _$jscoverage['core/node.js'][667] = 0; + _$jscoverage['core/node.js'][668] = 0; + _$jscoverage['core/node.js'][670] = 0; + _$jscoverage['core/node.js'][671] = 0; + _$jscoverage['core/node.js'][672] = 0; + _$jscoverage['core/node.js'][673] = 0; + _$jscoverage['core/node.js'][675] = 0; + _$jscoverage['core/node.js'][689] = 0; + _$jscoverage['core/node.js'][690] = 0; + _$jscoverage['core/node.js'][691] = 0; + _$jscoverage['core/node.js'][692] = 0; + _$jscoverage['core/node.js'][693] = 0; + _$jscoverage['core/node.js'][698] = 0; + _$jscoverage['core/node.js'][699] = 0; + _$jscoverage['core/node.js'][700] = 0; + _$jscoverage['core/node.js'][702] = 0; + _$jscoverage['core/node.js'][703] = 0; + _$jscoverage['core/node.js'][704] = 0; + _$jscoverage['core/node.js'][707] = 0; + _$jscoverage['core/node.js'][709] = 0; + _$jscoverage['core/node.js'][724] = 0; + _$jscoverage['core/node.js'][725] = 0; + _$jscoverage['core/node.js'][727] = 0; +} +_$jscoverage['core/node.js'].source = ["/**"," * 编辑器模拟的节点类"," * @file"," * @module UE"," * @class uNode"," * @since 1.2.6.1"," */","","/**"," * UEditor公用空间,UEditor所有的功能都挂载在该空间下"," * @unfile"," * @module UE"," */","","(function(){",""," /**"," * 编辑器模拟的节点类"," * @unfile"," * @module UE"," * @class uNode"," */",""," /**"," * 通过一个键值对,创建一个uNode对象"," * @constructor"," * @param { KeyValueMap } 传入要创建的uNode的属性"," * @example"," * ```javascript"," * var node = new uNode({"," * type:'element',"," * tagName:'span',"," * attrs:{style:'font-size:14px;'}"," * }"," * ```"," */"," var uNode = UE.uNode =function(obj){"," this.type = obj.type;"," this.data = obj.data;"," this.tagName = obj.tagName;"," this.parentNode = obj.parentNode;"," this.attrs = obj.attrs ||{};"," this.children = obj.children;"," };"," var indentChar =' ',"," breakChar ='\\n';",""," function insertLine(arr, current, begin){"," arr.push(breakChar);"," return current +(begin ?1:-1);"," }",""," function insertIndent(arr, current){"," //插入缩进"," for(var i =0; i < current; i++){"," arr.push(indentChar);"," }"," }",""," //创建uNode的静态方法"," //支持标签和html"," uNode.createElement =function(html){"," if(/[<>]/.test(html)){"," return UE.htmlparser(html).children[0]"," }else{"," returnnew uNode({"," type:'element',"," children:[],"," tagName: html"," })"," }"," };"," uNode.createText =function(data){"," returnnew UE.uNode({"," type:'text',"," 'data': utils.unhtml(data ||'')"," })"," };"," function nodeToHtml(node, arr, formatter, current){"," switch(node.type){"," case'root':"," for(var i =0, ci; ci = node.children[i++];){"," //插入新行"," if(formatter && ci.type =='element'&&!dtd.$inlineWithA[ci.tagName]&& i >1){"," insertLine(arr, current,true);"," insertIndent(arr, current)"," }"," nodeToHtml(ci, arr, formatter, current)"," }"," break;"," case'text':"," isText(node, arr);"," break;"," case'element':"," isElement(node, arr, formatter, current);"," break;"," case'comment':"," isComment(node, arr, formatter);"," }"," return arr;"," }",""," function isText(node, arr){"," arr.push(node.parentNode.tagName =='pre'? node.data : node.data.replace(/[ ]{2}/g,' &nbsp;'))"," }",""," function isElement(node, arr, formatter, current){"," var attrhtml ='';"," if(node.attrs){"," attrhtml =[];"," var attrs = node.attrs;"," for(var a in attrs){"," attrhtml.push(a +(attrs[a]!== undefined ?'=\"'+ utils.unhtml(attrs[a])+'\"':''))"," }"," attrhtml = attrhtml.join(' ');"," }"," arr.push('<'+ node.tagName +"," (attrhtml ?' '+ attrhtml :'')+"," (dtd.$empty[node.tagName]?'\\/':'')+'>'"," );"," //插入新行"," if(formatter &&!dtd.$inlineWithA[node.tagName]&& node.tagName !='pre'){"," if(node.children && node.children.length){"," current = insertLine(arr, current,true);"," insertIndent(arr, current)"," }",""," }"," if(node.children && node.children.length){"," for(var i =0, ci; ci = node.children[i++];){"," if(formatter && ci.type =='element'&&!dtd.$inlineWithA[ci.tagName]&& i >1){"," insertLine(arr, current);"," insertIndent(arr, current)"," }"," nodeToHtml(ci, arr, formatter, current)"," }"," }"," if(!dtd.$empty[node.tagName]){"," if(formatter &&!dtd.$inlineWithA[node.tagName]&& node.tagName !='pre'){",""," if(node.children && node.children.length){"," current = insertLine(arr, current);"," insertIndent(arr, current)"," }"," }"," arr.push('<\\/'+ node.tagName +'>');"," }",""," }",""," function isComment(node, arr){"," arr.push('<!--'+ node.data +'-->');"," }",""," function getNodeById(root, id){"," var node;"," if(root.type =='element'&& root.getAttr('id')== id){"," return root;"," }"," if(root.children && root.children.length){"," for(var i =0, ci; ci = root.children[i++];){"," if(node = getNodeById(ci, id)){"," return node;"," }"," }"," }"," }",""," function getNodesByTagName(node, tagName, arr){"," if(node.type =='element'&& node.tagName == tagName){"," arr.push(node);"," }"," if(node.children && node.children.length){"," for(var i =0, ci; ci = node.children[i++];){"," getNodesByTagName(ci, tagName, arr)"," }"," }"," }",""," function nodeTraversal(root, fn){"," if(root.children && root.children.length){"," for(var i =0, ci; ci = root.children[i];){"," nodeTraversal(ci, fn);"," //ci被替换的情况,这里就不再走 fn了"," if(ci.parentNode){"," if(ci.children && ci.children.length){"," fn(ci)"," }"," if(ci.parentNode) i++"," }"," }"," }else{"," fn(root)"," }",""," }",""," uNode.prototype ={",""," /**"," * 当前节点对象,转换成html文本"," * @method toHtml"," * @return { String } 返回转换后的html字符串"," * @example"," * ```javascript"," * node.toHtml();"," * ```"," */",""," /**"," * 当前节点对象,转换成html文本"," * @method toHtml"," * @param { Boolean } formatter 是否格式化返回值"," * @return { String } 返回转换后的html字符串"," * @example"," * ```javascript"," * node.toHtml();"," * ```"," */"," toHtml:function(formatter){"," var arr =[];"," nodeToHtml(this, arr, formatter,0);"," return arr.join('')"," },",""," /**"," * 获取节点的html内容"," * @method innerHTML"," * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接反悔当前节点"," * @return { String } 返回节点的html内容"," * @example"," * ```javascript"," * var htmlstr = node.innerHTML();"," * ```"," */",""," /**"," * 设置节点的html内容"," * @method innerHTML"," * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接反悔当前节点"," * @param { String } htmlstr 传入要设置的html内容"," * @return { UE.uNode } 返回节点本身"," * @example"," * ```javascript"," * node.innerHTML('<span>text</span>');"," * ```"," */"," innerHTML:function(htmlstr){"," if(this.type !='element'|| dtd.$empty[this.tagName]){"," returnthis;"," }"," if(utils.isString(htmlstr)){"," if(this.children){"," for(var i =0, ci; ci =this.children[i++];){"," ci.parentNode =null;"," }"," }"," this.children =[];"," var tmpRoot = UE.htmlparser(htmlstr);"," for(var i =0, ci; ci = tmpRoot.children[i++];){"," this.children.push(ci);"," ci.parentNode =this;"," }"," returnthis;"," }else{"," var tmpRoot =new UE.uNode({"," type:'root',"," children:this.children"," });"," return tmpRoot.toHtml();"," }"," },",""," /**"," * 获取节点的纯文本内容"," * @method innerText"," * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接反悔当前节点"," * @return { String } 返回节点的存文本内容"," * @example"," * ```javascript"," * var textStr = node.innerText();"," * ```"," */",""," /**"," * 获取节点的纯文本内容"," * @method innerText"," * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接反悔当前节点"," * @param { String } textStr 传入要设置的文本内容"," * @return { UE.uNode } 返回节点本身"," * @example"," * ```javascript"," * node.innerText('<span>text</span>');"," * ```"," */"," innerText:function(textStr){"," if(this.type !='element'|| dtd.$empty[this.tagName]){"," returnthis;"," }"," if(textStr){"," if(this.children){"," for(var i =0, ci; ci =this.children[i++];){"," ci.parentNode =null;"," }"," }"," this.children =[];"," this.appendChild(uNode.createText(textStr));"," returnthis;"," }else{"," returnthis.toHtml().replace(/<[^>]+>/g,'');"," }"," },",""," /**"," * 获取当前对象的data属性"," * @method getData"," * @return { KeyValueMap } 若节点的type值是elemenet,返回空字符串,否则返回节点的data属性"," * @example"," * ```javascript"," * node.getData();"," * ```"," */"," getData:function(){"," if(this.type =='element')"," return'';"," returnthis.data"," },",""," /**"," * 获取当前节点下的第一个子节点"," * @method firstChild"," * @return { UE.uNode } 返回第一个子节点"," * @example"," * ```javascript"," * node.firstChild(); //返回第一个子节点"," * ```"," */"," firstChild:function(){","// if (this.type != 'element' || dtd.$empty[this.tagName]) {","// return this;","// }"," returnthis.children ?this.children[0]:null;"," },",""," /**"," * 获取当前节点下的最后一个子节点"," * @method lastChild"," * @return { UE.uNode } 返回最后一个子节点"," * @example"," * ```javascript"," * node.lastChild(); //返回最后一个子节点"," * ```"," */"," lastChild:function(){","// if (this.type != 'element' || dtd.$empty[this.tagName] ) {","// return this;","// }"," returnthis.children ?this.children[this.children.length -1]:null;"," },",""," /**"," * 获取和当前节点有相同父亲节点的前一个节点"," * @method previousSibling"," * @return { UE.uNode } 返回前一个节点"," * @example"," * ```javascript"," * node.children[2].previousSibling(); //返回子节点node.children[1]"," * ```"," */"," previousSibling:function(){"," var parent =this.parentNode;"," for(var i =0, ci; ci = parent.children[i]; i++){"," if(ci ===this){"," return i ==0?null: parent.children[i -1];"," }"," }",""," },",""," /**"," * 获取和当前节点有相同父亲节点的后一个节点"," * @method nextSibling"," * @return { UE.uNode } 返回后一个节点,找不到返回null"," * @example"," * ```javascript"," * node.children[2].nextSibling(); //如果有,返回子节点node.children[3]"," * ```"," */"," nextSibling:function(){"," var parent =this.parentNode;"," for(var i =0, ci; ci = parent.children[i++];){"," if(ci ===this){"," return parent.children[i];"," }"," }"," },",""," /**"," * 用新的节点替换当前节点"," * @method replaceChild"," * @param { UE.uNode } target 要替换成该节点参数"," * @param { UE.uNode } source 要被替换掉的节点"," * @return { UE.uNode } 返回替换之后的节点对象"," * @example"," * ```javascript"," * node.replaceChild(newNode, childNode); //用newNode替换childNode,childNode是node的子节点"," * ```"," */"," replaceChild:function(target, source){"," if(this.children){"," if(target.parentNode){"," target.parentNode.removeChild(target);"," }"," for(var i =0, ci; ci =this.children[i]; i++){"," if(ci === source){"," this.children.splice(i,1, target);"," source.parentNode =null;"," target.parentNode =this;"," return target;"," }"," }"," }"," },",""," /**"," * 在节点的子节点列表最后位置插入一个节点"," * @method appendChild"," * @param { UE.uNode } node 要插入的节点"," * @return { UE.uNode } 返回刚插入的子节点"," * @example"," * ```javascript"," * node.appendChild( newNode ); //在node内插入子节点newNode"," * ```"," */"," appendChild:function(node){"," if(this.type =='root'||(this.type =='element'&&!dtd.$empty[this.tagName])){"," if(!this.children){"," this.children =[]"," }"," if(node.parentNode){"," node.parentNode.removeChild(node);"," }"," for(var i =0, ci; ci =this.children[i]; i++){"," if(ci === node){"," this.children.splice(i,1);"," break;"," }"," }"," this.children.push(node);"," node.parentNode =this;"," return node;"," }","",""," },",""," /**"," * 在传入节点的前面插入一个节点"," * @method insertBefore"," * @param { UE.uNode } target 要插入的节点"," * @param { UE.uNode } source 在该参数节点前面插入"," * @return { UE.uNode } 返回刚插入的子节点"," * @example"," * ```javascript"," * node.parentNode.insertBefore(newNode, node); //在node节点后面插入newNode"," * ```"," */"," insertBefore:function(target, source){"," if(this.children){"," if(target.parentNode){"," target.parentNode.removeChild(target);"," }"," for(var i =0, ci; ci =this.children[i]; i++){"," if(ci === source){"," this.children.splice(i,0, target);"," target.parentNode =this;"," return target;"," }"," }",""," }"," },",""," /**"," * 在传入节点的后面插入一个节点"," * @method insertAfter"," * @param { UE.uNode } target 要插入的节点"," * @param { UE.uNode } source 在该参数节点后面插入"," * @return { UE.uNode } 返回刚插入的子节点"," * @example"," * ```javascript"," * node.parentNode.insertAfter(newNode, node); //在node节点后面插入newNode"," * ```"," */"," insertAfter:function(target, source){"," if(this.children){"," if(target.parentNode){"," target.parentNode.removeChild(target);"," }"," for(var i =0, ci; ci =this.children[i]; i++){"," if(ci === source){"," this.children.splice(i +1,0, target);"," target.parentNode =this;"," return target;"," }",""," }"," }"," },",""," /**"," * 从当前节点的子节点列表中,移除节点"," * @method removeChild"," * @param { UE.uNode } node 要移除的节点引用"," * @param { Boolean } keepChildren 是否保留移除节点的子节点,若传入true,自动把移除节点的子节点插入到移除的位置"," * @return { * } 返回刚移除的子节点"," * @example"," * ```javascript"," * node.removeChild(childNode,true); //在node的子节点列表中移除child节点,并且吧child的子节点插入到移除的位置"," * ```"," */"," removeChild:function(node, keepChildren){"," if(this.children){"," for(var i =0, ci; ci =this.children[i]; i++){"," if(ci === node){"," this.children.splice(i,1);"," ci.parentNode =null;"," if(keepChildren && ci.children && ci.children.length){"," for(var j =0, cj; cj = ci.children[j]; j++){"," this.children.splice(i + j,0, cj);"," cj.parentNode =this;",""," }"," }"," return ci;"," }"," }"," }"," },",""," /**"," * 获取当前节点所代表的元素属性,即获取attrs对象下的属性值"," * @method getAttr"," * @param { String } attrName 要获取的属性名称"," * @return { * } 返回attrs对象下的属性值"," * @example"," * ```javascript"," * node.getAttr('title');"," * ```"," */"," getAttr:function(attrName){"," returnthis.attrs &&this.attrs[attrName.toLowerCase()]"," },",""," /**"," * 设置当前节点所代表的元素属性,即设置attrs对象下的属性值"," * @method getAttr"," * @param { String } attrName 要设置的属性名称"," * @param { * } attrVal 要设置的属性值,类型视设置的属性而定"," * @return { * } 返回attrs对象下的属性值"," * @example"," * ```javascript"," * node.setAttr('title','标题');"," * ```"," */"," setAttr:function(attrName, attrVal){"," if(!attrName){"," deletethis.attrs;"," return;"," }"," if(!this.attrs){"," this.attrs ={};"," }"," if(utils.isObject(attrName)){"," for(var a in attrName){"," if(!attrName[a]){"," deletethis.attrs[a]"," }else{"," this.attrs[a.toLowerCase()]= attrName[a];"," }"," }"," }else{"," if(!attrVal){"," deletethis.attrs[attrName]"," }else{"," this.attrs[attrName.toLowerCase()]= attrVal;"," }",""," }"," },",""," /**"," * 获取当前节点在父节点下的位置索引"," * @method getIndex"," * @return { Number } 返回索引数值,如果没有父节点,返回-1"," * @example"," * ```javascript"," * node.getIndex();"," * ```"," */"," getIndex:function(){"," var parent =this.parentNode;"," for(var i =0, ci; ci = parent.children[i]; i++){"," if(ci ===this){"," return i;"," }"," }"," return-1;"," },",""," /**"," * 在当前节点下,根据id查找节点"," * @method getNodeById"," * @param { String } id 要查找的id"," * @return { UE.uNode } 返回找到的节点"," * @example"," * ```javascript"," * node.getNodeById('textId');"," * ```"," */"," getNodeById:function(id){"," var node;"," if(this.children &&this.children.length){"," for(var i =0, ci; ci =this.children[i++];){"," if(node = getNodeById(ci, id)){"," return node;"," }"," }"," }"," },",""," /**"," * 在当前节点下,根据元素名称查找节点列表"," * @method getNodeById"," * @param { String } tagNames 要查找的元素名称"," * @return { Array } 返回找到的节点列表"," * @example"," * ```javascript"," * node.getNodesByTagName('span');"," * ```"," */"," getNodesByTagName:function(tagNames){"," tagNames = utils.trim(tagNames).replace(/[ ]{2,}/g,' ').split(' ');"," var arr =[], me =this;"," utils.each(tagNames,function(tagName){"," if(me.children && me.children.length){"," for(var i =0, ci; ci = me.children[i++];){"," getNodesByTagName(ci, tagName, arr)"," }"," }"," });"," return arr;"," },",""," /**"," * 根据样式名称,获取节点的样式值"," * @method getStyle"," * @param { String } name 要获取的样式名称"," * @return { String } 返回样式值"," * @example"," * ```javascript"," * node.getStyle('font-size');"," * ```"," */"," getStyle:function(name){"," var cssStyle =this.getAttr('style');"," if(!cssStyle){"," return''"," }"," var reg =new RegExp(name +':([^;]+)','i');"," var match = cssStyle.match(reg);"," if(match && match[0]){"," return match[1]"," }"," return'';"," },",""," /**"," * 给节点设置样式"," * @method setStyle"," * @param { String } name 要设置的的样式名称"," * @param { String } val 要设置的的样值"," * @example"," * ```javascript"," * node.setStyle('font-size', '12px');"," * ```"," */"," setStyle:function(name, val){"," function exec(name, val){"," var reg =new RegExp(name +':([^;]+;?)','gi');"," cssStyle = cssStyle.replace(reg,'');"," if(val){"," cssStyle = name +':'+ utils.unhtml(val)+';'+ cssStyle"," }",""," }",""," var cssStyle =this.getAttr('style');"," if(!cssStyle){"," cssStyle ='';"," }"," if(utils.isObject(name)){"," for(var a in name){"," exec(a, name[a])"," }"," }else{"," exec(name, val)"," }"," this.setAttr('style', utils.trim(cssStyle))"," },",""," /**"," * 传入一个函数,递归遍历当前节点下的所有节点"," * @method traversal"," * @param { Function } fn 遍历到节点的时,传入节点作为参数,运行此函数"," * @example"," * ```javascript"," * traversal(node, function(){"," * console.log(node.type);"," * });"," * ```"," */"," traversal:function(fn){"," if(this.children &&this.children.length){"," nodeTraversal(this, fn);"," }"," returnthis;"," }"," }","})();"]; +_$jscoverage['core/node.js'][15]++; +(function () { + _$jscoverage['core/node.js'][37]++; + var uNode = (UE.uNode = (function (obj) { + _$jscoverage['core/node.js'][38]++; + this.type = obj.type; + _$jscoverage['core/node.js'][39]++; + this.data = obj.data; + _$jscoverage['core/node.js'][40]++; + this.tagName = obj.tagName; + _$jscoverage['core/node.js'][41]++; + this.parentNode = obj.parentNode; + _$jscoverage['core/node.js'][42]++; + this.attrs = (obj.attrs || {}); + _$jscoverage['core/node.js'][43]++; + this.children = obj.children; +})); + _$jscoverage['core/node.js'][45]++; + var indentChar = " ", breakChar = "\n"; + _$jscoverage['core/node.js'][48]++; + function insertLine(arr, current, begin) { + _$jscoverage['core/node.js'][49]++; + arr.push(breakChar); + _$jscoverage['core/node.js'][50]++; + return (current + (begin? 1: -1)); +} + _$jscoverage['core/node.js'][53]++; + function insertIndent(arr, current) { + _$jscoverage['core/node.js'][55]++; + for (var i = 0; (i < current); (i++)) { + _$jscoverage['core/node.js'][56]++; + arr.push(indentChar); +} +} + _$jscoverage['core/node.js'][62]++; + uNode.createElement = (function (html) { + _$jscoverage['core/node.js'][63]++; + if (/[<>]/.test(html)) { + _$jscoverage['core/node.js'][64]++; + return UE.htmlparser(html).children[0]; + } + else { + _$jscoverage['core/node.js'][66]++; + return new uNode({type: "element", children: [], tagName: html}); + } +}); + _$jscoverage['core/node.js'][73]++; + uNode.createText = (function (data) { + _$jscoverage['core/node.js'][74]++; + return new (UE.uNode)({type: "text", "data": utils.unhtml((data || ""))}); +}); + _$jscoverage['core/node.js'][79]++; + function nodeToHtml(node, arr, formatter, current) { + _$jscoverage['core/node.js'][80]++; + switch (node.type) { + case "root": + _$jscoverage['core/node.js'][82]++; + for (var i = 0, ci; (ci = node.children[(i++)]);) { + _$jscoverage['core/node.js'][84]++; + if ((formatter && (ci.type == "element") && (! dtd.$inlineWithA[ci.tagName]) && (i > 1))) { + _$jscoverage['core/node.js'][85]++; + insertLine(arr, current, true); + _$jscoverage['core/node.js'][86]++; + insertIndent(arr, current); + } + _$jscoverage['core/node.js'][88]++; + nodeToHtml(ci, arr, formatter, current); +} + _$jscoverage['core/node.js'][90]++; + break; + case "text": + _$jscoverage['core/node.js'][92]++; + isText(node, arr); + _$jscoverage['core/node.js'][93]++; + break; + case "element": + _$jscoverage['core/node.js'][95]++; + isElement(node, arr, formatter, current); + _$jscoverage['core/node.js'][96]++; + break; + case "comment": + _$jscoverage['core/node.js'][98]++; + isComment(node, arr, formatter); + } + _$jscoverage['core/node.js'][100]++; + return arr; +} + _$jscoverage['core/node.js'][103]++; + function isText(node, arr) { + _$jscoverage['core/node.js'][104]++; + arr.push(((node.parentNode.tagName == "pre")? node.data: node.data.replace(/[ ]{2}/g, "  "))); +} + _$jscoverage['core/node.js'][107]++; + function isElement(node, arr, formatter, current) { + _$jscoverage['core/node.js'][108]++; + var attrhtml = ""; + _$jscoverage['core/node.js'][109]++; + if (node.attrs) { + _$jscoverage['core/node.js'][110]++; + attrhtml = []; + _$jscoverage['core/node.js'][111]++; + var attrs = node.attrs; + _$jscoverage['core/node.js'][112]++; + for (var a in attrs) { + _$jscoverage['core/node.js'][113]++; + attrhtml.push((a + ((attrs[a] !== undefined)? ("=\"" + utils.unhtml(attrs[a]) + "\""): ""))); +} + _$jscoverage['core/node.js'][115]++; + attrhtml = attrhtml.join(" "); + } + _$jscoverage['core/node.js'][117]++; + arr.push(("<" + node.tagName + (attrhtml? (" " + attrhtml): "") + (dtd.$empty[node.tagName]? "/": "") + ">")); + _$jscoverage['core/node.js'][122]++; + if ((formatter && (! dtd.$inlineWithA[node.tagName]) && (node.tagName != "pre"))) { + _$jscoverage['core/node.js'][123]++; + if ((node.children && node.children.length)) { + _$jscoverage['core/node.js'][124]++; + current = insertLine(arr, current, true); + _$jscoverage['core/node.js'][125]++; + insertIndent(arr, current); + } + } + _$jscoverage['core/node.js'][129]++; + if ((node.children && node.children.length)) { + _$jscoverage['core/node.js'][130]++; + for (var i = 0, ci; (ci = node.children[(i++)]);) { + _$jscoverage['core/node.js'][131]++; + if ((formatter && (ci.type == "element") && (! dtd.$inlineWithA[ci.tagName]) && (i > 1))) { + _$jscoverage['core/node.js'][132]++; + insertLine(arr, current); + _$jscoverage['core/node.js'][133]++; + insertIndent(arr, current); + } + _$jscoverage['core/node.js'][135]++; + nodeToHtml(ci, arr, formatter, current); +} + } + _$jscoverage['core/node.js'][138]++; + if ((! dtd.$empty[node.tagName])) { + _$jscoverage['core/node.js'][139]++; + if ((formatter && (! dtd.$inlineWithA[node.tagName]) && (node.tagName != "pre"))) { + _$jscoverage['core/node.js'][141]++; + if ((node.children && node.children.length)) { + _$jscoverage['core/node.js'][142]++; + current = insertLine(arr, current); + _$jscoverage['core/node.js'][143]++; + insertIndent(arr, current); + } + } + _$jscoverage['core/node.js'][146]++; + arr.push(("")); + } +} + _$jscoverage['core/node.js'][151]++; + function isComment(node, arr) { + _$jscoverage['core/node.js'][152]++; + arr.push(("")); +} + _$jscoverage['core/node.js'][155]++; + function getNodeById(root, id) { + _$jscoverage['core/node.js'][156]++; + var node; + _$jscoverage['core/node.js'][157]++; + if (((root.type == "element") && (root.getAttr("id") == id))) { + _$jscoverage['core/node.js'][158]++; + return root; + } + _$jscoverage['core/node.js'][160]++; + if ((root.children && root.children.length)) { + _$jscoverage['core/node.js'][161]++; + for (var i = 0, ci; (ci = root.children[(i++)]);) { + _$jscoverage['core/node.js'][162]++; + if ((node = getNodeById(ci, id))) { + _$jscoverage['core/node.js'][163]++; + return node; + } +} + } +} + _$jscoverage['core/node.js'][169]++; + function getNodesByTagName(node, tagName, arr) { + _$jscoverage['core/node.js'][170]++; + if (((node.type == "element") && (node.tagName == tagName))) { + _$jscoverage['core/node.js'][171]++; + arr.push(node); + } + _$jscoverage['core/node.js'][173]++; + if ((node.children && node.children.length)) { + _$jscoverage['core/node.js'][174]++; + for (var i = 0, ci; (ci = node.children[(i++)]);) { + _$jscoverage['core/node.js'][175]++; + getNodesByTagName(ci, tagName, arr); +} + } +} + _$jscoverage['core/node.js'][180]++; + function nodeTraversal(root, fn) { + _$jscoverage['core/node.js'][181]++; + if ((root.children && root.children.length)) { + _$jscoverage['core/node.js'][182]++; + for (var i = 0, ci; (ci = root.children[i]);) { + _$jscoverage['core/node.js'][183]++; + nodeTraversal(ci, fn); + _$jscoverage['core/node.js'][185]++; + if (ci.parentNode) { + _$jscoverage['core/node.js'][186]++; + if ((ci.children && ci.children.length)) { + _$jscoverage['core/node.js'][187]++; + fn(ci); + } + _$jscoverage['core/node.js'][189]++; + if (ci.parentNode) { + _$jscoverage['core/node.js'][189]++; + (i++); + } + } +} + } + else { + _$jscoverage['core/node.js'][193]++; + fn(root); + } +} + _$jscoverage['core/node.js'][198]++; + uNode.prototype = {toHtml: (function (formatter) { + _$jscoverage['core/node.js'][221]++; + var arr = []; + _$jscoverage['core/node.js'][222]++; + nodeToHtml(this, arr, formatter, 0); + _$jscoverage['core/node.js'][223]++; + return arr.join(""); +}), innerHTML: (function (htmlstr) { + _$jscoverage['core/node.js'][249]++; + if (((this.type != "element") || dtd.$empty[this.tagName])) { + _$jscoverage['core/node.js'][250]++; + return this; + } + _$jscoverage['core/node.js'][252]++; + if (utils.isString(htmlstr)) { + _$jscoverage['core/node.js'][253]++; + if (this.children) { + _$jscoverage['core/node.js'][254]++; + for (var i = 0, ci; (ci = this.children[(i++)]);) { + _$jscoverage['core/node.js'][255]++; + ci.parentNode = null; +} + } + _$jscoverage['core/node.js'][258]++; + this.children = []; + _$jscoverage['core/node.js'][259]++; + var tmpRoot = UE.htmlparser(htmlstr); + _$jscoverage['core/node.js'][260]++; + for (var i = 0, ci = ci; (ci = tmpRoot.children[(i++)]);) { + _$jscoverage['core/node.js'][261]++; + this.children.push(ci); + _$jscoverage['core/node.js'][262]++; + ci.parentNode = this; +} + _$jscoverage['core/node.js'][264]++; + return this; + } + else { + _$jscoverage['core/node.js'][266]++; + var tmpRoot = new (UE.uNode)({type: "root", children: this.children}); + _$jscoverage['core/node.js'][270]++; + return tmpRoot.toHtml(); + } +}), innerText: (function (textStr) { + _$jscoverage['core/node.js'][297]++; + if (((this.type != "element") || dtd.$empty[this.tagName])) { + _$jscoverage['core/node.js'][298]++; + return this; + } + _$jscoverage['core/node.js'][300]++; + if (textStr) { + _$jscoverage['core/node.js'][301]++; + if (this.children) { + _$jscoverage['core/node.js'][302]++; + for (var i = 0, ci; (ci = this.children[(i++)]);) { + _$jscoverage['core/node.js'][303]++; + ci.parentNode = null; +} + } + _$jscoverage['core/node.js'][306]++; + this.children = []; + _$jscoverage['core/node.js'][307]++; + this.appendChild(uNode.createText(textStr)); + _$jscoverage['core/node.js'][308]++; + return this; + } + else { + _$jscoverage['core/node.js'][310]++; + return this.toHtml().replace(/<[^>]+>/g, ""); + } +}), getData: (function () { + _$jscoverage['core/node.js'][324]++; + if ((this.type == "element")) { + _$jscoverage['core/node.js'][325]++; + return ""; + } + _$jscoverage['core/node.js'][326]++; + return this.data; +}), firstChild: (function () { + _$jscoverage['core/node.js'][342]++; + return (this.children? this.children[0]: null); +}), lastChild: (function () { + _$jscoverage['core/node.js'][358]++; + return (this.children? this.children[(this.children.length - 1)]: null); +}), previousSibling: (function () { + _$jscoverage['core/node.js'][371]++; + var parent = this.parentNode; + _$jscoverage['core/node.js'][372]++; + for (var i = 0, ci; (ci = parent.children[i]); (i++)) { + _$jscoverage['core/node.js'][373]++; + if ((ci === this)) { + _$jscoverage['core/node.js'][374]++; + return ((i == 0)? null: parent.children[(i - 1)]); + } +} +}), nextSibling: (function () { + _$jscoverage['core/node.js'][390]++; + var parent = this.parentNode; + _$jscoverage['core/node.js'][391]++; + for (var i = 0, ci; (ci = parent.children[(i++)]);) { + _$jscoverage['core/node.js'][392]++; + if ((ci === this)) { + _$jscoverage['core/node.js'][393]++; + return parent.children[i]; + } +} +}), replaceChild: (function (target, source) { + _$jscoverage['core/node.js'][410]++; + if (this.children) { + _$jscoverage['core/node.js'][411]++; + if (target.parentNode) { + _$jscoverage['core/node.js'][412]++; + target.parentNode.removeChild(target); + } + _$jscoverage['core/node.js'][414]++; + for (var i = 0, ci; (ci = this.children[i]); (i++)) { + _$jscoverage['core/node.js'][415]++; + if ((ci === source)) { + _$jscoverage['core/node.js'][416]++; + this.children.splice(i, 1, target); + _$jscoverage['core/node.js'][417]++; + source.parentNode = null; + _$jscoverage['core/node.js'][418]++; + target.parentNode = this; + _$jscoverage['core/node.js'][419]++; + return target; + } +} + } +}), appendChild: (function (node) { + _$jscoverage['core/node.js'][436]++; + if (((this.type == "root") || ((this.type == "element") && (! dtd.$empty[this.tagName])))) { + _$jscoverage['core/node.js'][437]++; + if ((! this.children)) { + _$jscoverage['core/node.js'][438]++; + this.children = []; + } + _$jscoverage['core/node.js'][440]++; + if (node.parentNode) { + _$jscoverage['core/node.js'][441]++; + node.parentNode.removeChild(node); + } + _$jscoverage['core/node.js'][443]++; + for (var i = 0, ci; (ci = this.children[i]); (i++)) { + _$jscoverage['core/node.js'][444]++; + if ((ci === node)) { + _$jscoverage['core/node.js'][445]++; + this.children.splice(i, 1); + _$jscoverage['core/node.js'][446]++; + break; + } +} + _$jscoverage['core/node.js'][449]++; + this.children.push(node); + _$jscoverage['core/node.js'][450]++; + node.parentNode = this; + _$jscoverage['core/node.js'][451]++; + return node; + } +}), insertBefore: (function (target, source) { + _$jscoverage['core/node.js'][469]++; + if (this.children) { + _$jscoverage['core/node.js'][470]++; + if (target.parentNode) { + _$jscoverage['core/node.js'][471]++; + target.parentNode.removeChild(target); + } + _$jscoverage['core/node.js'][473]++; + for (var i = 0, ci; (ci = this.children[i]); (i++)) { + _$jscoverage['core/node.js'][474]++; + if ((ci === source)) { + _$jscoverage['core/node.js'][475]++; + this.children.splice(i, 0, target); + _$jscoverage['core/node.js'][476]++; + target.parentNode = this; + _$jscoverage['core/node.js'][477]++; + return target; + } +} + } +}), insertAfter: (function (target, source) { + _$jscoverage['core/node.js'][496]++; + if (this.children) { + _$jscoverage['core/node.js'][497]++; + if (target.parentNode) { + _$jscoverage['core/node.js'][498]++; + target.parentNode.removeChild(target); + } + _$jscoverage['core/node.js'][500]++; + for (var i = 0, ci; (ci = this.children[i]); (i++)) { + _$jscoverage['core/node.js'][501]++; + if ((ci === source)) { + _$jscoverage['core/node.js'][502]++; + this.children.splice((i + 1), 0, target); + _$jscoverage['core/node.js'][503]++; + target.parentNode = this; + _$jscoverage['core/node.js'][504]++; + return target; + } +} + } +}), removeChild: (function (node, keepChildren) { + _$jscoverage['core/node.js'][523]++; + if (this.children) { + _$jscoverage['core/node.js'][524]++; + for (var i = 0, ci; (ci = this.children[i]); (i++)) { + _$jscoverage['core/node.js'][525]++; + if ((ci === node)) { + _$jscoverage['core/node.js'][526]++; + this.children.splice(i, 1); + _$jscoverage['core/node.js'][527]++; + ci.parentNode = null; + _$jscoverage['core/node.js'][528]++; + if ((keepChildren && ci.children && ci.children.length)) { + _$jscoverage['core/node.js'][529]++; + for (var j = 0, cj; (cj = ci.children[j]); (j++)) { + _$jscoverage['core/node.js'][530]++; + this.children.splice((i + j), 0, cj); + _$jscoverage['core/node.js'][531]++; + cj.parentNode = this; +} + } + _$jscoverage['core/node.js'][535]++; + return ci; + } +} + } +}), getAttr: (function (attrName) { + _$jscoverage['core/node.js'][552]++; + return (this.attrs && this.attrs[attrName.toLowerCase()]); +}), setAttr: (function (attrName, attrVal) { + _$jscoverage['core/node.js'][567]++; + if ((! attrName)) { + _$jscoverage['core/node.js'][568]++; + (delete this.attrs); + _$jscoverage['core/node.js'][569]++; + return; + } + _$jscoverage['core/node.js'][571]++; + if ((! this.attrs)) { + _$jscoverage['core/node.js'][572]++; + this.attrs = {}; + } + _$jscoverage['core/node.js'][574]++; + if (utils.isObject(attrName)) { + _$jscoverage['core/node.js'][575]++; + for (var a in attrName) { + _$jscoverage['core/node.js'][576]++; + if ((! attrName[a])) { + _$jscoverage['core/node.js'][577]++; + (delete this.attrs[a]); + } + else { + _$jscoverage['core/node.js'][579]++; + this.attrs[a.toLowerCase()] = attrName[a]; + } +} + } + else { + _$jscoverage['core/node.js'][583]++; + if ((! attrVal)) { + _$jscoverage['core/node.js'][584]++; + (delete this.attrs[attrName]); + } + else { + _$jscoverage['core/node.js'][586]++; + this.attrs[attrName.toLowerCase()] = attrVal; + } + } +}), getIndex: (function () { + _$jscoverage['core/node.js'][602]++; + var parent = this.parentNode; + _$jscoverage['core/node.js'][603]++; + for (var i = 0, ci; (ci = parent.children[i]); (i++)) { + _$jscoverage['core/node.js'][604]++; + if ((ci === this)) { + _$jscoverage['core/node.js'][605]++; + return i; + } +} + _$jscoverage['core/node.js'][608]++; + return -1; +}), getNodeById: (function (id) { + _$jscoverage['core/node.js'][622]++; + var node; + _$jscoverage['core/node.js'][623]++; + if ((this.children && this.children.length)) { + _$jscoverage['core/node.js'][624]++; + for (var i = 0, ci; (ci = this.children[(i++)]);) { + _$jscoverage['core/node.js'][625]++; + if ((node = getNodeById(ci, id))) { + _$jscoverage['core/node.js'][626]++; + return node; + } +} + } +}), getNodesByTagName: (function (tagNames) { + _$jscoverage['core/node.js'][643]++; + tagNames = utils.trim(tagNames).replace(/[ ]{2,}/g, " ").split(" "); + _$jscoverage['core/node.js'][644]++; + var arr = [], me = this; + _$jscoverage['core/node.js'][645]++; + utils.each(tagNames, (function (tagName) { + _$jscoverage['core/node.js'][646]++; + if ((me.children && me.children.length)) { + _$jscoverage['core/node.js'][647]++; + for (var i = 0, ci; (ci = me.children[(i++)]);) { + _$jscoverage['core/node.js'][648]++; + getNodesByTagName(ci, tagName, arr); +} + } +})); + _$jscoverage['core/node.js'][652]++; + return arr; +}), getStyle: (function (name) { + _$jscoverage['core/node.js'][666]++; + var cssStyle = this.getAttr("style"); + _$jscoverage['core/node.js'][667]++; + if ((! cssStyle)) { + _$jscoverage['core/node.js'][668]++; + return ""; + } + _$jscoverage['core/node.js'][670]++; + var reg = new RegExp((name + ":([^;]+)"), "i"); + _$jscoverage['core/node.js'][671]++; + var match = cssStyle.match(reg); + _$jscoverage['core/node.js'][672]++; + if ((match && match[0])) { + _$jscoverage['core/node.js'][673]++; + return match[1]; + } + _$jscoverage['core/node.js'][675]++; + return ""; +}), setStyle: (function (name, val) { + _$jscoverage['core/node.js'][689]++; + function exec(name, val) { + _$jscoverage['core/node.js'][690]++; + var reg = new RegExp((name + ":([^;]+;?)"), "gi"); + _$jscoverage['core/node.js'][691]++; + cssStyle = cssStyle.replace(reg, ""); + _$jscoverage['core/node.js'][692]++; + if (val) { + _$jscoverage['core/node.js'][693]++; + cssStyle = (name + ":" + utils.unhtml(val) + ";" + cssStyle); + } +} + _$jscoverage['core/node.js'][698]++; + var cssStyle = this.getAttr("style"); + _$jscoverage['core/node.js'][699]++; + if ((! cssStyle)) { + _$jscoverage['core/node.js'][700]++; + cssStyle = ""; + } + _$jscoverage['core/node.js'][702]++; + if (utils.isObject(name)) { + _$jscoverage['core/node.js'][703]++; + for (var a in name) { + _$jscoverage['core/node.js'][704]++; + exec(a, name[a]); +} + } + else { + _$jscoverage['core/node.js'][707]++; + exec(name, val); + } + _$jscoverage['core/node.js'][709]++; + this.setAttr("style", utils.trim(cssStyle)); +}), traversal: (function (fn) { + _$jscoverage['core/node.js'][724]++; + if ((this.children && this.children.length)) { + _$jscoverage['core/node.js'][725]++; + nodeTraversal(this, fn); + } + _$jscoverage['core/node.js'][727]++; + return this; +})}; +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/utils.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/utils.js new file mode 100644 index 000000000..b1af08e77 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/core/utils.js @@ -0,0 +1,888 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['core/utils.js']) { + _$jscoverage['core/utils.js'] = []; + _$jscoverage['core/utils.js'][14] = 0; + _$jscoverage['core/utils.js'][55] = 0; + _$jscoverage['core/utils.js'][56] = 0; + _$jscoverage['core/utils.js'][57] = 0; + _$jscoverage['core/utils.js'][58] = 0; + _$jscoverage['core/utils.js'][59] = 0; + _$jscoverage['core/utils.js'][62] = 0; + _$jscoverage['core/utils.js'][63] = 0; + _$jscoverage['core/utils.js'][64] = 0; + _$jscoverage['core/utils.js'][65] = 0; + _$jscoverage['core/utils.js'][87] = 0; + _$jscoverage['core/utils.js'][88] = 0; + _$jscoverage['core/utils.js'][89] = 0; + _$jscoverage['core/utils.js'][90] = 0; + _$jscoverage['core/utils.js'][91] = 0; + _$jscoverage['core/utils.js'][138] = 0; + _$jscoverage['core/utils.js'][139] = 0; + _$jscoverage['core/utils.js'][140] = 0; + _$jscoverage['core/utils.js'][141] = 0; + _$jscoverage['core/utils.js'][145] = 0; + _$jscoverage['core/utils.js'][172] = 0; + _$jscoverage['core/utils.js'][173] = 0; + _$jscoverage['core/utils.js'][174] = 0; + _$jscoverage['core/utils.js'][175] = 0; + _$jscoverage['core/utils.js'][176] = 0; + _$jscoverage['core/utils.js'][177] = 0; + _$jscoverage['core/utils.js'][181] = 0; + _$jscoverage['core/utils.js'][215] = 0; + _$jscoverage['core/utils.js'][217] = 0; + _$jscoverage['core/utils.js'][218] = 0; + _$jscoverage['core/utils.js'][219] = 0; + _$jscoverage['core/utils.js'][249] = 0; + _$jscoverage['core/utils.js'][250] = 0; + _$jscoverage['core/utils.js'][304] = 0; + _$jscoverage['core/utils.js'][305] = 0; + _$jscoverage['core/utils.js'][306] = 0; + _$jscoverage['core/utils.js'][307] = 0; + _$jscoverage['core/utils.js'][309] = 0; + _$jscoverage['core/utils.js'][348] = 0; + _$jscoverage['core/utils.js'][349] = 0; + _$jscoverage['core/utils.js'][350] = 0; + _$jscoverage['core/utils.js'][351] = 0; + _$jscoverage['core/utils.js'][352] = 0; + _$jscoverage['core/utils.js'][353] = 0; + _$jscoverage['core/utils.js'][356] = 0; + _$jscoverage['core/utils.js'][376] = 0; + _$jscoverage['core/utils.js'][377] = 0; + _$jscoverage['core/utils.js'][378] = 0; + _$jscoverage['core/utils.js'][379] = 0; + _$jscoverage['core/utils.js'][406] = 0; + _$jscoverage['core/utils.js'][439] = 0; + _$jscoverage['core/utils.js'][440] = 0; + _$jscoverage['core/utils.js'][441] = 0; + _$jscoverage['core/utils.js'][442] = 0; + _$jscoverage['core/utils.js'][444] = 0; + _$jscoverage['core/utils.js'][462] = 0; + _$jscoverage['core/utils.js'][463] = 0; + _$jscoverage['core/utils.js'][464] = 0; + _$jscoverage['core/utils.js'][466] = 0; + _$jscoverage['core/utils.js'][495] = 0; + _$jscoverage['core/utils.js'][496] = 0; + _$jscoverage['core/utils.js'][522] = 0; + _$jscoverage['core/utils.js'][527] = 0; + _$jscoverage['core/utils.js'][528] = 0; + _$jscoverage['core/utils.js'][529] = 0; + _$jscoverage['core/utils.js'][575] = 0; + _$jscoverage['core/utils.js'][577] = 0; + _$jscoverage['core/utils.js'][578] = 0; + _$jscoverage['core/utils.js'][579] = 0; + _$jscoverage['core/utils.js'][580] = 0; + _$jscoverage['core/utils.js'][581] = 0; + _$jscoverage['core/utils.js'][585] = 0; + _$jscoverage['core/utils.js'][590] = 0; + _$jscoverage['core/utils.js'][591] = 0; + _$jscoverage['core/utils.js'][592] = 0; + _$jscoverage['core/utils.js'][593] = 0; + _$jscoverage['core/utils.js'][594] = 0; + _$jscoverage['core/utils.js'][596] = 0; + _$jscoverage['core/utils.js'][598] = 0; + _$jscoverage['core/utils.js'][600] = 0; + _$jscoverage['core/utils.js'][605] = 0; + _$jscoverage['core/utils.js'][606] = 0; + _$jscoverage['core/utils.js'][607] = 0; + _$jscoverage['core/utils.js'][608] = 0; + _$jscoverage['core/utils.js'][609] = 0; + _$jscoverage['core/utils.js'][611] = 0; + _$jscoverage['core/utils.js'][612] = 0; + _$jscoverage['core/utils.js'][614] = 0; + _$jscoverage['core/utils.js'][615] = 0; + _$jscoverage['core/utils.js'][617] = 0; + _$jscoverage['core/utils.js'][618] = 0; + _$jscoverage['core/utils.js'][619] = 0; + _$jscoverage['core/utils.js'][620] = 0; + _$jscoverage['core/utils.js'][622] = 0; + _$jscoverage['core/utils.js'][623] = 0; + _$jscoverage['core/utils.js'][624] = 0; + _$jscoverage['core/utils.js'][625] = 0; + _$jscoverage['core/utils.js'][626] = 0; + _$jscoverage['core/utils.js'][627] = 0; + _$jscoverage['core/utils.js'][628] = 0; + _$jscoverage['core/utils.js'][631] = 0; + _$jscoverage['core/utils.js'][634] = 0; + _$jscoverage['core/utils.js'][635] = 0; + _$jscoverage['core/utils.js'][637] = 0; + _$jscoverage['core/utils.js'][672] = 0; + _$jscoverage['core/utils.js'][673] = 0; + _$jscoverage['core/utils.js'][674] = 0; + _$jscoverage['core/utils.js'][675] = 0; + _$jscoverage['core/utils.js'][687] = 0; + _$jscoverage['core/utils.js'][688] = 0; + _$jscoverage['core/utils.js'][689] = 0; + _$jscoverage['core/utils.js'][690] = 0; + _$jscoverage['core/utils.js'][691] = 0; + _$jscoverage['core/utils.js'][692] = 0; + _$jscoverage['core/utils.js'][693] = 0; + _$jscoverage['core/utils.js'][694] = 0; + _$jscoverage['core/utils.js'][696] = 0; + _$jscoverage['core/utils.js'][698] = 0; + _$jscoverage['core/utils.js'][708] = 0; + _$jscoverage['core/utils.js'][709] = 0; + _$jscoverage['core/utils.js'][710] = 0; + _$jscoverage['core/utils.js'][711] = 0; + _$jscoverage['core/utils.js'][713] = 0; + _$jscoverage['core/utils.js'][714] = 0; + _$jscoverage['core/utils.js'][715] = 0; + _$jscoverage['core/utils.js'][717] = 0; + _$jscoverage['core/utils.js'][718] = 0; + _$jscoverage['core/utils.js'][719] = 0; + _$jscoverage['core/utils.js'][721] = 0; + _$jscoverage['core/utils.js'][724] = 0; + _$jscoverage['core/utils.js'][727] = 0; + _$jscoverage['core/utils.js'][728] = 0; + _$jscoverage['core/utils.js'][729] = 0; + _$jscoverage['core/utils.js'][731] = 0; + _$jscoverage['core/utils.js'][732] = 0; + _$jscoverage['core/utils.js'][733] = 0; + _$jscoverage['core/utils.js'][734] = 0; + _$jscoverage['core/utils.js'][737] = 0; + _$jscoverage['core/utils.js'][742] = 0; + _$jscoverage['core/utils.js'][745] = 0; + _$jscoverage['core/utils.js'][746] = 0; + _$jscoverage['core/utils.js'][748] = 0; + _$jscoverage['core/utils.js'][759] = 0; + _$jscoverage['core/utils.js'][760] = 0; + _$jscoverage['core/utils.js'][761] = 0; + _$jscoverage['core/utils.js'][762] = 0; + _$jscoverage['core/utils.js'][763] = 0; + _$jscoverage['core/utils.js'][764] = 0; + _$jscoverage['core/utils.js'][765] = 0; + _$jscoverage['core/utils.js'][766] = 0; + _$jscoverage['core/utils.js'][768] = 0; + _$jscoverage['core/utils.js'][772] = 0; + _$jscoverage['core/utils.js'][792] = 0; + _$jscoverage['core/utils.js'][793] = 0; + _$jscoverage['core/utils.js'][795] = 0; + _$jscoverage['core/utils.js'][796] = 0; + _$jscoverage['core/utils.js'][797] = 0; + _$jscoverage['core/utils.js'][798] = 0; + _$jscoverage['core/utils.js'][800] = 0; + _$jscoverage['core/utils.js'][802] = 0; + _$jscoverage['core/utils.js'][803] = 0; + _$jscoverage['core/utils.js'][805] = 0; + _$jscoverage['core/utils.js'][807] = 0; + _$jscoverage['core/utils.js'][828] = 0; + _$jscoverage['core/utils.js'][830] = 0; + _$jscoverage['core/utils.js'][832] = 0; + _$jscoverage['core/utils.js'][833] = 0; + _$jscoverage['core/utils.js'][837] = 0; + _$jscoverage['core/utils.js'][838] = 0; + _$jscoverage['core/utils.js'][839] = 0; + _$jscoverage['core/utils.js'][840] = 0; + _$jscoverage['core/utils.js'][841] = 0; + _$jscoverage['core/utils.js'][842] = 0; + _$jscoverage['core/utils.js'][844] = 0; + _$jscoverage['core/utils.js'][845] = 0; + _$jscoverage['core/utils.js'][846] = 0; + _$jscoverage['core/utils.js'][847] = 0; + _$jscoverage['core/utils.js'][848] = 0; + _$jscoverage['core/utils.js'][849] = 0; + _$jscoverage['core/utils.js'][851] = 0; + _$jscoverage['core/utils.js'][852] = 0; + _$jscoverage['core/utils.js'][854] = 0; + _$jscoverage['core/utils.js'][856] = 0; + _$jscoverage['core/utils.js'][857] = 0; + _$jscoverage['core/utils.js'][860] = 0; + _$jscoverage['core/utils.js'][861] = 0; + _$jscoverage['core/utils.js'][862] = 0; + _$jscoverage['core/utils.js'][864] = 0; + _$jscoverage['core/utils.js'][865] = 0; + _$jscoverage['core/utils.js'][883] = 0; + _$jscoverage['core/utils.js'][884] = 0; + _$jscoverage['core/utils.js'][885] = 0; + _$jscoverage['core/utils.js'][886] = 0; + _$jscoverage['core/utils.js'][888] = 0; + _$jscoverage['core/utils.js'][890] = 0; + _$jscoverage['core/utils.js'][891] = 0; + _$jscoverage['core/utils.js'][892] = 0; + _$jscoverage['core/utils.js'][893] = 0; + _$jscoverage['core/utils.js'][895] = 0; + _$jscoverage['core/utils.js'][896] = 0; + _$jscoverage['core/utils.js'][898] = 0; + _$jscoverage['core/utils.js'][900] = 0; + _$jscoverage['core/utils.js'][901] = 0; + _$jscoverage['core/utils.js'][903] = 0; + _$jscoverage['core/utils.js'][905] = 0; + _$jscoverage['core/utils.js'][906] = 0; + _$jscoverage['core/utils.js'][907] = 0; + _$jscoverage['core/utils.js'][908] = 0; + _$jscoverage['core/utils.js'][909] = 0; + _$jscoverage['core/utils.js'][911] = 0; + _$jscoverage['core/utils.js'][912] = 0; + _$jscoverage['core/utils.js'][913] = 0; + _$jscoverage['core/utils.js'][915] = 0; + _$jscoverage['core/utils.js'][916] = 0; + _$jscoverage['core/utils.js'][918] = 0; + _$jscoverage['core/utils.js'][919] = 0; + _$jscoverage['core/utils.js'][921] = 0; + _$jscoverage['core/utils.js'][925] = 0; + _$jscoverage['core/utils.js'][926] = 0; + _$jscoverage['core/utils.js'][927] = 0; + _$jscoverage['core/utils.js'][928] = 0; + _$jscoverage['core/utils.js'][929] = 0; + _$jscoverage['core/utils.js'][930] = 0; + _$jscoverage['core/utils.js'][931] = 0; + _$jscoverage['core/utils.js'][935] = 0; + _$jscoverage['core/utils.js'][980] = 0; + _$jscoverage['core/utils.js'][981] = 0; + _$jscoverage['core/utils.js'][982] = 0; +} +_$jscoverage['core/utils.js'].source = ["/**"," * 工具函数包"," * @file"," * @module UE.utils"," * @since 1.2.6.1"," */","","/**"," * UEditor封装使用的静态工具函数"," * @module UE.utils"," * @unfile"," */","","var utils = UE.utils ={",""," /**"," * 用给定的迭代器遍历对象"," * @method each"," * @param { Object } obj 需要遍历的对象"," * @param { Function } iterator 迭代器, 该方法接受两个参数, 第一个参数是当前所处理的value, 第二个参数是当前遍历对象的key"," * @example"," * ```javascript"," * var demoObj = {"," * key1: 1,"," * key2: 2"," * };"," *"," * //output: key1: 1, key2: 2"," * UE.utils.each( demoObj, funciton ( value, key ) {"," *"," * console.log( key + \":\" + value );"," *"," * } );"," * ```"," */",""," /**"," * 用给定的迭代器遍历数组或类数组对象"," * @method each"," * @param { Array } array 需要遍历的数组或者类数组"," * @param { Function } iterator 迭代器, 该方法接受两个参数, 第一个参数是当前所处理的value, 第二个参数是当前遍历对象的key"," * @example"," * ```javascript"," * var divs = document.getElmentByTagNames( \"div\" );"," *"," * //output: 0: DIV, 1: DIV ..."," * UE.utils.each( divs, funciton ( value, key ) {"," *"," * console.log( key + \":\" + value.tagName );"," *"," * } );"," * ```"," */"," each :function(obj, iterator, context){"," if(obj ==null)return;"," if(obj.length ===+obj.length){"," for(var i =0, l = obj.length; i < l; i++){"," if(iterator.call(context, obj[i], i, obj)===false)"," returnfalse;"," }"," }else{"," for(var key in obj){"," if(obj.hasOwnProperty(key)){"," if(iterator.call(context, obj[key], key, obj)===false)"," returnfalse;"," }"," }"," }"," },",""," /**"," * 以给定对象作为原型创建一个新对象"," * @method makeInstance"," * @param { Object } protoObject 该对象将作为新创建对象的原型"," * @return { Object } 新的对象, 该对象的原型是给定的protoObject对象"," * @example"," * ```javascript"," *"," * var protoObject = { sayHello: function () { console.log('Hello UEditor!'); } };"," *"," * var newObject = UE.utils.makeInstance( protoObject );"," * //output: Hello UEditor!"," * newObject.sayHello();"," * ```"," */"," makeInstance:function(obj){"," var noop =new Function();"," noop.prototype = obj;"," obj =new noop;"," noop.prototype =null;"," return obj;"," },",""," /**"," * 将source对象中的属性扩展到target对象上"," * @method extend"," * @remind 该方法将强制把source对象上的属性复制到target对象上"," * @see UE.utils.extend(Object,Object,Boolean)"," * @param { Object } target 目标对象, 新的属性将附加到该对象上"," * @param { Object } source 源对象, 该对象的属性会被附加到target对象上"," * @return { Object } 返回target对象"," * @example"," * ```javascript"," *"," * var target = { name: 'target', sex: 1 },"," * source = { name: 'source', age: 17 };"," *"," * UE.utils.extend( target, source );"," *"," * //output: { name: 'source', sex: 1, age: 17 }"," * console.log( target );"," *"," * ```"," */",""," /**"," * 将source对象中的属性扩展到target对象上, 根据指定的isKeepTarget值决定是否保留目标对象中与"," * 源对象属性名相同的属性值。"," * @method extend"," * @param { Object } target 目标对象, 新的属性将附加到该对象上"," * @param { Object } source 源对象, 该对象的属性会被附加到target对象上"," * @param { Boolean } isKeepTarget 是否保留目标对象中与源对象中属性名相同的属性"," * @return { Object } 返回target对象"," * @example"," * ```javascript"," *"," * var target = { name: 'target', sex: 1 },"," * source = { name: 'source', age: 17 };"," *"," * UE.utils.extend( target, source, true );"," *"," * //output: { name: 'target', sex: 1, age: 17 }"," * console.log( target );"," *"," * ```"," */"," extend:function(t, s, b){"," if(s){"," for(var k in s){"," if(!b ||!t.hasOwnProperty(k)){"," t[k]= s[k];"," }"," }"," }"," return t;"," },",""," /**"," * 将给定的多个对象的属性复制到目标对象target上"," * @method extend2"," * @remind 该方法将强制把源对象上的属性复制到target对象上"," * @remind 该方法支持两个及以上的参数, 从第二个参数开始, 其属性都会被复制到第一个参数上。 如果遇到同名的属性,"," * 将会覆盖掉之前的值。"," * @param { Object } target 目标对象, 新的属性将附加到该对象上"," * @param { Object... } source 源对象, 支持多个对象, 该对象的属性会被附加到target对象上"," * @return { Object } 返回target对象"," * @example"," * ```javascript"," *"," * var target = {},"," * source1 = { name: 'source', age: 17 },"," * source2 = { title: 'dev' };"," *"," * UE.utils.extend2( target, source1, source2 );"," *"," * //output: { name: 'source', age: 17, title: 'dev' }"," * console.log( target );"," *"," * ```"," */"," extend2:function(t){"," var a = arguments;"," for(var i =1; i < a.length; i++){"," var x = a[i];"," for(var k in x){"," if(!t.hasOwnProperty(k)){"," t[k]= x[k];"," }"," }"," }"," return t;"," },",""," /**"," * 模拟继承机制, 使得subClass继承自superClass"," * @method inherits"," * @param { Object } subClass 子类对象"," * @param { Object } superClass 超类对象"," * @warning 该方法只能让subClass继承超类的原型, subClass对象自身的属性和方法不会被继承"," * @return { Object } 继承superClass后的子类对象"," * @example"," * ```javascript"," * function SuperClass(){"," * this.name = \"小李\";"," * }"," *"," * SuperClass.prototype = {"," * hello:function(str){"," * console.log(this.name + str);"," * }"," * }"," *"," * function SubClass(){"," * this.name = \"小张\";"," * }"," *"," * UE.utils.inherits(SubClass,SuperClass);"," *"," * var sub = new SubClass();"," * //output: '小张早上好!"," * sub.hello(\"早上好!\");"," * ```"," */"," inherits:function(subClass, superClass){"," var oldP = subClass.prototype,"," newP = utils.makeInstance(superClass.prototype);"," utils.extend(newP, oldP,true);"," subClass.prototype = newP;"," return(newP.constructor = subClass);"," },",""," /**"," * 用指定的context对象作为函数fn的上下文"," * @method bind"," * @param { Function } fn 需要绑定上下文的函数对象"," * @param { Object } content 函数fn新的上下文对象"," * @return { Function } 一个新的函数, 该函数作为原始函数fn的代理, 将完成fn的上下文调换工作。"," * @example"," * ```javascript"," *"," * var name = 'window',"," * newTest = null;"," *"," * function test () {"," * console.log( this.name );"," * }"," *"," * newTest = UE.utils.bind( test, { name: 'object' } );"," *"," * //output: object"," * newTest();"," *"," * //output: window"," * test();"," *"," * ```"," */"," bind:function(fn, context){"," returnfunction(){"," return fn.apply(context, arguments);"," };"," },",""," /**"," * 创建延迟指定时间后执行的函数fn"," * @method defer"," * @param { Function } fn 需要延迟执行的函数对象"," * @param { int } delay 延迟的时间, 单位是毫秒"," * @warning 该方法的时间控制是不精确的,仅仅只能保证函数的执行是在给定的时间之后,"," * 而不能保证刚好到达延迟时间时执行。"," * @return { Function } 目标函数fn的代理函数, 只有执行该函数才能起到延时效果"," * @example"," * ```javascript"," * var start = 0;"," *"," * function test(){"," * console.log( new Date() - start );"," * }"," *"," * var testDefer = UE.utils.defer( test, 1000 );"," * //"," * start = new Date();"," * //output: (大约在1000毫秒之后输出) 1000"," * testDefer();"," * ```"," */",""," /**"," * 创建延迟指定时间后执行的函数fn, 如果在延迟时间内再次执行该方法, 将会根据指定的exclusion的值,"," * 决定是否取消前一次函数的执行, 如果exclusion的值为true, 则取消执行,反之,将继续执行前一个方法。"," * @method defer"," * @param { Function } fn 需要延迟执行的函数对象"," * @param { int } delay 延迟的时间, 单位是毫秒"," * @param { Boolean } exclusion 如果在延迟时间内再次执行该函数,该值将决定是否取消执行前一次函数的执行,"," * 值为true表示取消执行, 反之则将在执行前一次函数之后才执行本次函数调用。"," * @warning 该方法的时间控制是不精确的,仅仅只能保证函数的执行是在给定的时间之后,"," * 而不能保证刚好到达延迟时间时执行。"," * @return { Function } 目标函数fn的代理函数, 只有执行该函数才能起到延时效果"," * @example"," * ```javascript"," *"," * function test(){"," * console.log(1);"," * }"," *"," * var testDefer = UE.utils.defer( test, 1000, true );"," *"," * //output: (两次调用仅有一次输出) 1"," * testDefer();"," * testDefer();"," * ```"," */"," defer:function(fn, delay, exclusion){"," var timerID;"," returnfunction(){"," if(exclusion){"," clearTimeout(timerID);"," }"," timerID = setTimeout(fn, delay);"," };"," },",""," /**"," * 获取元素item在数组array中首次出现的位置, 如果未找到item, 则返回-1"," * @method indexOf"," * @remind 该方法的匹配过程使用的是恒等“===”"," * @param { Array } array 需要查找的数组对象"," * @param { * } item 需要在目标数组中查找的值"," * @return { int } 返回item在目标数组array中首次出现的位置, 如果在数组中未找到item, 则返回-1"," * @example"," * ```javascript"," * var item = 1,"," * arr = [ 3, 4, 6, 8, 1, 1, 2 ];"," *"," * //output: 4"," * console.log( UE.utils.indexOf( arr, item ) );"," * ```"," */",""," /**"," * 获取元素item数组array中首次出现的位置, 如果未找到item, 则返回-1。通过start的值可以指定搜索的起始位置。"," * @method indexOf"," * @remind 该方法的匹配过程使用的是恒等“===”"," * @param { Array } array 需要查找的数组对象"," * @param { * } item 需要在目标数组中查找的值"," * @param { int } start 搜索的起始位置"," * @return { int } 返回item在目标数组array中的start位置之后首次出现的位置, 如果在数组中未找到item, 则返回-1"," * @example"," * ```javascript"," * var item = 1,"," * arr = [ 3, 4, 6, 8, 1, 2, 8, 3, 2, 1, 1, 4 ];"," *"," * //output: 9"," * console.log( UE.utils.indexOf( arr, item, 5 ) );"," * ```"," */"," indexOf:function(array, item, start){"," var index =-1;"," start =this.isNumber(start)? start :0;"," this.each(array,function(v, i){"," if(i >= start && v === item){"," index = i;"," returnfalse;"," }"," });"," return index;"," },",""," /**"," * 移除数组array中所有的元素item"," * @method removeItem"," * @param { Array } array 要移除元素的目标数组"," * @param { * } item 将要被移除的元素"," * @remind 该方法的匹配过程使用的是恒等“===”"," * @example"," * ```javascript"," * var arr = [ 4, 5, 7, 1, 3, 4, 6 ];"," *"," * UE.utils.removeItem( arr, 4 );"," * //output: [ 5, 7, 1, 3, 6 ]"," * console.log( arr );"," *"," * ```"," */"," removeItem:function(array, item){"," for(var i =0, l = array.length; i < l; i++){"," if(array[i]=== item){"," array.splice(i,1);"," i--;"," }"," }"," },",""," /**"," * 删除字符串str的首尾空格"," * @method trim"," * @param { String } str 需要删除首尾空格的字符串"," * @return { String } 删除了首尾的空格后的字符串"," * @example"," * ```javascript"," *"," * var str = \" UEdtior \";"," *"," * //output: 9"," * console.log( str.length );"," *"," * //output: 7"," * console.log( UE.utils.trim( \" UEdtior \" ).length );"," *"," * //output: 9"," * console.log( str.length );"," *"," * ```"," */"," trim:function(str){"," return str.replace(/(^[ \\t\\n\\r]+)|([ \\t\\n\\r]+$)/g,'');"," },",""," /**"," * 将字符串str以','分隔成数组后,将该数组转换成哈希对象, 其生成的hash对象的key为数组中的元素, value为1"," * @method listToMap"," * @warning 该方法在生成的hash对象中,会为每一个key同时生成一个另一个全大写的key。"," * @param { String } str 该字符串将被以','分割为数组, 然后进行转化"," * @return { Object } 转化之后的hash对象"," * @example"," * ```javascript"," *"," * //output: Object {UEdtior: 1, UEDTIOR: 1, Hello: 1, HELLO: 1}"," * console.log( UE.utils.listToMap( 'UEdtior,Hello' ) );"," *"," * ```"," */",""," /**"," * 将字符串数组转换成哈希对象, 其生成的hash对象的key为数组中的元素, value为1"," * @method listToMap"," * @warning 该方法在生成的hash对象中,会为每一个key同时生成一个另一个全大写的key。"," * @param { Array } arr 字符串数组"," * @return { Object } 转化之后的hash对象"," * @example"," * ```javascript"," *"," * //output: Object {UEdtior: 1, UEDTIOR: 1, Hello: 1, HELLO: 1}"," * console.log( UE.utils.listToMap( [ 'UEdtior', 'Hello' ] ) );"," *"," * ```"," */"," listToMap:function(list){"," if(!list)return{};"," list = utils.isArray(list)? list : list.split(',');"," for(var i =0, ci, obj ={}; ci = list[i++];){"," obj[ci.toUpperCase()]= obj[ci]=1;"," }"," return obj;"," },",""," /**"," * 将str中的html符号转义,将转义“',&,<,\",>”五个字符"," * @method unhtml"," * @param { String } str 需要转义的字符串"," * @return { String } 转义后的字符串"," * @example"," * ```javascript"," * var html = '<body>&</body>';"," *"," * //output: &lt;body&gt;&amp;&lt;/body&gt;"," * console.log( UE.utils.unhtml( html ) );"," *"," * ```"," */"," unhtml:function(str, reg){"," return str ? str.replace(reg ||/[&<\">'](?:(amp|lt|quot|gt|#39|nbsp);)?/g,function(a, b){"," if(b){"," return a;"," }else{"," return{"," '<':'&lt;',"," '&':'&amp;',"," '\"':'&quot;',"," '>':'&gt;',"," \"'\":'&#39;'"," }[a]"," }",""," }):'';"," },",""," /**"," * 将str中的转义字符还原成html字符"," * @see UE.utils.unhtml(String);"," * @method html"," * @param { String } str 需要逆转义的字符串"," * @return { String } 逆转义后的字符串"," * @example"," * ```javascript"," *"," * var str = '&lt;body&gt;&amp;&lt;/body&gt;';"," *"," * //output: <body>&</body>"," * console.log( UE.utils.html( str ) );"," *"," * ```"," */"," html:function(str){"," return str ? str.replace(/&((g|l|quo)t|amp|#39);/g,function(m){"," return{"," '&lt;':'<',"," '&amp;':'&',"," '&quot;':'\"',"," '&gt;':'>',"," '&#39;':\"'\""," }[m]"," }):'';"," },",""," /**"," * 将css样式转换为驼峰的形式"," * @method cssStyleToDomStyle"," * @param { String } cssName 需要转换的css样式名"," * @return { String } 转换成驼峰形式后的css样式名"," * @example"," * ```javascript"," *"," * var str = 'border-top';"," *"," * //output: borderTop"," * console.log( UE.utils.cssStyleToDomStyle( str ) );"," *"," * ```"," */"," cssStyleToDomStyle:function(){"," var test = document.createElement('div').style,"," cache ={"," 'float':test.cssFloat != undefined ?'cssFloat': test.styleFloat != undefined ?'styleFloat':'float'"," };",""," returnfunction(cssName){"," return cache[cssName]||(cache[cssName]= cssName.toLowerCase().replace(/-./g,function(match){"," return match.charAt(1).toUpperCase();"," }));"," };"," }(),",""," /**"," * 动态加载文件到doc中"," * @method loadFile"," * @param { DomDocument } document 需要加载资源文件的文档对象"," * @param { KeyValueMap } options 加载资源文件的属性集合, 取值请参考代码示例"," * @example"," * ```javascript"," *"," * UE.utils.loadFile( document, {"," * src:\"test.js\","," * tag:\"script\","," * type:\"text/javascript\","," * defer:\"defer\""," * } );"," *"," * ```"," */",""," /**"," * 动态加载文件到doc中,加载成功后执行的回调函数fn"," * @method loadFile"," * @param { DomDocument } document 需要加载资源文件的文档对象"," * @param { KeyValueMap } options 加载资源文件的属性集合, 该集合支持的值是script标签和style标签支持的所有属性。"," * @param { Function } fn 资源文件加载成功之后执行的回调"," * @warning 对于在同一个文档中多次加载同一URL的文件, 该方法会在第一次加载之后缓存该请求,"," * 在此之后的所有同一URL的请求, 将会直接出发回调。"," * @example"," * ```javascript"," *"," * UE.utils.loadFile( document, {"," * src:\"test.js\","," * tag:\"script\","," * type:\"text/javascript\","," * defer:\"defer\""," * }, function () {"," * console.log('加载成功');"," * } );"," *"," * ```"," */"," loadFile:function(){"," var tmpList =[];",""," function getItem(doc, obj){"," try{"," for(var i =0, ci; ci = tmpList[i++];){"," if(ci.doc === doc && ci.url ==(obj.src || obj.href)){"," return ci;"," }"," }"," }catch(e){"," returnnull;"," }",""," }",""," returnfunction(doc, obj, fn){"," var item = getItem(doc, obj);"," if(item){"," if(item.ready){"," fn && fn();"," }else{"," item.funs.push(fn)"," }"," return;"," }"," tmpList.push({"," doc:doc,"," url:obj.src || obj.href,"," funs:[fn]"," });"," if(!doc.body){"," var html =[];"," for(var p in obj){"," if(p =='tag')continue;"," html.push(p +'=\"'+ obj[p]+'\"')"," }"," doc.write('<'+ obj.tag +' '+ html.join(' ')+' ></'+ obj.tag +'>');"," return;"," }"," if(obj.id && doc.getElementById(obj.id)){"," return;"," }"," var element = doc.createElement(obj.tag);"," delete obj.tag;"," for(var p in obj){"," element.setAttribute(p, obj[p]);"," }"," element.onload = element.onreadystatechange =function(){"," if(!this.readyState ||/loaded|complete/.test(this.readyState)){"," item = getItem(doc, obj);"," if(item.funs.length >0){"," item.ready =1;"," for(var fi; fi = item.funs.pop();){"," fi();"," }"," }"," element.onload = element.onreadystatechange =null;"," }"," };"," element.onerror =function(){"," throw Error('The load '+(obj.href || obj.src)+' fails,check the url settings of file ueditor.config.js ')"," };"," doc.getElementsByTagName(\"head\")[0].appendChild(element);"," }"," }(),",""," /**"," * 判断obj对象是否为空"," * @method isEmptyObject"," * @param { * } obj 需要判断的对象"," * @remind 如果判断的对象是NULL, 将直接返回true, 如果是数组且为空, 返回true, 如果是字符串, 且字符串为空,"," * 返回true, 如果是普通对象, 且该对象没有任何实例属性, 返回true"," * @return { Boolean } 对象是否为空"," * @example"," * ```javascript"," *"," * //output: true"," * console.log( UE.utils.isEmptyObject( {} ) );"," *"," * //output: true"," * console.log( UE.utils.isEmptyObject( [] ) );"," *"," * //output: true"," * console.log( UE.utils.isEmptyObject( \"\" ) );"," *"," * //output: false"," * console.log( UE.utils.isEmptyObject( { key: 1 } ) );"," *"," * //output: false"," * console.log( UE.utils.isEmptyObject( [1] ) );"," *"," * //output: false"," * console.log( UE.utils.isEmptyObject( \"1\" ) );"," *"," * ```"," */"," isEmptyObject:function(obj){"," if(obj ==null)returntrue;"," if(this.isArray(obj)||this.isString(obj))return obj.length ===0;"," for(var key in obj)if(obj.hasOwnProperty(key))returnfalse;"," returntrue;"," },",""," /*"," * 把rgb格式的颜色值转换成16进制格式"," * @method fixColor"," * @param { String } rgb格式的颜色值"," * @param { String }"," * @example"," * rgb(255,255,255) => \"#ffffff\""," */"," fixColor:function(name, value){"," if(/color/i.test(name)&&/rgba?/.test(value)){"," var array = value.split(\",\");"," if(array.length >3)"," return\"\";"," value =\"#\";"," for(var i =0, color; color = array[i++];){"," color = parseInt(color.replace(/[^\\d]/gi,''),10).toString(16);"," value += color.length ==1?\"0\"+ color : color;"," }"," value = value.toUpperCase();"," }"," return value;"," },",""," /*"," * 只针对border,padding,margin做了处理,因为性能问题"," * @public"," * @function"," * @param {String} val style字符串"," */"," optCss:function(val){"," var padding, margin, border;"," val = val.replace(/(padding|margin|border)\\-([^:]+):([^;]+);?/gi,function(str, key, name, val){"," if(val.split(' ').length ==1){"," switch(key){"," case'padding':"," !padding &&(padding ={});"," padding[name]= val;"," return'';"," case'margin':"," !margin &&(margin ={});"," margin[name]= val;"," return'';"," case'border':"," return val =='initial'?'': str;"," }"," }"," return str;"," });",""," function opt(obj, name){"," if(!obj){"," return'';"," }"," var t = obj.top , b = obj.bottom, l = obj.left, r = obj.right, val ='';"," if(!t ||!l ||!b ||!r){"," for(var p in obj){"," val +=';'+ name +'-'+ p +':'+ obj[p]+';';"," }"," }else{"," val +=';'+ name +':'+"," (t == b && b == l && l == r ? t :"," t == b && l == r ?(t +' '+ l):"," l == r ?(t +' '+ l +' '+ b):(t +' '+ r +' '+ b +' '+ l))+';'"," }"," return val;"," }",""," val += opt(padding,'padding')+ opt(margin,'margin');"," return val.replace(/^[ \\n\\r\\t;]*|[ \\n\\r\\t]*$/,'').replace(/;([ \\n\\r\\t]+)|\\1;/g,';')"," .replace(/(&((l|g)t|quot|#39))?;{2,}/g,function(a, b){"," return b ? b +\";;\":';'"," });"," },",""," /*"," * 深度克隆对象,从source到target"," * @method clone"," * @grammar UE.utils.clone(source) => anthorObj 新的对象是完整的source的副本"," * @grammar UE.utils.clone(source,target) => target包含了source的所有内容,重名会覆盖"," */"," clone:function(source, target){"," var tmp;"," target = target ||{};"," for(var i in source){"," if(source.hasOwnProperty(i)){"," tmp = source[i];"," if(typeof tmp =='object'){"," target[i]= utils.isArray(tmp)?[]:{};"," utils.clone(source[i], target[i])"," }else{"," target[i]= tmp;"," }"," }"," }"," return target;"," },",""," /**"," * 把cm/pt为单位的值转换为px为单位的值"," * @method transUnitToPx"," * @param { String } 待转换的带单位的字符串"," * @return { String } 转换为px为计量单位的值的字符串"," * @example"," * ```javascript"," *"," * //output: 500px"," * console.log( UE.utils.transUnitToPx( '20cm' ) );"," *"," * //output: 27px"," * console.log( UE.utils.transUnitToPx( '20pt' ) );"," *"," * ```"," */"," transUnitToPx:function(val){"," if(!/(pt|cm)/.test(val)){"," return val"," }"," var unit;"," val.replace(/([\\d.]+)(\\w+)/,function(str, v, u){"," val = v;"," unit = u;"," });"," switch(unit){"," case'cm':"," val = parseFloat(val)*25;"," break;"," case'pt':"," val = Math.round(parseFloat(val)*96/72);"," }"," return val +(val ?'px':'');"," },",""," /**"," * 在dom树ready之后执行给定的回调函数"," * @method domReady"," * @remind 如果在执行该方法的时候, dom树已经ready, 那么回调函数将立刻执行"," * @param { Function } fn dom树ready之后的回调函数"," * @example"," * ```javascript"," *"," * UE.utils.domReady( function () {"," *"," * console.log('123');"," *"," * } );"," *"," * ```"," */"," domReady:function(){",""," var fnArr =[];",""," function doReady(doc){"," //确保onready只执行一次"," doc.isReady =true;"," for(var ci; ci = fnArr.pop(); ci()){"," }"," }",""," returnfunction(onready, win){"," win = win || window;"," var doc = win.document;"," onready && fnArr.push(onready);"," if(doc.readyState ===\"complete\"){"," doReady(doc);"," }else{"," doc.isReady && doReady(doc);"," if(browser.ie){"," (function(){"," if(doc.isReady)return;"," try{"," doc.documentElement.doScroll(\"left\");"," }catch(error){"," setTimeout(arguments.callee,0);"," return;"," }"," doReady(doc);"," })();"," win.attachEvent('onload',function(){"," doReady(doc)"," });"," }else{"," doc.addEventListener(\"DOMContentLoaded\",function(){"," doc.removeEventListener(\"DOMContentLoaded\", arguments.callee,false);"," doReady(doc);"," },false);"," win.addEventListener('load',function(){"," doReady(doc)"," },false);"," }"," }",""," }"," }(),",""," /*"," * 动态添加css样式"," * @method cssRule"," * @param { String } 节点名称"," * @grammar UE.utils.cssRule('添加的样式的节点名称',['样式','放到哪个document上'])"," * @grammar UE.utils.cssRule('body','body{background:#ccc}') => null //给body添加背景颜色"," * @grammar UE.utils.cssRule('body') =>样式的字符串 //取得key值为body的样式的内容,如果没有找到key值先关的样式将返回空,例如刚才那个背景颜色,将返回 body{background:#ccc}"," * @grammar UE.utils.cssRule('body','') =>null //清空给定的key值的背景颜色"," */"," cssRule:browser.ie ?function(key, style, doc){"," var indexList, index;"," doc = doc || document;"," if(doc.indexList){"," indexList = doc.indexList;"," }else{"," indexList = doc.indexList ={};"," }"," var sheetStyle;"," if(!indexList[key]){"," if(style === undefined){"," return''"," }"," sheetStyle = doc.createStyleSheet('', index = doc.styleSheets.length);"," indexList[key]= index;"," }else{"," sheetStyle = doc.styleSheets[indexList[key]];"," }"," if(style === undefined){"," return sheetStyle.cssText"," }"," sheetStyle.cssText = style ||''"," }:function(key, style, doc){"," doc = doc || document;"," var head = doc.getElementsByTagName('head')[0], node;"," if(!(node = doc.getElementById(key))){"," if(style === undefined){"," return''"," }"," node = doc.createElement('style');"," node.id = key;"," head.appendChild(node)"," }"," if(style === undefined){"," return node.innerHTML"," }"," if(style !==''){"," node.innerHTML = style;"," }else{"," head.removeChild(node)"," }"," },"," sort:function(array,compareFn){"," compareFn = compareFn ||function(item1, item2){return item1.localeCompare(item2);};"," for(var i=0,len = array.length; i<len; i++){"," for(var j = i,length = array.length; j<length; j++){"," if(compareFn(array[i], array[j])>0){"," var t = array[i];"," array[i]= array[j];"," array[j]= t;"," }"," }"," }"," return array;"," }","","};","/**"," * 判断给定的对象是否是字符串"," * @method isString"," * @param { * } object 需要判断的对象"," * @return { Boolean } 给定的对象是否是字符串"," */","","/**"," * 判断给定的对象是否是数组"," * @method isArray"," * @param { * } object 需要判断的对象"," * @return { Boolean } 给定的对象是否是数组"," */","","/**"," * 判断给定的对象是否是一个Function"," * @method isFunction"," * @param { * } object 需要判断的对象"," * @return { Boolean } 给定的对象是否是Function"," */","","/**"," * 判断给定的对象是否是Number"," * @method isNumber"," * @param { * } object 需要判断的对象"," * @return { Boolean } 给定的对象是否是Number"," */","","/**"," * 判断给定的对象是否是一个正则表达式"," * @method isRegExp"," * @param { * } object 需要判断的对象"," * @return { Boolean } 给定的对象是否是正则表达式"," */","","/**"," * 判断给定的对象是否是一个普通对象"," * @method isObject"," * @param { * } object 需要判断的对象"," * @return { Boolean } 给定的对象是否是普通对象"," */","utils.each(['String','Function','Array','Number','RegExp','Object'],function(v){"," UE.utils['is'+ v]=function(obj){"," return Object.prototype.toString.apply(obj)=='[object '+ v +']';"," }","});"]; +_$jscoverage['core/utils.js'][14]++; +var utils = (UE.utils = {each: (function (obj, iterator, context) { + _$jscoverage['core/utils.js'][55]++; + if ((obj == null)) { + _$jscoverage['core/utils.js'][55]++; + return; + } + _$jscoverage['core/utils.js'][56]++; + if ((obj.length === (+ obj.length))) { + _$jscoverage['core/utils.js'][57]++; + for (var i = 0, l = obj.length; (i < l); (i++)) { + _$jscoverage['core/utils.js'][58]++; + if ((iterator.call(context, obj[i], i, obj) === false)) { + _$jscoverage['core/utils.js'][59]++; + return false; + } +} + } + else { + _$jscoverage['core/utils.js'][62]++; + for (var key in obj) { + _$jscoverage['core/utils.js'][63]++; + if (obj.hasOwnProperty(key)) { + _$jscoverage['core/utils.js'][64]++; + if ((iterator.call(context, obj[key], key, obj) === false)) { + _$jscoverage['core/utils.js'][65]++; + return false; + } + } +} + } +}), makeInstance: (function (obj) { + _$jscoverage['core/utils.js'][87]++; + var noop = new Function(); + _$jscoverage['core/utils.js'][88]++; + noop.prototype = obj; + _$jscoverage['core/utils.js'][89]++; + obj = new noop(); + _$jscoverage['core/utils.js'][90]++; + noop.prototype = null; + _$jscoverage['core/utils.js'][91]++; + return obj; +}), extend: (function (t, s, b) { + _$jscoverage['core/utils.js'][138]++; + if (s) { + _$jscoverage['core/utils.js'][139]++; + for (var k in s) { + _$jscoverage['core/utils.js'][140]++; + if (((! b) || (! t.hasOwnProperty(k)))) { + _$jscoverage['core/utils.js'][141]++; + t[k] = s[k]; + } +} + } + _$jscoverage['core/utils.js'][145]++; + return t; +}), extend2: (function (t) { + _$jscoverage['core/utils.js'][172]++; + var a = arguments; + _$jscoverage['core/utils.js'][173]++; + for (var i = 1; (i < a.length); (i++)) { + _$jscoverage['core/utils.js'][174]++; + var x = a[i]; + _$jscoverage['core/utils.js'][175]++; + for (var k in x) { + _$jscoverage['core/utils.js'][176]++; + if ((! t.hasOwnProperty(k))) { + _$jscoverage['core/utils.js'][177]++; + t[k] = x[k]; + } +} +} + _$jscoverage['core/utils.js'][181]++; + return t; +}), inherits: (function (subClass, superClass) { + _$jscoverage['core/utils.js'][215]++; + var oldP = subClass.prototype, newP = utils.makeInstance(superClass.prototype); + _$jscoverage['core/utils.js'][217]++; + utils.extend(newP, oldP, true); + _$jscoverage['core/utils.js'][218]++; + subClass.prototype = newP; + _$jscoverage['core/utils.js'][219]++; + return (newP.constructor = subClass); +}), bind: (function (fn, context) { + _$jscoverage['core/utils.js'][249]++; + return (function () { + _$jscoverage['core/utils.js'][250]++; + return fn.apply(context, arguments); +}); +}), defer: (function (fn, delay, exclusion) { + _$jscoverage['core/utils.js'][304]++; + var timerID; + _$jscoverage['core/utils.js'][305]++; + return (function () { + _$jscoverage['core/utils.js'][306]++; + if (exclusion) { + _$jscoverage['core/utils.js'][307]++; + clearTimeout(timerID); + } + _$jscoverage['core/utils.js'][309]++; + timerID = setTimeout(fn, delay); +}); +}), indexOf: (function (array, item, start) { + _$jscoverage['core/utils.js'][348]++; + var index = -1; + _$jscoverage['core/utils.js'][349]++; + start = (this.isNumber(start)? start: 0); + _$jscoverage['core/utils.js'][350]++; + this.each(array, (function (v, i) { + _$jscoverage['core/utils.js'][351]++; + if (((i >= start) && (v === item))) { + _$jscoverage['core/utils.js'][352]++; + index = i; + _$jscoverage['core/utils.js'][353]++; + return false; + } +})); + _$jscoverage['core/utils.js'][356]++; + return index; +}), removeItem: (function (array, item) { + _$jscoverage['core/utils.js'][376]++; + for (var i = 0, l = array.length; (i < l); (i++)) { + _$jscoverage['core/utils.js'][377]++; + if ((array[i] === item)) { + _$jscoverage['core/utils.js'][378]++; + array.splice(i, 1); + _$jscoverage['core/utils.js'][379]++; + (i--); + } +} +}), trim: (function (str) { + _$jscoverage['core/utils.js'][406]++; + return str.replace(/(^[ \t\n\r]+)|([ \t\n\r]+$)/g, ""); +}), listToMap: (function (list) { + _$jscoverage['core/utils.js'][439]++; + if ((! list)) { + _$jscoverage['core/utils.js'][439]++; + return ({}); + } + _$jscoverage['core/utils.js'][440]++; + list = (utils.isArray(list)? list: list.split(",")); + _$jscoverage['core/utils.js'][441]++; + for (var i = 0, ci, obj = {}; (ci = list[(i++)]);) { + _$jscoverage['core/utils.js'][442]++; + obj[ci.toUpperCase()] = (obj[ci] = 1); +} + _$jscoverage['core/utils.js'][444]++; + return obj; +}), unhtml: (function (str, reg) { + _$jscoverage['core/utils.js'][462]++; + return (str? str.replace((reg || /[&<">'](?:(amp|lt|quot|gt|#39|nbsp);)?/g), (function (a, b) { + _$jscoverage['core/utils.js'][463]++; + if (b) { + _$jscoverage['core/utils.js'][464]++; + return a; + } + else { + _$jscoverage['core/utils.js'][466]++; + return {"<": "<", "&": "&", "\"": """, ">": ">", "'": "'"}[a]; + } +})): ""); +}), html: (function (str) { + _$jscoverage['core/utils.js'][495]++; + return (str? str.replace(/&((g|l|quo)t|amp|#39);/g, (function (m) { + _$jscoverage['core/utils.js'][496]++; + return {"<": "<", "&": "&", """: "\"", ">": ">", "'": "'"}[m]; +})): ""); +}), cssStyleToDomStyle: (function () { + _$jscoverage['core/utils.js'][522]++; + var test = document.createElement("div").style, cache = {"float": ((test.cssFloat != undefined)? "cssFloat": ((test.styleFloat != undefined)? "styleFloat": "float"))}; + _$jscoverage['core/utils.js'][527]++; + return (function (cssName) { + _$jscoverage['core/utils.js'][528]++; + return (cache[cssName] || (cache[cssName] = cssName.toLowerCase().replace(/-./g, (function (match) { + _$jscoverage['core/utils.js'][529]++; + return match.charAt(1).toUpperCase(); +})))); +}); +})(), loadFile: (function () { + _$jscoverage['core/utils.js'][575]++; + var tmpList = []; + _$jscoverage['core/utils.js'][577]++; + function getItem(doc, obj) { + _$jscoverage['core/utils.js'][578]++; + try { + _$jscoverage['core/utils.js'][579]++; + for (var i = 0, ci; (ci = tmpList[(i++)]);) { + _$jscoverage['core/utils.js'][580]++; + if (((ci.doc === doc) && (ci.url == (obj.src || obj.href)))) { + _$jscoverage['core/utils.js'][581]++; + return ci; + } +} + } + catch (e) { + _$jscoverage['core/utils.js'][585]++; + return null; + } +} + _$jscoverage['core/utils.js'][590]++; + return (function (doc, obj, fn) { + _$jscoverage['core/utils.js'][591]++; + var item = getItem(doc, obj); + _$jscoverage['core/utils.js'][592]++; + if (item) { + _$jscoverage['core/utils.js'][593]++; + if (item.ready) { + _$jscoverage['core/utils.js'][594]++; + (fn && fn()); + } + else { + _$jscoverage['core/utils.js'][596]++; + item.funs.push(fn); + } + _$jscoverage['core/utils.js'][598]++; + return; + } + _$jscoverage['core/utils.js'][600]++; + tmpList.push({doc: doc, url: (obj.src || obj.href), funs: [fn]}); + _$jscoverage['core/utils.js'][605]++; + if ((! doc.body)) { + _$jscoverage['core/utils.js'][606]++; + var html = []; + _$jscoverage['core/utils.js'][607]++; + for (var p in obj) { + _$jscoverage['core/utils.js'][608]++; + if ((p == "tag")) { + _$jscoverage['core/utils.js'][608]++; + continue; + } + _$jscoverage['core/utils.js'][609]++; + html.push((p + "=\"" + obj[p] + "\"")); +} + _$jscoverage['core/utils.js'][611]++; + doc.write(("<" + obj.tag + " " + html.join(" ") + " >")); + _$jscoverage['core/utils.js'][612]++; + return; + } + _$jscoverage['core/utils.js'][614]++; + if ((obj.id && doc.getElementById(obj.id))) { + _$jscoverage['core/utils.js'][615]++; + return; + } + _$jscoverage['core/utils.js'][617]++; + var element = doc.createElement(obj.tag); + _$jscoverage['core/utils.js'][618]++; + (delete obj.tag); + _$jscoverage['core/utils.js'][619]++; + for (var p = p in obj) { + _$jscoverage['core/utils.js'][620]++; + element.setAttribute(p, obj[p]); +} + _$jscoverage['core/utils.js'][622]++; + element.onload = (element.onreadystatechange = (function () { + _$jscoverage['core/utils.js'][623]++; + if (((! this.readyState) || /loaded|complete/.test(this.readyState))) { + _$jscoverage['core/utils.js'][624]++; + item = getItem(doc, obj); + _$jscoverage['core/utils.js'][625]++; + if ((item.funs.length > 0)) { + _$jscoverage['core/utils.js'][626]++; + item.ready = 1; + _$jscoverage['core/utils.js'][627]++; + for (var fi; (fi = item.funs.pop());) { + _$jscoverage['core/utils.js'][628]++; + fi(); +} + } + _$jscoverage['core/utils.js'][631]++; + element.onload = (element.onreadystatechange = null); + } +})); + _$jscoverage['core/utils.js'][634]++; + element.onerror = (function () { + _$jscoverage['core/utils.js'][635]++; + throw Error(("The load " + (obj.href || obj.src) + " fails,check the url settings of file ueditor.config.js ")); +}); + _$jscoverage['core/utils.js'][637]++; + doc.getElementsByTagName("head")[0].appendChild(element); +}); +})(), isEmptyObject: (function (obj) { + _$jscoverage['core/utils.js'][672]++; + if ((obj == null)) { + _$jscoverage['core/utils.js'][672]++; + return true; + } + _$jscoverage['core/utils.js'][673]++; + if ((this.isArray(obj) || this.isString(obj))) { + _$jscoverage['core/utils.js'][673]++; + return (obj.length === 0); + } + _$jscoverage['core/utils.js'][674]++; + for (var key in obj) { + _$jscoverage['core/utils.js'][674]++; + if (obj.hasOwnProperty(key)) { + _$jscoverage['core/utils.js'][674]++; + return false; + } +} + _$jscoverage['core/utils.js'][675]++; + return true; +}), fixColor: (function (name, value) { + _$jscoverage['core/utils.js'][687]++; + if ((/color/i.test(name) && /rgba?/.test(value))) { + _$jscoverage['core/utils.js'][688]++; + var array = value.split(","); + _$jscoverage['core/utils.js'][689]++; + if ((array.length > 3)) { + _$jscoverage['core/utils.js'][690]++; + return ""; + } + _$jscoverage['core/utils.js'][691]++; + value = "#"; + _$jscoverage['core/utils.js'][692]++; + for (var i = 0, color; (color = array[(i++)]);) { + _$jscoverage['core/utils.js'][693]++; + color = parseInt(color.replace(/[^\d]/gi, ""), 10).toString(16); + _$jscoverage['core/utils.js'][694]++; + value += ((color.length == 1)? ("0" + color): color); +} + _$jscoverage['core/utils.js'][696]++; + value = value.toUpperCase(); + } + _$jscoverage['core/utils.js'][698]++; + return value; +}), optCss: (function (val) { + _$jscoverage['core/utils.js'][708]++; + var padding, margin, border; + _$jscoverage['core/utils.js'][709]++; + val = val.replace(/(padding|margin|border)\-([^:]+):([^;]+);?/gi, (function (str, key, name, val) { + _$jscoverage['core/utils.js'][710]++; + if ((val.split(" ").length == 1)) { + _$jscoverage['core/utils.js'][711]++; + switch (key) { + case "padding": + _$jscoverage['core/utils.js'][713]++; + ((! padding) && (padding = {})); + _$jscoverage['core/utils.js'][714]++; + padding[name] = val; + _$jscoverage['core/utils.js'][715]++; + return ""; + case "margin": + _$jscoverage['core/utils.js'][717]++; + ((! margin) && (margin = {})); + _$jscoverage['core/utils.js'][718]++; + margin[name] = val; + _$jscoverage['core/utils.js'][719]++; + return ""; + case "border": + _$jscoverage['core/utils.js'][721]++; + return ((val == "initial")? "": str); + } + } + _$jscoverage['core/utils.js'][724]++; + return str; +})); + _$jscoverage['core/utils.js'][727]++; + function opt(obj, name) { + _$jscoverage['core/utils.js'][728]++; + if ((! obj)) { + _$jscoverage['core/utils.js'][729]++; + return ""; + } + _$jscoverage['core/utils.js'][731]++; + var t = obj.top, b = obj.bottom, l = obj.left, r = obj.right, val = ""; + _$jscoverage['core/utils.js'][732]++; + if (((! t) || (! l) || (! b) || (! r))) { + _$jscoverage['core/utils.js'][733]++; + for (var p in obj) { + _$jscoverage['core/utils.js'][734]++; + val += (";" + name + "-" + p + ":" + obj[p] + ";"); +} + } + else { + _$jscoverage['core/utils.js'][737]++; + val += (";" + name + ":" + (((t == b) && (b == l) && (l == r))? t: (((t == b) && (l == r))? (t + " " + l): ((l == r)? (t + " " + l + " " + b): (t + " " + r + " " + b + " " + l)))) + ";"); + } + _$jscoverage['core/utils.js'][742]++; + return val; +} + _$jscoverage['core/utils.js'][745]++; + val += (opt(padding, "padding") + opt(margin, "margin")); + _$jscoverage['core/utils.js'][746]++; + return val.replace(/^[ \n\r\t;]*|[ \n\r\t]*$/, "").replace(/;([ \n\r\t]+)|\1;/g, ";").replace(/(&((l|g)t|quot|#39))?;{2,}/g, (function (a, b) { + _$jscoverage['core/utils.js'][748]++; + return (b? (b + ";;"): ";"); +})); +}), clone: (function (source, target) { + _$jscoverage['core/utils.js'][759]++; + var tmp; + _$jscoverage['core/utils.js'][760]++; + target = (target || {}); + _$jscoverage['core/utils.js'][761]++; + for (var i in source) { + _$jscoverage['core/utils.js'][762]++; + if (source.hasOwnProperty(i)) { + _$jscoverage['core/utils.js'][763]++; + tmp = source[i]; + _$jscoverage['core/utils.js'][764]++; + if (((typeof tmp) == "object")) { + _$jscoverage['core/utils.js'][765]++; + target[i] = (utils.isArray(tmp)? []: {}); + _$jscoverage['core/utils.js'][766]++; + utils.clone(source[i], target[i]); + } + else { + _$jscoverage['core/utils.js'][768]++; + target[i] = tmp; + } + } +} + _$jscoverage['core/utils.js'][772]++; + return target; +}), transUnitToPx: (function (val) { + _$jscoverage['core/utils.js'][792]++; + if ((! /(pt|cm)/.test(val))) { + _$jscoverage['core/utils.js'][793]++; + return val; + } + _$jscoverage['core/utils.js'][795]++; + var unit; + _$jscoverage['core/utils.js'][796]++; + val.replace(/([\d.]+)(\w+)/, (function (str, v, u) { + _$jscoverage['core/utils.js'][797]++; + val = v; + _$jscoverage['core/utils.js'][798]++; + unit = u; +})); + _$jscoverage['core/utils.js'][800]++; + switch (unit) { + case "cm": + _$jscoverage['core/utils.js'][802]++; + val = (parseFloat(val) * 25); + _$jscoverage['core/utils.js'][803]++; + break; + case "pt": + _$jscoverage['core/utils.js'][805]++; + val = Math.round(((parseFloat(val) * 96) / 72)); + } + _$jscoverage['core/utils.js'][807]++; + return (val + (val? "px": "")); +}), domReady: (function () { + _$jscoverage['core/utils.js'][828]++; + var fnArr = []; + _$jscoverage['core/utils.js'][830]++; + function doReady(doc) { + _$jscoverage['core/utils.js'][832]++; + doc.isReady = true; + _$jscoverage['core/utils.js'][833]++; + for (var ci; (ci = fnArr.pop()); ci()) { +} +} + _$jscoverage['core/utils.js'][837]++; + return (function (onready, win) { + _$jscoverage['core/utils.js'][838]++; + win = (win || window); + _$jscoverage['core/utils.js'][839]++; + var doc = win.document; + _$jscoverage['core/utils.js'][840]++; + (onready && fnArr.push(onready)); + _$jscoverage['core/utils.js'][841]++; + if ((doc.readyState === "complete")) { + _$jscoverage['core/utils.js'][842]++; + doReady(doc); + } + else { + _$jscoverage['core/utils.js'][844]++; + (doc.isReady && doReady(doc)); + _$jscoverage['core/utils.js'][845]++; + if (browser.ie) { + _$jscoverage['core/utils.js'][846]++; + (function () { + _$jscoverage['core/utils.js'][847]++; + if (doc.isReady) { + _$jscoverage['core/utils.js'][847]++; + return; + } + _$jscoverage['core/utils.js'][848]++; + try { + _$jscoverage['core/utils.js'][849]++; + doc.documentElement.doScroll("left"); + } + catch (error) { + _$jscoverage['core/utils.js'][851]++; + setTimeout(arguments.callee, 0); + _$jscoverage['core/utils.js'][852]++; + return; + } + _$jscoverage['core/utils.js'][854]++; + doReady(doc); +})(); + _$jscoverage['core/utils.js'][856]++; + win.attachEvent("onload", (function () { + _$jscoverage['core/utils.js'][857]++; + doReady(doc); +})); + } + else { + _$jscoverage['core/utils.js'][860]++; + doc.addEventListener("DOMContentLoaded", (function () { + _$jscoverage['core/utils.js'][861]++; + doc.removeEventListener("DOMContentLoaded", arguments.callee, false); + _$jscoverage['core/utils.js'][862]++; + doReady(doc); +}), false); + _$jscoverage['core/utils.js'][864]++; + win.addEventListener("load", (function () { + _$jscoverage['core/utils.js'][865]++; + doReady(doc); +}), false); + } + } +}); +})(), cssRule: (browser.ie? (function (key, style, doc) { + _$jscoverage['core/utils.js'][883]++; + var indexList, index; + _$jscoverage['core/utils.js'][884]++; + doc = (doc || document); + _$jscoverage['core/utils.js'][885]++; + if (doc.indexList) { + _$jscoverage['core/utils.js'][886]++; + indexList = doc.indexList; + } + else { + _$jscoverage['core/utils.js'][888]++; + indexList = (doc.indexList = {}); + } + _$jscoverage['core/utils.js'][890]++; + var sheetStyle; + _$jscoverage['core/utils.js'][891]++; + if ((! indexList[key])) { + _$jscoverage['core/utils.js'][892]++; + if ((style === undefined)) { + _$jscoverage['core/utils.js'][893]++; + return ""; + } + _$jscoverage['core/utils.js'][895]++; + sheetStyle = doc.createStyleSheet("", (index = doc.styleSheets.length)); + _$jscoverage['core/utils.js'][896]++; + indexList[key] = index; + } + else { + _$jscoverage['core/utils.js'][898]++; + sheetStyle = doc.styleSheets[indexList[key]]; + } + _$jscoverage['core/utils.js'][900]++; + if ((style === undefined)) { + _$jscoverage['core/utils.js'][901]++; + return sheetStyle.cssText; + } + _$jscoverage['core/utils.js'][903]++; + sheetStyle.cssText = (style || ""); +}): (function (key, style, doc) { + _$jscoverage['core/utils.js'][905]++; + doc = (doc || document); + _$jscoverage['core/utils.js'][906]++; + var head = doc.getElementsByTagName("head")[0], node; + _$jscoverage['core/utils.js'][907]++; + if ((! (node = doc.getElementById(key)))) { + _$jscoverage['core/utils.js'][908]++; + if ((style === undefined)) { + _$jscoverage['core/utils.js'][909]++; + return ""; + } + _$jscoverage['core/utils.js'][911]++; + node = doc.createElement("style"); + _$jscoverage['core/utils.js'][912]++; + node.id = key; + _$jscoverage['core/utils.js'][913]++; + head.appendChild(node); + } + _$jscoverage['core/utils.js'][915]++; + if ((style === undefined)) { + _$jscoverage['core/utils.js'][916]++; + return node.innerHTML; + } + _$jscoverage['core/utils.js'][918]++; + if ((style !== "")) { + _$jscoverage['core/utils.js'][919]++; + node.innerHTML = style; + } + else { + _$jscoverage['core/utils.js'][921]++; + head.removeChild(node); + } +})), sort: (function (array, compareFn) { + _$jscoverage['core/utils.js'][925]++; + compareFn = (compareFn || (function (item1, item2) { + _$jscoverage['core/utils.js'][925]++; + return item1.localeCompare(item2); +})); + _$jscoverage['core/utils.js'][926]++; + for (var i = 0, len = array.length; (i < len); (i++)) { + _$jscoverage['core/utils.js'][927]++; + for (var j = i, length = array.length; (j < length); (j++)) { + _$jscoverage['core/utils.js'][928]++; + if ((compareFn(array[i], array[j]) > 0)) { + _$jscoverage['core/utils.js'][929]++; + var t = array[i]; + _$jscoverage['core/utils.js'][930]++; + array[i] = array[j]; + _$jscoverage['core/utils.js'][931]++; + array[j] = t; + } +} +} + _$jscoverage['core/utils.js'][935]++; + return array; +})}); +_$jscoverage['core/utils.js'][980]++; +utils.each(["String", "Function", "Array", "Number", "RegExp", "Object"], (function (v) { + _$jscoverage['core/utils.js'][981]++; + UE.utils[("is" + v)] = (function (obj) { + _$jscoverage['core/utils.js'][982]++; + return (Object.prototype.toString.apply(obj) == ("[object " + v + "]")); +}); +})); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/customEvent.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/customEvent.js new file mode 100644 index 000000000..cd7c0e836 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/customEvent.js @@ -0,0 +1,43 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['customEvent.js']) { + _$jscoverage['customEvent.js'] = []; +} +_$jscoverage['customEvent.js'].source = ["/**"," * @file"," * @name 编辑器事件接口"," * @short Custom events"," * @des 本文件非编辑器核心文件,仅适用于生成对应的事件接口文档"," * UEditor编辑器中的所有事件监听和触发都统一采用"," * ''editor''是编辑器实例"," * editor.addListener(\"eventName\",handler) 和 editor.fireEvent(\"eventName\")方式调用,支持浏览器原生事件,如keydown,keyup,mousedown,mouseup等"," */","/**"," * 编辑器加载完成事件(核心),在编辑器准备好所有运行条件时触发,大部分场景可以使用editor.ready(fn)取代。"," * @name ready"," * @grammar editor.addListener(\"ready\",fn)"," * @example"," * editor.addListener(\"ready\",function(){"," * //this为editor实例"," * this.setContent(\"欢迎使用UEditor!\");"," * })"," * //同如下接口方式调用"," * editor.ready(function(){"," * this.setContent(\"欢迎使用UEditor!\");"," * })"," */","/**"," * 选区变化事件(核心),当选区出现变化时触发。"," * 在UEditor中,任何涉及到光标改变的操作都会触发选区变化事件,该事件主要用来实现工具栏状态反射。"," * @name selectionChange"," * @grammar editor.addListener(\"selectionChange\",fn)"," * @grammar editor.fireEvent(\"selectionChange\")"," * @example"," * editor.addListener(\"selectionChange\",function(){"," * //this为editor实例"," * })"," */","","/**"," * 内容变化事件(核心),当编辑区域中的文本内容出现变化时触发"," * @name contentChange"," * @grammar editor.addListener(\"contentChange\",fn)"," * @grammar editor.fireEvent(\"contentChange\")"," */","","/**"," * 粘贴事件(核心),当使用ctr+v快捷键粘贴(包括Chrome、FF浏览器的右键粘贴)时会触发本事件"," * @name (before|after)Paste"," * @grammar editor.addListener(\"beforePaste\",fn)"," * @desc"," * * beforePaste 在将粘贴的内容写到编辑器之前触发,这个事件触发时,粘贴的内容还未在编辑器内显示"," * * afterPaste 粘贴的内容已经写到编辑器里边后触发"," * @example"," * editor.addListener(\"beforePaste\",function(type,data){"," * //beforePaste事件监听区别于afterPaste事件监听最主要的一个方面是存在一个data参数,"," * //该data参数是一个对象,包含属性html。"," * //若用户在此处更改该html的值时,将会影响粘贴到编辑器中的内容,主要用于粘贴时需要特殊处理的一些场景。"," * console.log(this.getContent) //this都是当前编辑器的实例"," * //before事件才用这个参数,用来在写出编辑器之前对粘贴进来的内容进行最后的修改"," * data.html = \"我把粘贴内容改成了这句话\";"," * })"," */","","/**"," * 设置内容事件(核心),当调用setContent方法时触发"," * @name (before|after)SetContent"," * @grammar editor.addListener(\"beforeSetContent\",fn)"," * @desc"," * * beforeSetContent 在内容写到编辑器之前触发"," * * afterSetContent 内容已经写到编辑器里边后触发"," * @example"," * editor.addListener(\"beforeSetContent\",function(type,data){"," * //beforeSetContent事件监听区别于afterSetContent事件监听最主要的一个方面是存在一个data参数,"," * //该data参数是一个对象,包含属性html。"," * //若用户在此处更改该html的值时,将会影响设置到编辑器中的内容,主要用于设置内容时需要特殊处理的一些场景。"," * data.html = \"我把设置内容改成了这句话\";"," * })"," */","","/**"," * getAllHtml事件,当调用getAllHtml方法时触发"," * @name getAllHtml"," * @grammar editor.addListener(\"getAllHtml\",fn)"," * @desc"," * * 主要用来对于生成的整个html代码中的head内容进行定制,比如你想插入你自己的样式,script标签等,用来在展示时使用"," * @example"," * editor.addListener(\"getAllHtml\",function(type,data){"," * //data是document中head部分html的封装,可通过data.html来获取对应字符串。"," * //需要修改的话得重新赋值data.html = '<style type=\"text/css\"> body{margin:0;}</style>';"," * })"," */","","/**"," * 内容提交事件(插件),当内容提交插件加载并调用了autosubmit命令时触发,多用于提交之前的验证"," * @name beforeSubmit"," * @grammar editor.addListener(\"beforeSubmit\",fn) //若fn返回false,则阻止本次提交"," * @example"," * editor.addListener(\"beforeSubmit\",function(){"," * if(!editor.hasContents()){"," * return false;"," * }"," * })"," */","","/**"," * 如果抓取远程的图片失败了,就触发"," * @name catchRemoteError"," * @grammar editor.addListener(\"catchRemoteError\",fn)"," * @example"," * editor.addListener(\"catchRemoteError\",function(){"," * console.log(\"抓取失败了!\")"," * })"," */","","/**"," * 当抓取远程的图片成功并会返回生成图片的链接时触发"," * @name catchRemoterSuccess"," * @grammar editor.addListener(\"catchRemoterSuccess\",fn)"," * @example"," * editor.addListener(\"catchRemoterSuccess\",function(){"," * console.log(\"抓取成功\")"," * })"," */","","/**"," * 编辑模式切换事件(插件),当源码模式和富文本模式发生切换时触发事件"," * @name sourceModeChanged"," * @grammar editor.addListener(\"sourceModeChanged\",fn)"," * @example"," * editor.addListener(\"sourceModeChanged\",function(type,mode){"," * //mode代表了当前的编辑模式,true代表切换到了源码模式,false代表切换到了富文本模式"," * })"," */","","/**"," * 全屏切换事件(插件),当执行全屏切换的时候触发事件"," * @name fullScreenChanged"," * @grammar editor.addListener(\"fullScreenChanged\",fn)"," * @example"," * editor.addListener(\"fullScreenChanged\",function(type,mode){"," * //mode代表当前是否全屏,true代表切换到了全屏模式,false代表切换到了普通模式"," * })"," */","","/**"," * 字数超出限制事件(插件),当输入的字符数超出配置项配置时触发"," * @name wordCountOverflow"," * @grammar editor.addListener(\"wordCountOverflow\",fn)"," * @example"," * editor.addListener(\"wordCountOverflow\",function(type,length){"," * console.log(length)"," * })"," */",""]; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/editor.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/editor.js new file mode 100644 index 000000000..2c544eae9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/editor.js @@ -0,0 +1,73 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['editor.js']) { + _$jscoverage['editor.js'] = []; + _$jscoverage['editor.js'][1] = 0; + _$jscoverage['editor.js'][3] = 0; + _$jscoverage['editor.js'][5] = 0; + _$jscoverage['editor.js'][7] = 0; + _$jscoverage['editor.js'][9] = 0; + _$jscoverage['editor.js'][11] = 0; + _$jscoverage['editor.js'][13] = 0; + _$jscoverage['editor.js'][15] = 0; + _$jscoverage['editor.js'][17] = 0; + _$jscoverage['editor.js'][19] = 0; +} +_$jscoverage['editor.js'].source = ["UEDITOR_CONFIG = window.UEDITOR_CONFIG ||{};","","var baidu = window.baidu ||{};","","window.baidu = baidu;","","window.UE = baidu.editor ={};","","UE.plugins ={};","","UE.commands ={};","","UE.instants ={};","","UE.I18N ={};","","UE.version =\"1.2.6.1\";","","var dom = UE.dom ={};"]; +_$jscoverage['editor.js'][1]++; +UEDITOR_CONFIG = (window.UEDITOR_CONFIG || {}); +_$jscoverage['editor.js'][3]++; +var baidu = (window.baidu || {}); +_$jscoverage['editor.js'][5]++; +window.baidu = baidu; +_$jscoverage['editor.js'][7]++; +window.UE = (baidu.editor = {}); +_$jscoverage['editor.js'][9]++; +UE.plugins = {}; +_$jscoverage['editor.js'][11]++; +UE.commands = {}; +_$jscoverage['editor.js'][13]++; +UE.instants = {}; +_$jscoverage['editor.js'][15]++; +UE.I18N = {}; +_$jscoverage['editor.js'][17]++; +UE.version = "1.2.6.1"; +_$jscoverage['editor.js'][19]++; +var dom = (UE.dom = {}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage-highlight.css b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage-highlight.css new file mode 100644 index 000000000..d2ad01da5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage-highlight.css @@ -0,0 +1,38 @@ +/* + jscoverage-highlight.css - JSCoverage syntax highlighting style sheet + Copyright (C) 2008, 2009, 2010 siliconforks.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* keyword, type, symbol, cbracket */ +#sourceTable .k { + font-weight: bold; +} + +/* string, regexp, number */ +#sourceTable .s { + color: #006400; +} + +/* specialchar */ +#sourceTable .t { + color: #2e8b57; +} + +/* comment */ +#sourceTable .c { + font-style: italic; +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage-ie.css b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage-ie.css new file mode 100644 index 000000000..05cad2afa --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage-ie.css @@ -0,0 +1,108 @@ +/* + jscoverage-ie.css - JSCoverage style sheet for Internet Explorer + Copyright (C) 2007, 2008, 2009, 2010 siliconforks.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#headingDiv { + position: static; + margin-left: 10px; + margin-right: 10px; + padding-top: 0.5em; +} + +#tabs { + clear: all; + position: static; + top: auto; + left: auto; + right: auto; + height: auto; + margin-left: 10px; + margin-right: 10px; +} + +#tabs div { + position: relative; + height: auto; + line-height: normal; + padding-top: 5px; + padding-bottom: 5px; +} + +#tabs div.selected { + padding-bottom: 6px; + z-index: 2; +} + +.TabPage { + position: relative; + top: -1px; + left: auto; + right: auto; + bottom: auto; + clear: left; + margin-left: 10px; + margin-right: 10px; + padding: 10px; + z-index: 1; +} + +#locationDiv { + margin-bottom: 10px; +} + +#iframeDiv { + position: static; + width: 100%; +} + +#summaryDiv { + position: static; + width: 100%; +} + +#fileDiv { + margin-bottom: 10px; +} + +#sourceDiv { + position: static; + width: 100%; +} + +#storeDiv { + position: static; + width: 100%; +} + +/* some defaults */ + +.TabPage { + height: 650px; +} + +#iframeDiv { + height: 600px; +} + +#summaryDiv { + height: 600px; +} + +#sourceDiv { + height: 600px; +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage-throbber.gif b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage-throbber.gif new file mode 100644 index 000000000..f13c0b4ec Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage-throbber.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage.css b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage.css new file mode 100644 index 000000000..9866fd706 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage.css @@ -0,0 +1,355 @@ +/* + jscoverage.css - code coverage for JavaScript + Copyright (C) 2007, 2008, 2009, 2010 siliconforks.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +body { + background-color: #bfffbf; + font-family: sans-serif; + font-size: 100%; + margin: 0; +} + +#mainDiv { + font-size: 0.8125em; +} + +#headingDiv { + position: absolute; + top: 0.5em; + left: 1.5em; + right: 1.5em; + bottom: 0; + line-height: 1.5em; +} + +h1 { + float: left; + margin: 0; + padding-bottom: 0.5em; + font-size: 1.3em; +} + +.ProgressBar { + float: left; + visibility: hidden; +} + +.ProgressPercentage { + display: block; + float: left; + width: 5em; + text-align: right; +} + +.ProgressGraph { + float: left; + width: 100px; + height: 10px; + border: 1px solid black; + margin-top: 0.3em; + background-color: #d4d0c8; + overflow: hidden; +} + +.ProgressCovered { + /* windows system color ActiveCaption or Highlight */ + background-color: #0a246a; + width: 0; + height: 10px; + overflow: hidden; +} + +#progressLabel { + display: block; + float: left; + padding-left: 0.3em; +} + +#warningDiv { + display: none; + float: right; + background-color: #FFBFBF; + border: 1px solid red; + padding-left: 2px; + padding-right: 2px; +} + +.WarningDialog { + display: none; + background-color: #FFBFBF; + position: absolute; + z-index: 10; + top: 20%; + left: 20%; + width: 50%; + padding: 5%; + border: 1px solid red; +} + +.WarningDialog button { + display: block; + margin-left: auto; + margin-right: auto; +} + +/******************************************************************************* +browser tab +*/ + +input#location, button { + border: 1px solid black; + margin-left: 1px; + margin-right: 1px; +} + +#iframeDiv { + position: absolute; + top: 3.5em; + left: 1em; + right: 1em; + bottom: 1em; +} + +iframe { + width: 100%; + height: 100%; +} + +/******************************************************************************* +summary tab +*/ + +#summaryDiv { + position: absolute; + top: 3em; + left: 1em; + right: 1em; + bottom: 1em; + overflow: auto; +} + +table#summaryTable { + width: 100%; + margin-left: 0px; + margin-right: 0px; + border-collapse: collapse; + font-size: small; +} + +table#summaryTable th, table#summaryTable td { + border-left: 1px solid #d9d9d9; +} + +table#summaryTable th.leftColumn, table#summaryTable td.leftColumn { + border-left-width: 0px; +} + +table#summaryTable th, table#summaryTable td { + padding: 2px; +} + +th { + background-color: #e6ffe6; +} + +td.numeric { + text-align: right; +} + +abbr { + cursor: help; +} + +tr#summaryTotals td.leftColumn span { + float: right; +} +tr#summaryTotals td.leftColumn span.title { + float: left; + font-weight: bold; +} +tr#summaryTotals td { + background-color: #ffd; +} +td.coverage { + width: 150px; +} +td.coverage span { + float: right; + margin-right: 5px; +} +.pctGraph { + width: 100px; + height: 10px; + float: right; + border: 1px solid #000; + background-color: #e00000; + overflow: hidden; + margin-top: 4px; +} +.pctGraph .covered { + background-color: #00f000; + width: 0; + height: 10px; +} +.pctGraph .skipped { + background-color: #d4d0c8; + width: 100px; + height: 10px; +} +tbody#summaryTbody tr.even td { + background-color: #e6ffe6; +} + +/******************************************************************************* +source tab +*/ + +#fileDiv { + font-size: large; + font-weight: bold; +} + +#sourceDiv { + position: absolute; + top: 3em; + left: 1em; + right: 1em; + bottom: 1em; + overflow: auto; +} + +table#sourceTable { + border: 0px; + border-collapse: collapse; + font-size: small; +} + +/* +IE default behavior is to make
     smaller than surrounding text.  Because
    +the table already has font-size small, this would make the font-size within the
    +
     x-small.  So we don't rely on the default.
    +*/
    +table#sourceTable pre {
    +  font-size: medium;
    +}
    +
    +table#sourceTable td {
    +  border: 0px;
    +  padding-top: 0px;
    +  padding-bottom: 0px;
    +  padding-left: 10px;
    +  padding-right: 10px;
    +}
    +
    +table#sourceTable pre {
    +  border: 0px;
    +  margin: 0px;
    +}
    +
    +.g {
    +  background-color: #bfffbf;
    +}
    +
    +.y {
    +  background-color: #ffffbf;
    +}
    +
    +.r {
    +  background-color: #ffbfbf;
    +}
    +
    +/*******************************************************************************
    +store tab
    +*/
    +
    +#storeDiv {
    +  position: absolute;
    +  top: 3em;
    +  left: 1em;
    +  right: 1em;
    +  bottom: 1em;
    +  overflow: auto;
    +}
    +
    +/*******************************************************************************
    +about tab
    +*/
    +
    +p {
    +  margin-top: 0;
    +}
    +
    +/*******************************************************************************
    +tabs
    +*/
    +
    +#tabs {
    +  position: absolute;
    +  top: 3em;
    +  left: 1.5em;
    +  right: 1.5em;
    +  height: 2em;
    +}
    +
    +#tabs div {
    +  background-color: white;
    +  position: relative;
    +  float: left;
    +  border: 1px solid black;
    +  border-bottom-width: 0;
    +  cursor: pointer;
    +  margin-left: 0.5em;
    +  margin-right: 0.5em;
    +  padding-left: 0.5em;
    +  padding-right: 0.5em;
    +  height: 2em;
    +  z-index: 1;
    +  line-height: 1.8em;
    +}
    +
    +#tabs div.selected {
    +  z-index: 3;
    +  cursor: default;
    +}
    +
    +#tabs div.disabled {
    +  /* windows system color GrayText */
    +  color: #808080;
    +  cursor: default; 
    +}
    +
    +.TabPage {
    +  background-color: white;
    +  border: 1px solid black;
    +  position: absolute;
    +  top: 5em;
    +  left: 1.5em;
    +  right: 1.5em;
    +  bottom: 1.5em;
    +  z-index: 2;
    +  padding: 1em;
    +  display: none;
    +}
    +
    +#tabPages div.selected {
    +  display: block;
    +}
    +
    +img {
    +  visibility: hidden;
    +}
    diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage.html b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage.html
    new file mode 100644
    index 000000000..00d35185a
    --- /dev/null
    +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage.html
    @@ -0,0 +1,164 @@
    +
    +
    +
    +
    +
    +
    +JSCoverage
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +

    +Recent web browsers tend to place significant security restrictions on the use +of file: URLs. These restrictions can prevent JSCoverage from +working properly. To avoid problems, it is recommended that you do either of the +following: +

    +
      +
    • If you are using the jscoverage program to instrument your +JavaScript code, install the instrumented files on a web server.
    • +
    • Use the jscoverage-server program (which itself acts as a web +server).
    • +
    +

    +See the +manual +for further details. +

    + +
    + +
    +

    +Recent web browsers tend to place significant security restrictions on the use +of file: URLs. These restrictions can prevent JSCoverage from +working properly. To avoid problems, it is recommended that you view coverage +reports stored to the filesystem by serving them from a web server. +

    +

    +See the +manual +for further details. +

    + +
    + +
    +
    Browser
    +
    Summary
    +
    Source
    +
    Store
    +
    About
    +
    +
    +
    +
    + URL: + + +
    +
    + +
    +
    +
    + +
    +
    +
    + + + + + + + + + + + + + + + + + + + + +
    FileStatementsExecutedCoverage
    + Total: + 0 + 00 +
    +
    +
    + 0% +
    +
    +
    +
    +
    +
    +
    +
    + + loading... +
    +
    +
    +

    + This is version 0.5.1 of JSCoverage, a program that calculates code + coverage statistics for JavaScript. +

    +

    + See http://siliconforks.com/jscoverage/ for more information. +

    +

    + Copyright © 2007, 2008, 2009, 2010 siliconforks.com +

    +
    +
    +
    + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage.js new file mode 100644 index 000000000..4233615a4 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/jscoverage.js @@ -0,0 +1,1176 @@ +/* + jscoverage.js - code coverage for JavaScript + Copyright (C) 2007, 2008, 2009, 2010 siliconforks.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +function jscoverage_openWarningDialog() { + var id; + if (jscoverage_isReport) { + id = 'reportWarningDialog'; + } + else { + id = 'warningDialog'; + } + var dialog = document.getElementById(id); + dialog.style.display = 'block'; +} + +function jscoverage_closeWarningDialog() { + var id; + if (jscoverage_isReport) { + id = 'reportWarningDialog'; + } + else { + id = 'warningDialog'; + } + var dialog = document.getElementById(id); + dialog.style.display = 'none'; +} + +/** +Initializes the _$jscoverage object in a window. This should be the first +function called in the page. +@param w this should always be the global window object +*/ +function jscoverage_init(w) { + try { + // in Safari, "import" is a syntax error + Components.utils['import']('resource://app/modules/jscoverage.jsm'); + jscoverage_isInvertedMode = true; + return; + } + catch (e) {} + + // check if we are in inverted mode + if (w.opener) { + try { + if (w.opener.top._$jscoverage) { + jscoverage_isInvertedMode = true; + if (! w._$jscoverage) { + w._$jscoverage = w.opener.top._$jscoverage; + } + } + else { + jscoverage_isInvertedMode = false; + } + } + catch (e) { + try { + if (w.opener._$jscoverage) { + jscoverage_isInvertedMode = true; + if (! w._$jscoverage) { + w._$jscoverage = w.opener._$jscoverage; + } + } + else { + jscoverage_isInvertedMode = false; + } + } + catch (e2) { + jscoverage_isInvertedMode = false; + } + } + } + else { + jscoverage_isInvertedMode = false; + } + + if (! jscoverage_isInvertedMode) { + if (! w._$jscoverage) { + w._$jscoverage = {}; + } + } +} + +var jscoverage_currentFile = null; +var jscoverage_currentLine = null; + +var jscoverage_inLengthyOperation = false; + +/* +Possible states: + isInvertedMode isServer isReport tabs +normal false false false Browser +inverted true false false +server, normal false true false Browser, Store +server, inverted true true false Store +report false false true +*/ +var jscoverage_isInvertedMode = false; +var jscoverage_isServer = false; +var jscoverage_isReport = false; + +jscoverage_init(window); + +function jscoverage_createRequest() { + // Note that the IE7 XMLHttpRequest does not support file URL's. + // http://xhab.blogspot.com/2006/11/ie7-support-for-xmlhttprequest.html + // http://blogs.msdn.com/ie/archive/2006/12/06/file-uris-in-windows.aspx +//#JSCOVERAGE_IF + if (window.ActiveXObject) { + return new ActiveXObject("Microsoft.XMLHTTP"); + } + else { + return new XMLHttpRequest(); + } +} + +// http://www.quirksmode.org/js/findpos.html +function jscoverage_findPos(obj) { + var result = 0; + do { + result += obj.offsetTop; + obj = obj.offsetParent; + } + while (obj); + return result; +} + +// http://www.quirksmode.org/viewport/compatibility.html +function jscoverage_getViewportHeight() { +//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent) + if (self.innerHeight) { + // all except Explorer + return self.innerHeight; + } + else if (document.documentElement && document.documentElement.clientHeight) { + // Explorer 6 Strict Mode + return document.documentElement.clientHeight; + } + else if (document.body) { + // other Explorers + return document.body.clientHeight; + } + else { + throw "Couldn't calculate viewport height"; + } +//#JSCOVERAGE_ENDIF +} + +/** +Indicates visually that a lengthy operation has begun. The progress bar is +displayed, and the cursor is changed to busy (on browsers which support this). +*/ +function jscoverage_beginLengthyOperation() { + jscoverage_inLengthyOperation = true; + + var progressBar = document.getElementById('progressBar'); + progressBar.style.visibility = 'visible'; + ProgressBar.setPercentage(progressBar, 0); + var progressLabel = document.getElementById('progressLabel'); + progressLabel.style.visibility = 'visible'; + + /* blacklist buggy browsers */ +//#JSCOVERAGE_IF + if (! /Opera|WebKit/.test(navigator.userAgent)) { + /* + Change the cursor style of each element. Note that changing the class of the + element (to one with a busy cursor) is buggy in IE. + */ + var tabs = document.getElementById('tabs').getElementsByTagName('div'); + var i; + for (i = 0; i < tabs.length; i++) { + tabs.item(i).style.cursor = 'wait'; + } + } +} + +/** +Removes the progress bar and busy cursor. +*/ +function jscoverage_endLengthyOperation() { + var progressBar = document.getElementById('progressBar'); + ProgressBar.setPercentage(progressBar, 100); + setTimeout(function() { + jscoverage_inLengthyOperation = false; + progressBar.style.visibility = 'hidden'; + var progressLabel = document.getElementById('progressLabel'); + progressLabel.style.visibility = 'hidden'; + progressLabel.innerHTML = ''; + + var tabs = document.getElementById('tabs').getElementsByTagName('div'); + var i; + for (i = 0; i < tabs.length; i++) { + tabs.item(i).style.cursor = ''; + } + }, 50); +} + +function jscoverage_setSize() { +//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent) + var viewportHeight = jscoverage_getViewportHeight(); + + /* + border-top-width: 1px + padding-top: 10px + padding-bottom: 10px + border-bottom-width: 1px + margin-bottom: 10px + ---- + 32px + */ + var tabPages = document.getElementById('tabPages'); + var tabPageHeight = (viewportHeight - jscoverage_findPos(tabPages) - 32) + 'px'; + var nodeList = tabPages.childNodes; + var length = nodeList.length; + for (var i = 0; i < length; i++) { + var node = nodeList.item(i); + if (node.nodeType !== 1) { + continue; + } + node.style.height = tabPageHeight; + } + + var iframeDiv = document.getElementById('iframeDiv'); + // may not exist if we have removed the first tab + if (iframeDiv) { + iframeDiv.style.height = (viewportHeight - jscoverage_findPos(iframeDiv) - 21) + 'px'; + } + + var summaryDiv = document.getElementById('summaryDiv'); + summaryDiv.style.height = (viewportHeight - jscoverage_findPos(summaryDiv) - 21) + 'px'; + + var sourceDiv = document.getElementById('sourceDiv'); + sourceDiv.style.height = (viewportHeight - jscoverage_findPos(sourceDiv) - 21) + 'px'; + + var storeDiv = document.getElementById('storeDiv'); + if (storeDiv) { + storeDiv.style.height = (viewportHeight - jscoverage_findPos(storeDiv) - 21) + 'px'; + } +//#JSCOVERAGE_ENDIF +} + +/** +Returns the boolean value of a string. Values 'false', 'f', 'no', 'n', 'off', +and '0' (upper or lower case) are false. +@param s the string +@return a boolean value +*/ +function jscoverage_getBooleanValue(s) { + s = s.toLowerCase(); + if (s === 'false' || s === 'f' || s === 'no' || s === 'n' || s === 'off' || s === '0') { + return false; + } + return true; +} + +function jscoverage_removeTab(id) { + var tab = document.getElementById(id + 'Tab'); + tab.parentNode.removeChild(tab); + var tabPage = document.getElementById(id + 'TabPage'); + tabPage.parentNode.removeChild(tabPage); +} + +function jscoverage_isValidURL(url) { + // RFC 3986 + var matches = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/.exec(url); + if (matches === null) { + return false; + } + var scheme = matches[1]; + if (typeof scheme === 'string') { + scheme = scheme.toLowerCase(); + return scheme === '' || scheme === 'file:' || scheme === 'http:' || scheme === 'https:'; + } + return true; +} + +/** +Initializes the contents of the tabs. This sets the initial values of the +input field and iframe in the "Browser" tab and the checkbox in the "Summary" +tab. +@param queryString this should always be location.search +*/ +function jscoverage_initTabContents(queryString) { + var showMissingColumn = false; + var url = null; + var windowURL = null; + var parameters, parameter, i, index, name, value; + if (queryString.length > 0) { + // chop off the question mark + queryString = queryString.substring(1); + parameters = queryString.split(/&|;/); + for (i = 0; i < parameters.length; i++) { + parameter = parameters[i]; + index = parameter.indexOf('='); + if (index === -1) { + // still works with old syntax + url = decodeURIComponent(parameter); + } + else { + name = parameter.substr(0, index); + value = decodeURIComponent(parameter.substr(index + 1)); + if (name === 'missing' || name === 'm') { + showMissingColumn = jscoverage_getBooleanValue(value); + } + else if (name === 'url' || name === 'u' || name === 'frame' || name === 'f') { + url = value; + } + else if (name === 'window' || name === 'w') { + windowURL = value; + } + } + } + } + + var checkbox = document.getElementById('checkbox'); + checkbox.checked = showMissingColumn; + if (showMissingColumn) { + jscoverage_appendMissingColumn(); + } + + var isValidURL = function (url) { + var result = jscoverage_isValidURL(url); + if (! result) { + alert('Invalid URL: ' + url); + } + return result; + }; + + if (url !== null && isValidURL(url)) { + // this will automatically propagate to the input field + frames[0].location = url; + } + else if (windowURL !== null && isValidURL(windowURL)) { + window.open(windowURL); + } + + // if the browser tab is absent, we have to initialize the summary tab + if (! document.getElementById('browserTab')) { + jscoverage_recalculateSummaryTab(); + } +} + +function jscoverage_body_load() { + // check if this is a file: URL + if (window.location && window.location.href && /^file:/i.test(window.location.href)) { + var warningDiv = document.getElementById('warningDiv'); + warningDiv.style.display = 'block'; + } + + var progressBar = document.getElementById('progressBar'); + ProgressBar.init(progressBar); + + function reportError(e) { + jscoverage_endLengthyOperation(); + var summaryThrobber = document.getElementById('summaryThrobber'); + summaryThrobber.style.visibility = 'hidden'; + var div = document.getElementById('summaryErrorDiv'); + div.innerHTML = 'Error: ' + e; + } + + if (jscoverage_isReport) { + jscoverage_beginLengthyOperation(); + var summaryThrobber = document.getElementById('summaryThrobber'); + summaryThrobber.style.visibility = 'visible'; + var request = jscoverage_createRequest(); + try { + request.open('GET', 'jscoverage.json', true); + request.onreadystatechange = function (event) { + if (request.readyState === 4) { + try { + if (request.status !== 0 && request.status !== 200) { + throw request.status; + } + var response = request.responseText; + if (response === '') { + throw 404; + } + + var json; + if (window.JSON && window.JSON.parse) { + json = window.JSON.parse(response); + } + else { + json = eval('(' + response + ')'); + } + + var file; + for (file in json) { + if (! json.hasOwnProperty(file)) { + continue; + } + + var fileCoverage = json[file]; + _$jscoverage[file] = fileCoverage.coverage; + _$jscoverage[file].source = fileCoverage.source; + } + jscoverage_recalculateSummaryTab(); + summaryThrobber.style.visibility = 'hidden'; + } + catch (e) { + reportError(e); + } + } + }; + request.send(null); + } + catch (e) { + reportError(e); + } + + jscoverage_removeTab('browser'); + jscoverage_removeTab('store'); + } + else { + if (jscoverage_isInvertedMode) { + jscoverage_removeTab('browser'); + } + + if (! jscoverage_isServer) { + jscoverage_removeTab('store'); + } + } + + jscoverage_initTabControl(); + + jscoverage_initTabContents(location.search); +} + +function jscoverage_body_resize() { + if (/MSIE/.test(navigator.userAgent)) { + jscoverage_setSize(); + } +} + +// ----------------------------------------------------------------------------- +// tab 1 + +function jscoverage_updateBrowser() { + var input = document.getElementById("location"); + frames[0].location = input.value; +} + +function jscoverage_openWindow() { + var input = document.getElementById("location"); + var url = input.value; + window.open(url); +} + +function jscoverage_input_keypress(e) { + if (e.keyCode === 13) { + if (e.shiftKey) { + jscoverage_openWindow(); + } + else { + jscoverage_updateBrowser(); + } + } +} + +function jscoverage_openInFrameButton_click() { + jscoverage_updateBrowser(); +} + +function jscoverage_openInWindowButton_click() { + jscoverage_openWindow(); +} + +function jscoverage_browser_load() { + /* update the input box */ + var input = document.getElementById("location"); + + /* sometimes IE seems to fire this after the tab has been removed */ + if (input) { + input.value = frames[0].location; + } +} + +// ----------------------------------------------------------------------------- +// tab 2 + +function jscoverage_createHandler(file, line) { + return function () { + jscoverage_get(file, line); + return false; + }; +} + +function jscoverage_createLink(file, line) { + var link = document.createElement("a"); + link.href = '#'; + link.onclick = jscoverage_createHandler(file, line); + + var text; + if (line) { + text = line.toString(); + } + else { + text = file; + } + + link.appendChild(document.createTextNode(text)); + + return link; +} + +function jscoverage_recalculateSummaryTab(cc) { + var checkbox = document.getElementById('checkbox'); + var showMissingColumn = checkbox.checked; + + if (! cc) { + cc = window._$jscoverage; + } + if (! cc) { +//#JSCOVERAGE_IF 0 + throw "No coverage information found."; +//#JSCOVERAGE_ENDIF + } + + var tbody = document.getElementById("summaryTbody"); + while (tbody.hasChildNodes()) { + tbody.removeChild(tbody.firstChild); + } + + var totals = { files:0, statements:0, executed:0 }; + + var file; + var files = []; + for (file in cc) { + if (! cc.hasOwnProperty(file)) { + continue; + } + + files.push(file); + } + files.sort(); + + var rowCounter = 0; + for (var f = 0; f < files.length; f++) { + file = files[f]; + var lineNumber; + var num_statements = 0; + var num_executed = 0; + var missing = []; + var fileCC = cc[file]; + var length = fileCC.length; + var currentConditionalEnd = 0; + var conditionals = null; + if (fileCC.conditionals) { + conditionals = fileCC.conditionals; + } + for (lineNumber = 0; lineNumber < length; lineNumber++) { + var n = fileCC[lineNumber]; + + if (lineNumber === currentConditionalEnd) { + currentConditionalEnd = 0; + } + else if (currentConditionalEnd === 0 && conditionals && conditionals[lineNumber]) { + currentConditionalEnd = conditionals[lineNumber]; + } + + if (currentConditionalEnd !== 0) { + continue; + } + + if (n === undefined || n === null) { + continue; + } + + if (n === 0) { + missing.push(lineNumber); + } + else { + num_executed++; + } + num_statements++; + } + + var percentage = ( num_statements === 0 ? 0 : parseInt(100 * num_executed / num_statements) ); + + var row = document.createElement("tr"); + row.className = ( rowCounter++ % 2 == 0 ? "odd" : "even" ); + + var cell = document.createElement("td"); + cell.className = 'leftColumn'; + var link = jscoverage_createLink(file); + cell.appendChild(link); + + row.appendChild(cell); + + cell = document.createElement("td"); + cell.className = 'numeric'; + cell.appendChild(document.createTextNode(num_statements)); + row.appendChild(cell); + + cell = document.createElement("td"); + cell.className = 'numeric'; + cell.appendChild(document.createTextNode(num_executed)); + row.appendChild(cell); + + // new coverage td containing a bar graph + cell = document.createElement("td"); + cell.className = 'coverage'; + var pctGraph = document.createElement("div"), + covered = document.createElement("div"), + pct = document.createElement("span"); + pctGraph.className = "pctGraph"; + if( num_statements === 0 ) { + covered.className = "skipped"; + pct.appendChild(document.createTextNode("N/A")); + } else { + covered.className = "covered"; + covered.style.width = percentage + "px"; + pct.appendChild(document.createTextNode(percentage + '%')); + } + pct.className = "pct"; + pctGraph.appendChild(covered); + cell.appendChild(pctGraph); + cell.appendChild(pct); + row.appendChild(cell); + + if (showMissingColumn) { + cell = document.createElement("td"); + for (var i = 0; i < missing.length; i++) { + if (i !== 0) { + cell.appendChild(document.createTextNode(", ")); + } + link = jscoverage_createLink(file, missing[i]); + + // group contiguous missing lines; e.g., 10, 11, 12 -> 10-12 + var j, start = missing[i]; + for (;;) { + j = 1; + while (i + j < missing.length && missing[i + j] == missing[i] + j) { + j++; + } + var nextmissing = missing[i + j], cur = missing[i] + j; + if (isNaN(nextmissing)) { + break; + } + while (cur < nextmissing && ! fileCC[cur]) { + cur++; + } + if (cur < nextmissing || cur >= length) { + break; + } + i += j; + } + if (start != missing[i] || j > 1) { + i += j - 1; + link.innerHTML += "-" + missing[i]; + } + + cell.appendChild(link); + } + row.appendChild(cell); + } + + tbody.appendChild(row); + + totals['files'] ++; + totals['statements'] += num_statements; + totals['executed'] += num_executed; + + // write totals data into summaryTotals row + var tr = document.getElementById("summaryTotals"); + if (tr) { + var tds = tr.getElementsByTagName("td"); + tds[0].getElementsByTagName("span")[1].firstChild.nodeValue = totals['files']; + tds[1].firstChild.nodeValue = totals['statements']; + tds[2].firstChild.nodeValue = totals['executed']; + + var coverage = parseInt(100 * totals['executed'] / totals['statements']); + if( isNaN( coverage ) ) { + coverage = 0; + } + tds[3].getElementsByTagName("span")[0].firstChild.nodeValue = coverage + '%'; + tds[3].getElementsByTagName("div")[1].style.width = coverage + 'px'; + } + + } + jscoverage_endLengthyOperation(); +} + +function jscoverage_appendMissingColumn() { + var headerRow = document.getElementById('headerRow'); + var missingHeader = document.createElement('th'); + missingHeader.id = 'missingHeader'; + missingHeader.innerHTML = 'Missing'; + headerRow.appendChild(missingHeader); + var summaryTotals = document.getElementById('summaryTotals'); + var empty = document.createElement('td'); + empty.id = 'missingCell'; + summaryTotals.appendChild(empty); +} + +function jscoverage_removeMissingColumn() { + var missingNode; + missingNode = document.getElementById('missingHeader'); + missingNode.parentNode.removeChild(missingNode); + missingNode = document.getElementById('missingCell'); + missingNode.parentNode.removeChild(missingNode); +} + +function jscoverage_checkbox_click() { + if (jscoverage_inLengthyOperation) { + return false; + } + jscoverage_beginLengthyOperation(); + var checkbox = document.getElementById('checkbox'); + var showMissingColumn = checkbox.checked; + setTimeout(function() { + if (showMissingColumn) { + jscoverage_appendMissingColumn(); + } + else { + jscoverage_removeMissingColumn(); + } + jscoverage_recalculateSummaryTab(); + }, 50); + return true; +} + +// ----------------------------------------------------------------------------- +// tab 3 + +function jscoverage_makeTable() { + var coverage = _$jscoverage[jscoverage_currentFile]; + var lines = coverage.source; + + // this can happen if there is an error in the original JavaScript file + if (! lines) { + lines = []; + } + + var rows = ['']; + var i = 0; + var progressBar = document.getElementById('progressBar'); + var tableHTML; + var currentConditionalEnd = 0; + + function joinTableRows() { + tableHTML = rows.join(''); + ProgressBar.setPercentage(progressBar, 60); + /* + This may be a long delay, so set a timeout of 100 ms to make sure the + display is updated. + */ + setTimeout(appendTable, 100); + } + + function appendTable() { + var sourceDiv = document.getElementById('sourceDiv'); + sourceDiv.innerHTML = tableHTML; + ProgressBar.setPercentage(progressBar, 80); + setTimeout(jscoverage_scrollToLine, 0); + } + + while (i < lines.length) { + var lineNumber = i + 1; + + if (lineNumber === currentConditionalEnd) { + currentConditionalEnd = 0; + } + else if (currentConditionalEnd === 0 && coverage.conditionals && coverage.conditionals[lineNumber]) { + currentConditionalEnd = coverage.conditionals[lineNumber]; + } + + var row = ''; + row += ''; + var timesExecuted = coverage[lineNumber]; + if (timesExecuted !== undefined && timesExecuted !== null) { + if (currentConditionalEnd !== 0) { + row += ''; + } + else { + row += ''; + } + row += ''; + row += ''; + row += '\n'; + rows[lineNumber] = row; + i++; + } + rows[i + 1] = '
    ' + lineNumber + ''; + } + else if (timesExecuted === 0) { + row += ''; + } + else { + row += ''; + } + row += timesExecuted; + row += '
    ' + lines[i] + '
    '; + ProgressBar.setPercentage(progressBar, 40); + setTimeout(joinTableRows, 0); +} + +function jscoverage_scrollToLine() { + jscoverage_selectTab('sourceTab'); + if (! window.jscoverage_currentLine) { + jscoverage_endLengthyOperation(); + return; + } + var div = document.getElementById('sourceDiv'); + if (jscoverage_currentLine === 1) { + div.scrollTop = 0; + } + else { + var cell = document.getElementById('line-' + jscoverage_currentLine); + + // this might not be there if there is an error in the original JavaScript + if (cell) { + var divOffset = jscoverage_findPos(div); + var cellOffset = jscoverage_findPos(cell); + div.scrollTop = cellOffset - divOffset; + } + } + jscoverage_currentLine = 0; + jscoverage_endLengthyOperation(); +} + +/** +Loads the given file (and optional line) in the source tab. +*/ +function jscoverage_get(file, line) { + if (jscoverage_inLengthyOperation) { + return; + } + jscoverage_beginLengthyOperation(); + setTimeout(function() { + var sourceDiv = document.getElementById('sourceDiv'); + sourceDiv.innerHTML = ''; + jscoverage_selectTab('sourceTab'); + if (file === jscoverage_currentFile) { + jscoverage_currentLine = line; + jscoverage_recalculateSourceTab(); + } + else { + if (jscoverage_currentFile === null) { + var tab = document.getElementById('sourceTab'); + tab.className = ''; + tab.onclick = jscoverage_tab_click; + } + jscoverage_currentFile = file; + jscoverage_currentLine = line || 1; // when changing the source, always scroll to top + var fileDiv = document.getElementById('fileDiv'); + fileDiv.innerHTML = jscoverage_currentFile; + jscoverage_recalculateSourceTab(); + return; + } + }, 50); +} + +/** +Calculates coverage statistics for the current source file. +*/ +function jscoverage_recalculateSourceTab() { + if (! jscoverage_currentFile) { + jscoverage_endLengthyOperation(); + return; + } + var progressLabel = document.getElementById('progressLabel'); + progressLabel.innerHTML = 'Calculating coverage ...'; + var progressBar = document.getElementById('progressBar'); + ProgressBar.setPercentage(progressBar, 20); + setTimeout(jscoverage_makeTable, 0); +} + +// ----------------------------------------------------------------------------- +// tabs + +/** +Initializes the tab control. This function must be called when the document is +loaded. +*/ +function jscoverage_initTabControl() { + var tabs = document.getElementById('tabs'); + var i; + var child; + var tabNum = 0; + for (i = 0; i < tabs.childNodes.length; i++) { + child = tabs.childNodes.item(i); + if (child.nodeType === 1) { + if (child.className !== 'disabled') { + child.onclick = jscoverage_tab_click; + } + tabNum++; + } + } + jscoverage_selectTab(0); +} + +/** +Selects a tab. +@param tab the integer index of the tab (0, 1, 2, or 3) + OR + the ID of the tab element + OR + the tab element itself +*/ +function jscoverage_selectTab(tab) { + if (typeof tab !== 'number') { + tab = jscoverage_tabIndexOf(tab); + } + var tabs = document.getElementById('tabs'); + var tabPages = document.getElementById('tabPages'); + var nodeList; + var tabNum; + var i; + var node; + + nodeList = tabs.childNodes; + tabNum = 0; + for (i = 0; i < nodeList.length; i++) { + node = nodeList.item(i); + if (node.nodeType !== 1) { + continue; + } + + if (node.className !== 'disabled') { + if (tabNum === tab) { + node.className = 'selected'; + } + else { + node.className = ''; + } + } + tabNum++; + } + + nodeList = tabPages.childNodes; + tabNum = 0; + for (i = 0; i < nodeList.length; i++) { + node = nodeList.item(i); + if (node.nodeType !== 1) { + continue; + } + + if (tabNum === tab) { + node.className = 'selected TabPage'; + } + else { + node.className = 'TabPage'; + } + tabNum++; + } +} + +/** +Returns an integer (0, 1, 2, or 3) representing the index of a given tab. +@param tab the ID of the tab element + OR + the tab element itself +*/ +function jscoverage_tabIndexOf(tab) { + if (typeof tab === 'string') { + tab = document.getElementById(tab); + } + var tabs = document.getElementById('tabs'); + var i; + var child; + var tabNum = 0; + for (i = 0; i < tabs.childNodes.length; i++) { + child = tabs.childNodes.item(i); + if (child.nodeType === 1) { + if (child === tab) { + return tabNum; + } + tabNum++; + } + } +//#JSCOVERAGE_IF 0 + throw "Tab not found"; +//#JSCOVERAGE_ENDIF +} + +function jscoverage_tab_click(e) { + if (jscoverage_inLengthyOperation) { + return; + } + var target; +//#JSCOVERAGE_IF + if (e) { + target = e.target; + } + else if (window.event) { + // IE + target = window.event.srcElement; + } + if (target.className === 'selected') { + return; + } + jscoverage_beginLengthyOperation(); + setTimeout(function() { + if (target.id === 'summaryTab') { + var tbody = document.getElementById("summaryTbody"); + while (tbody.hasChildNodes()) { + tbody.removeChild(tbody.firstChild); + } + } + else if (target.id === 'sourceTab') { + var sourceDiv = document.getElementById('sourceDiv'); + sourceDiv.innerHTML = ''; + } + jscoverage_selectTab(target); + if (target.id === 'summaryTab') { + jscoverage_recalculateSummaryTab(); + } + else if (target.id === 'sourceTab') { + jscoverage_recalculateSourceTab(); + } + else { + jscoverage_endLengthyOperation(); + } + }, 50); +} + +// ----------------------------------------------------------------------------- +// progress bar + +var ProgressBar = { + init: function(element) { + element._percentage = 0; + + /* doing this via JavaScript crashes Safari */ +/* + var pctGraph = document.createElement('div'); + pctGraph.className = 'pctGraph'; + element.appendChild(pctGraph); + var covered = document.createElement('div'); + covered.className = 'covered'; + pctGraph.appendChild(covered); + var pct = document.createElement('span'); + pct.className = 'pct'; + element.appendChild(pct); +*/ + + ProgressBar._update(element); + }, + setPercentage: function(element, percentage) { + element._percentage = percentage; + ProgressBar._update(element); + }, + _update: function(element) { + var pctGraph = element.getElementsByTagName('div').item(0); + var covered = pctGraph.getElementsByTagName('div').item(0); + var pct = element.getElementsByTagName('span').item(0); + pct.innerHTML = element._percentage.toString() + '%'; + covered.style.width = element._percentage + 'px'; + } +}; + +// ----------------------------------------------------------------------------- +// reports + +function jscoverage_pad(s) { + return '0000'.substr(s.length) + s; +} + +function jscoverage_quote(s) { + return '"' + s.replace(/[\u0000-\u001f"\\\u007f-\uffff]/g, function (c) { + switch (c) { + case '\b': + return '\\b'; + case '\f': + return '\\f'; + case '\n': + return '\\n'; + case '\r': + return '\\r'; + case '\t': + return '\\t'; + // IE doesn't support this + /* + case '\v': + return '\\v'; + */ + case '"': + return '\\"'; + case '\\': + return '\\\\'; + default: + return '\\u' + jscoverage_pad(c.charCodeAt(0).toString(16)); + } + }) + '"'; +} + +function jscoverage_serializeCoverageToJSON() { + var json = []; + for (var file in _$jscoverage) { + if (! _$jscoverage.hasOwnProperty(file)) { + continue; + } + + var coverage = _$jscoverage[file]; + + var array = []; + var length = coverage.length; + for (var line = 0; line < length; line++) { + var value = coverage[line]; + if (value === undefined || value === null) { + value = 'null'; + } + array.push(value); + } + + var source = coverage.source; + var lines = []; + length = source.length; + for (var line = 0; line < length; line++) { + lines.push(jscoverage_quote(source[line])); + } + + json.push(jscoverage_quote(file) + ':{"coverage":[' + array.join(',') + '],"source":[' + lines.join(',') + ']}'); + } + return '{' + json.join(',') + '}'; +} + +function jscoverage_storeButton_click() { + if (jscoverage_inLengthyOperation) { + return; + } + + jscoverage_beginLengthyOperation(); + var img = document.getElementById('storeImg'); + img.style.visibility = 'visible'; + + var request = jscoverage_createRequest(); + request.open('POST', '/jscoverage-store', true); + request.onreadystatechange = function (event) { + if (request.readyState === 4) { + var message; + try { + if (request.status !== 200 && request.status !== 201 && request.status !== 204) { + throw request.status; + } + message = request.responseText; + } + catch (e) { + if (e.toString().search(/^\d{3}$/) === 0) { + message = e + ': ' + request.responseText; + } + else { + message = 'Could not connect to server: ' + e; + } + } + + jscoverage_endLengthyOperation(); + var img = document.getElementById('storeImg'); + img.style.visibility = 'hidden'; + + var div = document.getElementById('storeDiv'); + div.appendChild(document.createTextNode(new Date() + ': ' + message)); + div.appendChild(document.createElement('br')); + } + }; + request.setRequestHeader('Content-Type', 'application/json'); + var json = jscoverage_serializeCoverageToJSON(); + request.setRequestHeader('Content-Length', json.length.toString()); + request.send(json); +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/anchor.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/anchor.js new file mode 100644 index 000000000..09dd629c7 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/anchor.js @@ -0,0 +1,146 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/anchor.js']) { + _$jscoverage['plugins/anchor.js'] = []; + _$jscoverage['plugins/anchor.js'][7] = 0; + _$jscoverage['plugins/anchor.js'][8] = 0; + _$jscoverage['plugins/anchor.js'][10] = 0; + _$jscoverage['plugins/anchor.js'][11] = 0; + _$jscoverage['plugins/anchor.js'][17] = 0; + _$jscoverage['plugins/anchor.js'][18] = 0; + _$jscoverage['plugins/anchor.js'][19] = 0; + _$jscoverage['plugins/anchor.js'][20] = 0; + _$jscoverage['plugins/anchor.js'][21] = 0; + _$jscoverage['plugins/anchor.js'][22] = 0; + _$jscoverage['plugins/anchor.js'][30] = 0; + _$jscoverage['plugins/anchor.js'][31] = 0; + _$jscoverage['plugins/anchor.js'][32] = 0; + _$jscoverage['plugins/anchor.js'][33] = 0; + _$jscoverage['plugins/anchor.js'][34] = 0; + _$jscoverage['plugins/anchor.js'][35] = 0; + _$jscoverage['plugins/anchor.js'][39] = 0; + _$jscoverage['plugins/anchor.js'][57] = 0; + _$jscoverage['plugins/anchor.js'][59] = 0; + _$jscoverage['plugins/anchor.js'][60] = 0; + _$jscoverage['plugins/anchor.js'][61] = 0; + _$jscoverage['plugins/anchor.js'][62] = 0; + _$jscoverage['plugins/anchor.js'][64] = 0; + _$jscoverage['plugins/anchor.js'][65] = 0; + _$jscoverage['plugins/anchor.js'][68] = 0; + _$jscoverage['plugins/anchor.js'][70] = 0; + _$jscoverage['plugins/anchor.js'][71] = 0; + _$jscoverage['plugins/anchor.js'][72] = 0; + _$jscoverage['plugins/anchor.js'][76] = 0; +} +_$jscoverage['plugins/anchor.js'].source = ["/**"," * 锚点插件,为UEditor提供插入锚点支持"," * @file"," * @since 1.2.6.1"," */","","UE.plugins['anchor'] = function (){"," var me = this;",""," me.ready(function(){"," utils.cssRule('anchor',"," '.anchorclass{background: url(\\''"," + me.options.UEDITOR_HOME_URL +"," 'themes/default/images/anchor.gif\\') no-repeat scroll left center transparent;border: 1px dotted #0000FF;cursor: auto;display: inline-block;height: 16px;width: 15px;}',"," me.document)"," });"," me.addOutputRule(function(root){"," utils.each(root.getNodesByTagName('img'),function(a){"," var val;"," if(val = a.getAttr('anchorname')){"," a.tagName = 'a';"," a.setAttr({"," anchorname : '',"," name : val,"," 'class' : ''"," })"," }"," })"," });"," me.addInputRule(function(root){"," utils.each(root.getNodesByTagName('a'),function(a){"," var val;"," if((val = a.getAttr('name')) && !a.getAttr('href')){"," a.tagName = 'img';"," a.setAttr({"," anchorname :a.getAttr('name'),"," 'class' : 'anchorclass'"," });"," a.setAttr('name')",""," }"," })"," });",""," /**"," * 插入锚点"," * @command anchor"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param { String } name 锚点名称字符串"," * @example"," * ```javascript"," * //editor 是编辑器实例"," * editor.execCommand('anchor', 'anchor1');"," * ```"," */"," me.commands['anchor'] = {"," execCommand:function (cmd, name) {"," var range = this.selection.getRange(),img = range.getClosedNode();"," if (img && img.getAttribute('anchorname')) {"," if (name) {"," img.setAttribute('anchorname', name);"," } else {"," range.setStartBefore(img).setCursor();"," domUtils.remove(img);"," }"," } else {"," if (name) {"," //只在选区的开始插入"," var anchor = this.document.createElement('img');"," range.collapse(true);"," domUtils.setAttributes(anchor,{"," 'anchorname':name,"," 'class':'anchorclass'"," });"," range.insertNode(anchor).setStartAfter(anchor).setCursor(false,true);"," }"," }"," }",""," };","","","};"]; +_$jscoverage['plugins/anchor.js'][7]++; +UE.plugins.anchor = (function () { + _$jscoverage['plugins/anchor.js'][8]++; + var me = this; + _$jscoverage['plugins/anchor.js'][10]++; + me.ready((function () { + _$jscoverage['plugins/anchor.js'][11]++; + utils.cssRule("anchor", (".anchorclass{background: url('" + me.options.UEDITOR_HOME_URL + "themes/default/images/anchor.gif') no-repeat scroll left center transparent;border: 1px dotted #0000FF;cursor: auto;display: inline-block;height: 16px;width: 15px;}"), me.document); +})); + _$jscoverage['plugins/anchor.js'][17]++; + me.addOutputRule((function (root) { + _$jscoverage['plugins/anchor.js'][18]++; + utils.each(root.getNodesByTagName("img"), (function (a) { + _$jscoverage['plugins/anchor.js'][19]++; + var val; + _$jscoverage['plugins/anchor.js'][20]++; + if ((val = a.getAttr("anchorname"))) { + _$jscoverage['plugins/anchor.js'][21]++; + a.tagName = "a"; + _$jscoverage['plugins/anchor.js'][22]++; + a.setAttr({anchorname: "", name: val, "class": ""}); + } +})); +})); + _$jscoverage['plugins/anchor.js'][30]++; + me.addInputRule((function (root) { + _$jscoverage['plugins/anchor.js'][31]++; + utils.each(root.getNodesByTagName("a"), (function (a) { + _$jscoverage['plugins/anchor.js'][32]++; + var val; + _$jscoverage['plugins/anchor.js'][33]++; + if (((val = a.getAttr("name")) && (! a.getAttr("href")))) { + _$jscoverage['plugins/anchor.js'][34]++; + a.tagName = "img"; + _$jscoverage['plugins/anchor.js'][35]++; + a.setAttr({anchorname: a.getAttr("name"), "class": "anchorclass"}); + _$jscoverage['plugins/anchor.js'][39]++; + a.setAttr("name"); + } +})); +})); + _$jscoverage['plugins/anchor.js'][57]++; + me.commands.anchor = {execCommand: (function (cmd, name) { + _$jscoverage['plugins/anchor.js'][59]++; + var range = this.selection.getRange(), img = range.getClosedNode(); + _$jscoverage['plugins/anchor.js'][60]++; + if ((img && img.getAttribute("anchorname"))) { + _$jscoverage['plugins/anchor.js'][61]++; + if (name) { + _$jscoverage['plugins/anchor.js'][62]++; + img.setAttribute("anchorname", name); + } + else { + _$jscoverage['plugins/anchor.js'][64]++; + range.setStartBefore(img).setCursor(); + _$jscoverage['plugins/anchor.js'][65]++; + domUtils.remove(img); + } + } + else { + _$jscoverage['plugins/anchor.js'][68]++; + if (name) { + _$jscoverage['plugins/anchor.js'][70]++; + var anchor = this.document.createElement("img"); + _$jscoverage['plugins/anchor.js'][71]++; + range.collapse(true); + _$jscoverage['plugins/anchor.js'][72]++; + domUtils.setAttributes(anchor, {"anchorname": name, "class": "anchorclass"}); + _$jscoverage['plugins/anchor.js'][76]++; + range.insertNode(anchor).setStartAfter(anchor).setCursor(false, true); + } + } +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/autofloat.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/autofloat.js new file mode 100644 index 000000000..6cb09ad9c --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/autofloat.js @@ -0,0 +1,290 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/autofloat.js']) { + _$jscoverage['plugins/autofloat.js'] = []; + _$jscoverage['plugins/autofloat.js'][10] = 0; + _$jscoverage['plugins/autofloat.js'][11] = 0; + _$jscoverage['plugins/autofloat.js'][13] = 0; + _$jscoverage['plugins/autofloat.js'][16] = 0; + _$jscoverage['plugins/autofloat.js'][21] = 0; + _$jscoverage['plugins/autofloat.js'][22] = 0; + _$jscoverage['plugins/autofloat.js'][24] = 0; + _$jscoverage['plugins/autofloat.js'][28] = 0; + _$jscoverage['plugins/autofloat.js'][29] = 0; + _$jscoverage['plugins/autofloat.js'][30] = 0; + _$jscoverage['plugins/autofloat.js'][31] = 0; + _$jscoverage['plugins/autofloat.js'][33] = 0; + _$jscoverage['plugins/autofloat.js'][35] = 0; + _$jscoverage['plugins/autofloat.js'][36] = 0; + _$jscoverage['plugins/autofloat.js'][37] = 0; + _$jscoverage['plugins/autofloat.js'][38] = 0; + _$jscoverage['plugins/autofloat.js'][40] = 0; + _$jscoverage['plugins/autofloat.js'][45] = 0; + _$jscoverage['plugins/autofloat.js'][46] = 0; + _$jscoverage['plugins/autofloat.js'][49] = 0; + _$jscoverage['plugins/autofloat.js'][50] = 0; + _$jscoverage['plugins/autofloat.js'][51] = 0; + _$jscoverage['plugins/autofloat.js'][52] = 0; + _$jscoverage['plugins/autofloat.js'][53] = 0; + _$jscoverage['plugins/autofloat.js'][54] = 0; + _$jscoverage['plugins/autofloat.js'][56] = 0; + _$jscoverage['plugins/autofloat.js'][58] = 0; + _$jscoverage['plugins/autofloat.js'][59] = 0; + _$jscoverage['plugins/autofloat.js'][60] = 0; + _$jscoverage['plugins/autofloat.js'][62] = 0; + _$jscoverage['plugins/autofloat.js'][63] = 0; + _$jscoverage['plugins/autofloat.js'][64] = 0; + _$jscoverage['plugins/autofloat.js'][65] = 0; + _$jscoverage['plugins/autofloat.js'][69] = 0; + _$jscoverage['plugins/autofloat.js'][70] = 0; + _$jscoverage['plugins/autofloat.js'][71] = 0; + _$jscoverage['plugins/autofloat.js'][72] = 0; + _$jscoverage['plugins/autofloat.js'][74] = 0; + _$jscoverage['plugins/autofloat.js'][77] = 0; + _$jscoverage['plugins/autofloat.js'][78] = 0; + _$jscoverage['plugins/autofloat.js'][79] = 0; + _$jscoverage['plugins/autofloat.js'][80] = 0; + _$jscoverage['plugins/autofloat.js'][81] = 0; + _$jscoverage['plugins/autofloat.js'][83] = 0; + _$jscoverage['plugins/autofloat.js'][86] = 0; + _$jscoverage['plugins/autofloat.js'][87] = 0; + _$jscoverage['plugins/autofloat.js'][90] = 0; + _$jscoverage['plugins/autofloat.js'][91] = 0; + _$jscoverage['plugins/autofloat.js'][92] = 0; + _$jscoverage['plugins/autofloat.js'][95] = 0; + _$jscoverage['plugins/autofloat.js'][96] = 0; + _$jscoverage['plugins/autofloat.js'][98] = 0; + _$jscoverage['plugins/autofloat.js'][99] = 0; + _$jscoverage['plugins/autofloat.js'][100] = 0; + _$jscoverage['plugins/autofloat.js'][101] = 0; + _$jscoverage['plugins/autofloat.js'][102] = 0; + _$jscoverage['plugins/autofloat.js'][103] = 0; + _$jscoverage['plugins/autofloat.js'][104] = 0; + _$jscoverage['plugins/autofloat.js'][106] = 0; + _$jscoverage['plugins/autofloat.js'][107] = 0; + _$jscoverage['plugins/autofloat.js'][109] = 0; + _$jscoverage['plugins/autofloat.js'][110] = 0; + _$jscoverage['plugins/autofloat.js'][111] = 0; + _$jscoverage['plugins/autofloat.js'][114] = 0; + _$jscoverage['plugins/autofloat.js'][115] = 0; + _$jscoverage['plugins/autofloat.js'][116] = 0; + _$jscoverage['plugins/autofloat.js'][119] = 0; + _$jscoverage['plugins/autofloat.js'][120] = 0; + _$jscoverage['plugins/autofloat.js'][121] = 0; + _$jscoverage['plugins/autofloat.js'][124] = 0; + _$jscoverage['plugins/autofloat.js'][125] = 0; + _$jscoverage['plugins/autofloat.js'][126] = 0; +} +_$jscoverage['plugins/autofloat.js'].source = ["///import core","///commands 悬浮工具栏","///commandsName AutoFloat,autoFloatEnabled","///commandsTitle 悬浮工具栏","/*"," * modified by chengchao01"," *"," * 注意: 引入此功能后,在IE6下会将body的背景图片覆盖掉!"," */"," UE.plugins['autofloat'] = function() {"," var me = this,"," lang = me.getLang();"," me.setOpt({"," topOffset:0"," });"," var optsAutoFloatEnabled = me.options.autoFloatEnabled !== false,"," topOffset = me.options.topOffset;","",""," //如果不固定toolbar的位置,则直接退出"," if(!optsAutoFloatEnabled){"," return;"," }"," var uiUtils = UE.ui.uiUtils,"," \t\tLteIE6 = browser.ie && browser.version <= 6,"," quirks = browser.quirks;",""," function checkHasUI(){"," if(!UE.ui){"," alert(lang.autofloatMsg);"," return 0;"," }"," return 1;"," }"," function fixIE6FixedPos(){"," var docStyle = document.body.style;"," docStyle.backgroundImage = 'url(\"about:blank\")';"," docStyle.backgroundAttachment = 'fixed';"," }","\t\tvar\tbakCssText,","\t\t\tplaceHolder = document.createElement('div'),"," toolbarBox,orgTop,"," getPosition,"," flag =true; //ie7模式下需要偏移","\t\tfunction setFloating(){","\t\t\tvar toobarBoxPos = domUtils.getXY(toolbarBox),","\t\t\t\torigalFloat = domUtils.getComputedStyle(toolbarBox,'position'),"," origalLeft = domUtils.getComputedStyle(toolbarBox,'left');","\t\t\ttoolbarBox.style.width = toolbarBox.offsetWidth + 'px';"," toolbarBox.style.zIndex = me.options.zIndex * 1 + 1;","\t\t\ttoolbarBox.parentNode.insertBefore(placeHolder, toolbarBox);","\t\t\tif (LteIE6 || (quirks && browser.ie)) {"," if(toolbarBox.style.position != 'absolute'){"," toolbarBox.style.position = 'absolute';"," }"," toolbarBox.style.top = (document.body.scrollTop||document.documentElement.scrollTop) - orgTop + topOffset + 'px';","\t\t\t} else {"," if (browser.ie7Compat && flag) {"," flag = false;"," toolbarBox.style.left = domUtils.getXY(toolbarBox).x - document.documentElement.getBoundingClientRect().left+2 + 'px';"," }"," if(toolbarBox.style.position != 'fixed'){"," toolbarBox.style.position = 'fixed';"," toolbarBox.style.top = topOffset +\"px\";"," ((origalFloat == 'absolute' || origalFloat == 'relative') && parseFloat(origalLeft)) && (toolbarBox.style.left = toobarBoxPos.x + 'px');"," }","\t\t\t}","\t\t}","\t\tfunction unsetFloating(){"," flag = true;"," if(placeHolder.parentNode){"," placeHolder.parentNode.removeChild(placeHolder);"," }","\t\t\ttoolbarBox.style.cssText = bakCssText;","\t\t}",""," function updateFloating(){"," var rect3 = getPosition(me.container);"," var offset=me.options.toolbarTopOffset||0;"," if (rect3.top < 0 && rect3.bottom - toolbarBox.offsetHeight > offset) {"," setFloating();"," }else{"," unsetFloating();"," }"," }"," var defer_updateFloating = utils.defer(function(){"," updateFloating();"," },browser.ie ? 200 : 100,true);",""," me.addListener('destroy',function(){"," domUtils.un(window, ['scroll','resize'], updateFloating);"," me.removeListener('keydown', defer_updateFloating);"," });",""," me.addListener('ready', function(){"," if(checkHasUI(me)){",""," getPosition = uiUtils.getClientRect;"," toolbarBox = me.ui.getDom('toolbarbox');"," orgTop = getPosition(toolbarBox).top;"," bakCssText = toolbarBox.style.cssText;"," placeHolder.style.height = toolbarBox.offsetHeight + 'px';"," if(LteIE6){"," fixIE6FixedPos();"," }"," domUtils.on(window, ['scroll','resize'], updateFloating);"," me.addListener('keydown', defer_updateFloating);",""," me.addListener('beforefullscreenchange', function (t, enabled){"," if (enabled) {"," unsetFloating();"," }"," });"," me.addListener('fullscreenchanged', function (t, enabled){"," if (!enabled) {"," updateFloating();"," }"," });"," me.addListener('sourcemodechanged', function (t, enabled){"," setTimeout(function (){"," updateFloating();"," },0);"," });"," me.addListener(\"clearDoc\",function(){"," setTimeout(function(){"," updateFloating();"," },0);",""," })"," }"," });","\t};"]; +_$jscoverage['plugins/autofloat.js'][10]++; +UE.plugins.autofloat = (function () { + _$jscoverage['plugins/autofloat.js'][11]++; + var me = this, lang = me.getLang(); + _$jscoverage['plugins/autofloat.js'][13]++; + me.setOpt({topOffset: 0}); + _$jscoverage['plugins/autofloat.js'][16]++; + var optsAutoFloatEnabled = (me.options.autoFloatEnabled !== false), topOffset = me.options.topOffset; + _$jscoverage['plugins/autofloat.js'][21]++; + if ((! optsAutoFloatEnabled)) { + _$jscoverage['plugins/autofloat.js'][22]++; + return; + } + _$jscoverage['plugins/autofloat.js'][24]++; + var uiUtils = UE.ui.uiUtils, LteIE6 = (browser.ie && (browser.version <= 6)), quirks = browser.quirks; + _$jscoverage['plugins/autofloat.js'][28]++; + function checkHasUI() { + _$jscoverage['plugins/autofloat.js'][29]++; + if ((! UE.ui)) { + _$jscoverage['plugins/autofloat.js'][30]++; + alert(lang.autofloatMsg); + _$jscoverage['plugins/autofloat.js'][31]++; + return 0; + } + _$jscoverage['plugins/autofloat.js'][33]++; + return 1; +} + _$jscoverage['plugins/autofloat.js'][35]++; + function fixIE6FixedPos() { + _$jscoverage['plugins/autofloat.js'][36]++; + var docStyle = document.body.style; + _$jscoverage['plugins/autofloat.js'][37]++; + docStyle.backgroundImage = "url(\"about:blank\")"; + _$jscoverage['plugins/autofloat.js'][38]++; + docStyle.backgroundAttachment = "fixed"; +} + _$jscoverage['plugins/autofloat.js'][40]++; + var bakCssText, placeHolder = document.createElement("div"), toolbarBox, orgTop, getPosition, flag = true; + _$jscoverage['plugins/autofloat.js'][45]++; + function setFloating() { + _$jscoverage['plugins/autofloat.js'][46]++; + var toobarBoxPos = domUtils.getXY(toolbarBox), origalFloat = domUtils.getComputedStyle(toolbarBox, "position"), origalLeft = domUtils.getComputedStyle(toolbarBox, "left"); + _$jscoverage['plugins/autofloat.js'][49]++; + toolbarBox.style.width = (toolbarBox.offsetWidth + "px"); + _$jscoverage['plugins/autofloat.js'][50]++; + toolbarBox.style.zIndex = ((me.options.zIndex * 1) + 1); + _$jscoverage['plugins/autofloat.js'][51]++; + toolbarBox.parentNode.insertBefore(placeHolder, toolbarBox); + _$jscoverage['plugins/autofloat.js'][52]++; + if ((LteIE6 || (quirks && browser.ie))) { + _$jscoverage['plugins/autofloat.js'][53]++; + if ((toolbarBox.style.position != "absolute")) { + _$jscoverage['plugins/autofloat.js'][54]++; + toolbarBox.style.position = "absolute"; + } + _$jscoverage['plugins/autofloat.js'][56]++; + toolbarBox.style.top = (((document.body.scrollTop || document.documentElement.scrollTop) - orgTop) + topOffset + "px"); + } + else { + _$jscoverage['plugins/autofloat.js'][58]++; + if ((browser.ie7Compat && flag)) { + _$jscoverage['plugins/autofloat.js'][59]++; + flag = false; + _$jscoverage['plugins/autofloat.js'][60]++; + toolbarBox.style.left = ((domUtils.getXY(toolbarBox).x - document.documentElement.getBoundingClientRect().left) + 2 + "px"); + } + _$jscoverage['plugins/autofloat.js'][62]++; + if ((toolbarBox.style.position != "fixed")) { + _$jscoverage['plugins/autofloat.js'][63]++; + toolbarBox.style.position = "fixed"; + _$jscoverage['plugins/autofloat.js'][64]++; + toolbarBox.style.top = (topOffset + "px"); + _$jscoverage['plugins/autofloat.js'][65]++; + (((origalFloat == "absolute") || (origalFloat == "relative")) && parseFloat(origalLeft) && (toolbarBox.style.left = (toobarBoxPos.x + "px"))); + } + } +} + _$jscoverage['plugins/autofloat.js'][69]++; + function unsetFloating() { + _$jscoverage['plugins/autofloat.js'][70]++; + flag = true; + _$jscoverage['plugins/autofloat.js'][71]++; + if (placeHolder.parentNode) { + _$jscoverage['plugins/autofloat.js'][72]++; + placeHolder.parentNode.removeChild(placeHolder); + } + _$jscoverage['plugins/autofloat.js'][74]++; + toolbarBox.style.cssText = bakCssText; +} + _$jscoverage['plugins/autofloat.js'][77]++; + function updateFloating() { + _$jscoverage['plugins/autofloat.js'][78]++; + var rect3 = getPosition(me.container); + _$jscoverage['plugins/autofloat.js'][79]++; + var offset = (me.options.toolbarTopOffset || 0); + _$jscoverage['plugins/autofloat.js'][80]++; + if (((rect3.top < 0) && ((rect3.bottom - toolbarBox.offsetHeight) > offset))) { + _$jscoverage['plugins/autofloat.js'][81]++; + setFloating(); + } + else { + _$jscoverage['plugins/autofloat.js'][83]++; + unsetFloating(); + } +} + _$jscoverage['plugins/autofloat.js'][86]++; + var defer_updateFloating = utils.defer((function () { + _$jscoverage['plugins/autofloat.js'][87]++; + updateFloating(); +}), (browser.ie? 200: 100), true); + _$jscoverage['plugins/autofloat.js'][90]++; + me.addListener("destroy", (function () { + _$jscoverage['plugins/autofloat.js'][91]++; + domUtils.un(window, ["scroll", "resize"], updateFloating); + _$jscoverage['plugins/autofloat.js'][92]++; + me.removeListener("keydown", defer_updateFloating); +})); + _$jscoverage['plugins/autofloat.js'][95]++; + me.addListener("ready", (function () { + _$jscoverage['plugins/autofloat.js'][96]++; + if (checkHasUI(me)) { + _$jscoverage['plugins/autofloat.js'][98]++; + getPosition = uiUtils.getClientRect; + _$jscoverage['plugins/autofloat.js'][99]++; + toolbarBox = me.ui.getDom("toolbarbox"); + _$jscoverage['plugins/autofloat.js'][100]++; + orgTop = getPosition(toolbarBox).top; + _$jscoverage['plugins/autofloat.js'][101]++; + bakCssText = toolbarBox.style.cssText; + _$jscoverage['plugins/autofloat.js'][102]++; + placeHolder.style.height = (toolbarBox.offsetHeight + "px"); + _$jscoverage['plugins/autofloat.js'][103]++; + if (LteIE6) { + _$jscoverage['plugins/autofloat.js'][104]++; + fixIE6FixedPos(); + } + _$jscoverage['plugins/autofloat.js'][106]++; + domUtils.on(window, ["scroll", "resize"], updateFloating); + _$jscoverage['plugins/autofloat.js'][107]++; + me.addListener("keydown", defer_updateFloating); + _$jscoverage['plugins/autofloat.js'][109]++; + me.addListener("beforefullscreenchange", (function (t, enabled) { + _$jscoverage['plugins/autofloat.js'][110]++; + if (enabled) { + _$jscoverage['plugins/autofloat.js'][111]++; + unsetFloating(); + } +})); + _$jscoverage['plugins/autofloat.js'][114]++; + me.addListener("fullscreenchanged", (function (t, enabled) { + _$jscoverage['plugins/autofloat.js'][115]++; + if ((! enabled)) { + _$jscoverage['plugins/autofloat.js'][116]++; + updateFloating(); + } +})); + _$jscoverage['plugins/autofloat.js'][119]++; + me.addListener("sourcemodechanged", (function (t, enabled) { + _$jscoverage['plugins/autofloat.js'][120]++; + setTimeout((function () { + _$jscoverage['plugins/autofloat.js'][121]++; + updateFloating(); +}), 0); +})); + _$jscoverage['plugins/autofloat.js'][124]++; + me.addListener("clearDoc", (function () { + _$jscoverage['plugins/autofloat.js'][125]++; + setTimeout((function () { + _$jscoverage['plugins/autofloat.js'][126]++; + updateFloating(); +}), 0); +})); + } +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/autoheight.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/autoheight.js new file mode 100644 index 000000000..ba8195a94 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/autoheight.js @@ -0,0 +1,224 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/autoheight.js']) { + _$jscoverage['plugins/autoheight.js'] = []; + _$jscoverage['plugins/autoheight.js'][9] = 0; + _$jscoverage['plugins/autoheight.js'][10] = 0; + _$jscoverage['plugins/autoheight.js'][12] = 0; + _$jscoverage['plugins/autoheight.js'][13] = 0; + _$jscoverage['plugins/autoheight.js'][14] = 0; + _$jscoverage['plugins/autoheight.js'][17] = 0; + _$jscoverage['plugins/autoheight.js'][24] = 0; + _$jscoverage['plugins/autoheight.js'][25] = 0; + _$jscoverage['plugins/autoheight.js'][26] = 0; + _$jscoverage['plugins/autoheight.js'][27] = 0; + _$jscoverage['plugins/autoheight.js'][28] = 0; + _$jscoverage['plugins/autoheight.js'][29] = 0; + _$jscoverage['plugins/autoheight.js'][30] = 0; + _$jscoverage['plugins/autoheight.js'][31] = 0; + _$jscoverage['plugins/autoheight.js'][33] = 0; + _$jscoverage['plugins/autoheight.js'][34] = 0; + _$jscoverage['plugins/autoheight.js'][36] = 0; + _$jscoverage['plugins/autoheight.js'][37] = 0; + _$jscoverage['plugins/autoheight.js'][38] = 0; + _$jscoverage['plugins/autoheight.js'][39] = 0; + _$jscoverage['plugins/autoheight.js'][41] = 0; + _$jscoverage['plugins/autoheight.js'][43] = 0; + _$jscoverage['plugins/autoheight.js'][45] = 0; + _$jscoverage['plugins/autoheight.js'][50] = 0; + _$jscoverage['plugins/autoheight.js'][51] = 0; + _$jscoverage['plugins/autoheight.js'][52] = 0; + _$jscoverage['plugins/autoheight.js'][54] = 0; + _$jscoverage['plugins/autoheight.js'][55] = 0; + _$jscoverage['plugins/autoheight.js'][57] = 0; + _$jscoverage['plugins/autoheight.js'][58] = 0; + _$jscoverage['plugins/autoheight.js'][59] = 0; + _$jscoverage['plugins/autoheight.js'][60] = 0; + _$jscoverage['plugins/autoheight.js'][62] = 0; + _$jscoverage['plugins/autoheight.js'][63] = 0; + _$jscoverage['plugins/autoheight.js'][64] = 0; + _$jscoverage['plugins/autoheight.js'][65] = 0; + _$jscoverage['plugins/autoheight.js'][66] = 0; + _$jscoverage['plugins/autoheight.js'][69] = 0; + _$jscoverage['plugins/autoheight.js'][70] = 0; + _$jscoverage['plugins/autoheight.js'][72] = 0; + _$jscoverage['plugins/autoheight.js'][74] = 0; + _$jscoverage['plugins/autoheight.js'][76] = 0; + _$jscoverage['plugins/autoheight.js'][78] = 0; + _$jscoverage['plugins/autoheight.js'][79] = 0; + _$jscoverage['plugins/autoheight.js'][80] = 0; + _$jscoverage['plugins/autoheight.js'][81] = 0; + _$jscoverage['plugins/autoheight.js'][82] = 0; + _$jscoverage['plugins/autoheight.js'][84] = 0; + _$jscoverage['plugins/autoheight.js'][85] = 0; + _$jscoverage['plugins/autoheight.js'][87] = 0; + _$jscoverage['plugins/autoheight.js'][88] = 0; + _$jscoverage['plugins/autoheight.js'][89] = 0; + _$jscoverage['plugins/autoheight.js'][90] = 0; + _$jscoverage['plugins/autoheight.js'][91] = 0; +} +_$jscoverage['plugins/autoheight.js'].source = ["///import core","///commands 当输入内容超过编辑器高度时,编辑器自动增高","///commandsName AutoHeight,autoHeightEnabled","///commandsTitle 自动增高","/*"," * @description 自动伸展"," * @author zhanyi"," */","UE.plugins['autoheight'] = function () {"," var me = this;"," //提供开关,就算加载也可以关闭"," me.autoHeightEnabled = me.options.autoHeightEnabled !== false;"," if (!me.autoHeightEnabled) {"," return;"," }",""," var bakOverflow,"," span, tmpNode,"," lastHeight = 0,"," options = me.options,"," currentHeight,"," timer;",""," function adjustHeight() {"," var me = this;"," clearTimeout(timer);"," if(isFullscreen)return;"," timer = setTimeout(function () {"," if (!me.queryCommandState || me.queryCommandState && me.queryCommandState('source') != 1) {"," if (!span) {"," span = me.document.createElement('span');"," //trace:1764"," span.style.cssText = 'display:block;width:0;margin:0;padding:0;border:0;clear:both;';"," span.innerHTML = '.';"," }"," tmpNode = span.cloneNode(true);"," me.body.appendChild(tmpNode);"," currentHeight = Math.max(domUtils.getXY(tmpNode).y + tmpNode.offsetHeight,Math.max(options.minFrameHeight, options.initialFrameHeight));"," if (currentHeight != lastHeight) {",""," me.setHeight(currentHeight,true);",""," lastHeight = currentHeight;"," }"," domUtils.remove(tmpNode);",""," }"," }, 50);"," }"," var isFullscreen;"," me.addListener('fullscreenchanged',function(cmd,f){"," isFullscreen = f"," });"," me.addListener('destroy', function () {"," me.removeListener('contentchange afterinserthtml keyup mouseup',adjustHeight)"," });"," me.enableAutoHeight = function () {"," var me = this;"," if (!me.autoHeightEnabled) {"," return;"," }"," var doc = me.document;"," me.autoHeightEnabled = true;"," bakOverflow = doc.body.style.overflowY;"," doc.body.style.overflowY = 'hidden';"," me.addListener('contentchange afterinserthtml keyup mouseup',adjustHeight);"," //ff不给事件算得不对",""," setTimeout(function () {"," adjustHeight.call(me);"," }, browser.gecko ? 100 : 0);"," me.fireEvent('autoheightchanged', me.autoHeightEnabled);"," };"," me.disableAutoHeight = function () {",""," me.body.style.overflowY = bakOverflow || '';",""," me.removeListener('contentchange', adjustHeight);"," me.removeListener('keyup', adjustHeight);"," me.removeListener('mouseup', adjustHeight);"," me.autoHeightEnabled = false;"," me.fireEvent('autoheightchanged', me.autoHeightEnabled);"," };"," me.addListener('ready', function () {"," me.enableAutoHeight();"," //trace:1764"," var timer;"," domUtils.on(browser.ie ? me.body : me.document, browser.webkit ? 'dragover' : 'drop', function () {"," clearTimeout(timer);"," timer = setTimeout(function () {"," adjustHeight.call(this);"," }, 100);",""," });"," });","","","};",""]; +_$jscoverage['plugins/autoheight.js'][9]++; +UE.plugins.autoheight = (function () { + _$jscoverage['plugins/autoheight.js'][10]++; + var me = this; + _$jscoverage['plugins/autoheight.js'][12]++; + me.autoHeightEnabled = (me.options.autoHeightEnabled !== false); + _$jscoverage['plugins/autoheight.js'][13]++; + if ((! me.autoHeightEnabled)) { + _$jscoverage['plugins/autoheight.js'][14]++; + return; + } + _$jscoverage['plugins/autoheight.js'][17]++; + var bakOverflow, span, tmpNode, lastHeight = 0, options = me.options, currentHeight, timer; + _$jscoverage['plugins/autoheight.js'][24]++; + function adjustHeight() { + _$jscoverage['plugins/autoheight.js'][25]++; + var me = this; + _$jscoverage['plugins/autoheight.js'][26]++; + clearTimeout(timer); + _$jscoverage['plugins/autoheight.js'][27]++; + if (isFullscreen) { + _$jscoverage['plugins/autoheight.js'][27]++; + return; + } + _$jscoverage['plugins/autoheight.js'][28]++; + timer = setTimeout((function () { + _$jscoverage['plugins/autoheight.js'][29]++; + if (((! me.queryCommandState) || (me.queryCommandState && (me.queryCommandState("source") != 1)))) { + _$jscoverage['plugins/autoheight.js'][30]++; + if ((! span)) { + _$jscoverage['plugins/autoheight.js'][31]++; + span = me.document.createElement("span"); + _$jscoverage['plugins/autoheight.js'][33]++; + span.style.cssText = "display:block;width:0;margin:0;padding:0;border:0;clear:both;"; + _$jscoverage['plugins/autoheight.js'][34]++; + span.innerHTML = "."; + } + _$jscoverage['plugins/autoheight.js'][36]++; + tmpNode = span.cloneNode(true); + _$jscoverage['plugins/autoheight.js'][37]++; + me.body.appendChild(tmpNode); + _$jscoverage['plugins/autoheight.js'][38]++; + currentHeight = Math.max((domUtils.getXY(tmpNode).y + tmpNode.offsetHeight), Math.max(options.minFrameHeight, options.initialFrameHeight)); + _$jscoverage['plugins/autoheight.js'][39]++; + if ((currentHeight != lastHeight)) { + _$jscoverage['plugins/autoheight.js'][41]++; + me.setHeight(currentHeight, true); + _$jscoverage['plugins/autoheight.js'][43]++; + lastHeight = currentHeight; + } + _$jscoverage['plugins/autoheight.js'][45]++; + domUtils.remove(tmpNode); + } +}), 50); +} + _$jscoverage['plugins/autoheight.js'][50]++; + var isFullscreen; + _$jscoverage['plugins/autoheight.js'][51]++; + me.addListener("fullscreenchanged", (function (cmd, f) { + _$jscoverage['plugins/autoheight.js'][52]++; + isFullscreen = f; +})); + _$jscoverage['plugins/autoheight.js'][54]++; + me.addListener("destroy", (function () { + _$jscoverage['plugins/autoheight.js'][55]++; + me.removeListener("contentchange afterinserthtml keyup mouseup", adjustHeight); +})); + _$jscoverage['plugins/autoheight.js'][57]++; + me.enableAutoHeight = (function () { + _$jscoverage['plugins/autoheight.js'][58]++; + var me = this; + _$jscoverage['plugins/autoheight.js'][59]++; + if ((! me.autoHeightEnabled)) { + _$jscoverage['plugins/autoheight.js'][60]++; + return; + } + _$jscoverage['plugins/autoheight.js'][62]++; + var doc = me.document; + _$jscoverage['plugins/autoheight.js'][63]++; + me.autoHeightEnabled = true; + _$jscoverage['plugins/autoheight.js'][64]++; + bakOverflow = doc.body.style.overflowY; + _$jscoverage['plugins/autoheight.js'][65]++; + doc.body.style.overflowY = "hidden"; + _$jscoverage['plugins/autoheight.js'][66]++; + me.addListener("contentchange afterinserthtml keyup mouseup", adjustHeight); + _$jscoverage['plugins/autoheight.js'][69]++; + setTimeout((function () { + _$jscoverage['plugins/autoheight.js'][70]++; + adjustHeight.call(me); +}), (browser.gecko? 100: 0)); + _$jscoverage['plugins/autoheight.js'][72]++; + me.fireEvent("autoheightchanged", me.autoHeightEnabled); +}); + _$jscoverage['plugins/autoheight.js'][74]++; + me.disableAutoHeight = (function () { + _$jscoverage['plugins/autoheight.js'][76]++; + me.body.style.overflowY = (bakOverflow || ""); + _$jscoverage['plugins/autoheight.js'][78]++; + me.removeListener("contentchange", adjustHeight); + _$jscoverage['plugins/autoheight.js'][79]++; + me.removeListener("keyup", adjustHeight); + _$jscoverage['plugins/autoheight.js'][80]++; + me.removeListener("mouseup", adjustHeight); + _$jscoverage['plugins/autoheight.js'][81]++; + me.autoHeightEnabled = false; + _$jscoverage['plugins/autoheight.js'][82]++; + me.fireEvent("autoheightchanged", me.autoHeightEnabled); +}); + _$jscoverage['plugins/autoheight.js'][84]++; + me.addListener("ready", (function () { + _$jscoverage['plugins/autoheight.js'][85]++; + me.enableAutoHeight(); + _$jscoverage['plugins/autoheight.js'][87]++; + var timer; + _$jscoverage['plugins/autoheight.js'][88]++; + domUtils.on((browser.ie? me.body: me.document), (browser.webkit? "dragover": "drop"), (function () { + _$jscoverage['plugins/autoheight.js'][89]++; + clearTimeout(timer); + _$jscoverage['plugins/autoheight.js'][90]++; + timer = setTimeout((function () { + _$jscoverage['plugins/autoheight.js'][91]++; + adjustHeight.call(this); +}), 100); +})); +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/autolink.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/autolink.js new file mode 100644 index 000000000..e232a6180 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/autolink.js @@ -0,0 +1,246 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/autolink.js']) { + _$jscoverage['plugins/autolink.js'] = []; + _$jscoverage['plugins/autolink.js'][9] = 0; + _$jscoverage['plugins/autolink.js'][10] = 0; + _$jscoverage['plugins/autolink.js'][11] = 0; + _$jscoverage['plugins/autolink.js'][12] = 0; + _$jscoverage['plugins/autolink.js'][14] = 0; + _$jscoverage['plugins/autolink.js'][15] = 0; + _$jscoverage['plugins/autolink.js'][16] = 0; + _$jscoverage['plugins/autolink.js'][18] = 0; + _$jscoverage['plugins/autolink.js'][19] = 0; + _$jscoverage['plugins/autolink.js'][21] = 0; + _$jscoverage['plugins/autolink.js'][23] = 0; + _$jscoverage['plugins/autolink.js'][28] = 0; + _$jscoverage['plugins/autolink.js'][29] = 0; + _$jscoverage['plugins/autolink.js'][30] = 0; + _$jscoverage['plugins/autolink.js'][31] = 0; + _$jscoverage['plugins/autolink.js'][32] = 0; + _$jscoverage['plugins/autolink.js'][34] = 0; + _$jscoverage['plugins/autolink.js'][35] = 0; + _$jscoverage['plugins/autolink.js'][36] = 0; + _$jscoverage['plugins/autolink.js'][39] = 0; + _$jscoverage['plugins/autolink.js'][40] = 0; + _$jscoverage['plugins/autolink.js'][41] = 0; + _$jscoverage['plugins/autolink.js'][43] = 0; + _$jscoverage['plugins/autolink.js'][44] = 0; + _$jscoverage['plugins/autolink.js'][46] = 0; + _$jscoverage['plugins/autolink.js'][47] = 0; + _$jscoverage['plugins/autolink.js'][49] = 0; + _$jscoverage['plugins/autolink.js'][51] = 0; + _$jscoverage['plugins/autolink.js'][52] = 0; + _$jscoverage['plugins/autolink.js'][54] = 0; + _$jscoverage['plugins/autolink.js'][55] = 0; + _$jscoverage['plugins/autolink.js'][58] = 0; + _$jscoverage['plugins/autolink.js'][59] = 0; + _$jscoverage['plugins/autolink.js'][60] = 0; + _$jscoverage['plugins/autolink.js'][61] = 0; + _$jscoverage['plugins/autolink.js'][63] = 0; + _$jscoverage['plugins/autolink.js'][64] = 0; + _$jscoverage['plugins/autolink.js'][67] = 0; + _$jscoverage['plugins/autolink.js'][68] = 0; + _$jscoverage['plugins/autolink.js'][69] = 0; + _$jscoverage['plugins/autolink.js'][70] = 0; + _$jscoverage['plugins/autolink.js'][72] = 0; + _$jscoverage['plugins/autolink.js'][75] = 0; + _$jscoverage['plugins/autolink.js'][81] = 0; + _$jscoverage['plugins/autolink.js'][82] = 0; + _$jscoverage['plugins/autolink.js'][84] = 0; + _$jscoverage['plugins/autolink.js'][86] = 0; + _$jscoverage['plugins/autolink.js'][87] = 0; + _$jscoverage['plugins/autolink.js'][88] = 0; + _$jscoverage['plugins/autolink.js'][89] = 0; + _$jscoverage['plugins/autolink.js'][90] = 0; + _$jscoverage['plugins/autolink.js'][91] = 0; + _$jscoverage['plugins/autolink.js'][92] = 0; + _$jscoverage['plugins/autolink.js'][94] = 0; + _$jscoverage['plugins/autolink.js'][95] = 0; + _$jscoverage['plugins/autolink.js'][96] = 0; + _$jscoverage['plugins/autolink.js'][97] = 0; + _$jscoverage['plugins/autolink.js'][98] = 0; + _$jscoverage['plugins/autolink.js'][99] = 0; + _$jscoverage['plugins/autolink.js'][100] = 0; +} +_$jscoverage['plugins/autolink.js'].source = ["///import core","///commands 为非ie浏览器自动添加a标签","///commandsName AutoLink","///commandsTitle 自动增加链接","/*"," * @description 为非ie浏览器自动添加a标签"," * @author zhanyi"," */"," UE.plugins['autolink'] = function() {"," var cont = 0;"," if (browser.ie) {"," return;"," }"," var me = this;"," me.addListener('reset',function(){"," cont = 0;"," });"," me.addListener('keydown', function(type, evt) {"," var keyCode = evt.keyCode || evt.which;",""," if (keyCode == 32 || keyCode == 13) {",""," var sel = me.selection.getNative(),"," range = sel.getRangeAt(0).cloneRange(),"," offset,"," charCode;",""," var start = range.startContainer;"," while (start.nodeType == 1 && range.startOffset > 0) {"," start = range.startContainer.childNodes[range.startOffset - 1];"," if (!start){"," break;"," }"," range.setStart(start, start.nodeType == 1 ? start.childNodes.length : start.nodeValue.length);"," range.collapse(true);"," start = range.startContainer;"," }",""," do{"," if (range.startOffset == 0) {"," start = range.startContainer.previousSibling;",""," while (start && start.nodeType == 1) {"," start = start.lastChild;"," }"," if (!start || domUtils.isFillChar(start)){"," break;"," }"," offset = start.nodeValue.length;"," } else {"," start = range.startContainer;"," offset = range.startOffset;"," }"," range.setStart(start, offset - 1);"," charCode = range.toString().charCodeAt(0);"," } while (charCode != 160 && charCode != 32);",""," if (range.toString().replace(new RegExp(domUtils.fillChar, 'g'), '').match(/(?:https?:\\/\\/|ssh:\\/\\/|ftp:\\/\\/|file:\\/|www\\.)/i)) {"," while(range.toString().length){"," if(/^(?:https?:\\/\\/|ssh:\\/\\/|ftp:\\/\\/|file:\\/|www\\.)/i.test(range.toString())){"," break;"," }"," try{"," range.setStart(range.startContainer,range.startOffset+1);"," }catch(e){"," //trace:2121"," var start = range.startContainer;"," while(!(next = start.nextSibling)){"," if(domUtils.isBody(start)){"," return;"," }"," start = start.parentNode;",""," }"," range.setStart(next,0);",""," }",""," }"," //range的开始边界已经在a标签里的不再处理"," if(domUtils.findParentByTagName(range.startContainer,'a',true)){"," return;"," }"," var a = me.document.createElement('a'),text = me.document.createTextNode(' '),href;",""," me.undoManger && me.undoManger.save();"," a.appendChild(range.extractContents());"," a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g,'');"," href = a.getAttribute(\"href\").replace(new RegExp(domUtils.fillChar,'g'),'');"," href = /^(?:https?:\\/\\/)/ig.test(href) ? href : \"http://\"+ href;"," a.setAttribute('_src',utils.html(href));"," a.href = utils.html(href);",""," range.insertNode(a);"," a.parentNode.insertBefore(text, a.nextSibling);"," range.setStart(text, 0);"," range.collapse(true);"," sel.removeAllRanges();"," sel.addRange(range);"," me.undoManger && me.undoManger.save();"," }"," }"," });"," };"]; +_$jscoverage['plugins/autolink.js'][9]++; +UE.plugins.autolink = (function () { + _$jscoverage['plugins/autolink.js'][10]++; + var cont = 0; + _$jscoverage['plugins/autolink.js'][11]++; + if (browser.ie) { + _$jscoverage['plugins/autolink.js'][12]++; + return; + } + _$jscoverage['plugins/autolink.js'][14]++; + var me = this; + _$jscoverage['plugins/autolink.js'][15]++; + me.addListener("reset", (function () { + _$jscoverage['plugins/autolink.js'][16]++; + cont = 0; +})); + _$jscoverage['plugins/autolink.js'][18]++; + me.addListener("keydown", (function (type, evt) { + _$jscoverage['plugins/autolink.js'][19]++; + var keyCode = (evt.keyCode || evt.which); + _$jscoverage['plugins/autolink.js'][21]++; + if (((keyCode == 32) || (keyCode == 13))) { + _$jscoverage['plugins/autolink.js'][23]++; + var sel = me.selection.getNative(), range = sel.getRangeAt(0).cloneRange(), offset, charCode; + _$jscoverage['plugins/autolink.js'][28]++; + var start = range.startContainer; + _$jscoverage['plugins/autolink.js'][29]++; + while (((start.nodeType == 1) && (range.startOffset > 0))) { + _$jscoverage['plugins/autolink.js'][30]++; + start = range.startContainer.childNodes[(range.startOffset - 1)]; + _$jscoverage['plugins/autolink.js'][31]++; + if ((! start)) { + _$jscoverage['plugins/autolink.js'][32]++; + break; + } + _$jscoverage['plugins/autolink.js'][34]++; + range.setStart(start, ((start.nodeType == 1)? start.childNodes.length: start.nodeValue.length)); + _$jscoverage['plugins/autolink.js'][35]++; + range.collapse(true); + _$jscoverage['plugins/autolink.js'][36]++; + start = range.startContainer; +} + _$jscoverage['plugins/autolink.js'][39]++; + do { + _$jscoverage['plugins/autolink.js'][40]++; + if ((range.startOffset == 0)) { + _$jscoverage['plugins/autolink.js'][41]++; + start = range.startContainer.previousSibling; + _$jscoverage['plugins/autolink.js'][43]++; + while ((start && (start.nodeType == 1))) { + _$jscoverage['plugins/autolink.js'][44]++; + start = start.lastChild; +} + _$jscoverage['plugins/autolink.js'][46]++; + if (((! start) || domUtils.isFillChar(start))) { + _$jscoverage['plugins/autolink.js'][47]++; + break; + } + _$jscoverage['plugins/autolink.js'][49]++; + offset = start.nodeValue.length; + } + else { + _$jscoverage['plugins/autolink.js'][51]++; + start = range.startContainer; + _$jscoverage['plugins/autolink.js'][52]++; + offset = range.startOffset; + } + _$jscoverage['plugins/autolink.js'][54]++; + range.setStart(start, (offset - 1)); + _$jscoverage['plugins/autolink.js'][55]++; + charCode = range.toString().charCodeAt(0); +} + while (((charCode != 160) && (charCode != 32))); + _$jscoverage['plugins/autolink.js'][58]++; + if (range.toString().replace(new RegExp(domUtils.fillChar, "g"), "").match(/(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i)) { + _$jscoverage['plugins/autolink.js'][59]++; + while (range.toString().length) { + _$jscoverage['plugins/autolink.js'][60]++; + if (/^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i.test(range.toString())) { + _$jscoverage['plugins/autolink.js'][61]++; + break; + } + _$jscoverage['plugins/autolink.js'][63]++; + try { + _$jscoverage['plugins/autolink.js'][64]++; + range.setStart(range.startContainer, (range.startOffset + 1)); + } + catch (e) { + _$jscoverage['plugins/autolink.js'][67]++; + var start = range.startContainer; + _$jscoverage['plugins/autolink.js'][68]++; + while ((! (next = start.nextSibling))) { + _$jscoverage['plugins/autolink.js'][69]++; + if (domUtils.isBody(start)) { + _$jscoverage['plugins/autolink.js'][70]++; + return; + } + _$jscoverage['plugins/autolink.js'][72]++; + start = start.parentNode; +} + _$jscoverage['plugins/autolink.js'][75]++; + range.setStart(next, 0); + } +} + _$jscoverage['plugins/autolink.js'][81]++; + if (domUtils.findParentByTagName(range.startContainer, "a", true)) { + _$jscoverage['plugins/autolink.js'][82]++; + return; + } + _$jscoverage['plugins/autolink.js'][84]++; + var a = me.document.createElement("a"), text = me.document.createTextNode(" "), href; + _$jscoverage['plugins/autolink.js'][86]++; + (me.undoManger && me.undoManger.save()); + _$jscoverage['plugins/autolink.js'][87]++; + a.appendChild(range.extractContents()); + _$jscoverage['plugins/autolink.js'][88]++; + a.href = (a.innerHTML = a.innerHTML.replace(/<[^>]+>/g, "")); + _$jscoverage['plugins/autolink.js'][89]++; + href = a.getAttribute("href").replace(new RegExp(domUtils.fillChar, "g"), ""); + _$jscoverage['plugins/autolink.js'][90]++; + href = (/^(?:https?:\/\/)/gi.test(href)? href: ("http://" + href)); + _$jscoverage['plugins/autolink.js'][91]++; + a.setAttribute("_src", utils.html(href)); + _$jscoverage['plugins/autolink.js'][92]++; + a.href = utils.html(href); + _$jscoverage['plugins/autolink.js'][94]++; + range.insertNode(a); + _$jscoverage['plugins/autolink.js'][95]++; + a.parentNode.insertBefore(text, a.nextSibling); + _$jscoverage['plugins/autolink.js'][96]++; + range.setStart(text, 0); + _$jscoverage['plugins/autolink.js'][97]++; + range.collapse(true); + _$jscoverage['plugins/autolink.js'][98]++; + sel.removeAllRanges(); + _$jscoverage['plugins/autolink.js'][99]++; + sel.addRange(range); + _$jscoverage['plugins/autolink.js'][100]++; + (me.undoManger && me.undoManger.save()); + } + } +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/autosubmit.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/autosubmit.js new file mode 100644 index 000000000..72002947b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/autosubmit.js @@ -0,0 +1,77 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/autosubmit.js']) { + _$jscoverage['plugins/autosubmit.js'] = []; + _$jscoverage['plugins/autosubmit.js'][17] = 0; + _$jscoverage['plugins/autosubmit.js'][18] = 0; + _$jscoverage['plugins/autosubmit.js'][19] = 0; + _$jscoverage['plugins/autosubmit.js'][21] = 0; + _$jscoverage['plugins/autosubmit.js'][23] = 0; + _$jscoverage['plugins/autosubmit.js'][24] = 0; + _$jscoverage['plugins/autosubmit.js'][25] = 0; + _$jscoverage['plugins/autosubmit.js'][27] = 0; + _$jscoverage['plugins/autosubmit.js'][28] = 0; + _$jscoverage['plugins/autosubmit.js'][33] = 0; +} +_$jscoverage['plugins/autosubmit.js'].source = ["/**"," * 快捷键提交"," * @file"," * @since 1.2.6.1"," */","","/**"," * 对编辑器区域插入html字符串"," * @command autosubmit"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'autosubmit' );"," * ```"," */","UE.plugins['autosubmit'] = function(){"," var me = this;"," me.commands['autosubmit'] = {"," execCommand:function () {"," var me=this,"," form = domUtils.findParentByTagName(me.iframe,\"form\", false);"," if (form) {"," if(me.fireEvent(\"beforesubmit\")===false){"," return;"," }"," me.sync();"," form.submit();"," }"," }"," };"," //快捷键"," me.addshortcutkey({"," \"autosubmit\" : \"ctrl+13\" //手动提交"," });","};"]; +_$jscoverage['plugins/autosubmit.js'][17]++; +UE.plugins.autosubmit = (function () { + _$jscoverage['plugins/autosubmit.js'][18]++; + var me = this; + _$jscoverage['plugins/autosubmit.js'][19]++; + me.commands.autosubmit = {execCommand: (function () { + _$jscoverage['plugins/autosubmit.js'][21]++; + var me = this, form = domUtils.findParentByTagName(me.iframe, "form", false); + _$jscoverage['plugins/autosubmit.js'][23]++; + if (form) { + _$jscoverage['plugins/autosubmit.js'][24]++; + if ((me.fireEvent("beforesubmit") === false)) { + _$jscoverage['plugins/autosubmit.js'][25]++; + return; + } + _$jscoverage['plugins/autosubmit.js'][27]++; + me.sync(); + _$jscoverage['plugins/autosubmit.js'][28]++; + form.submit(); + } +})}; + _$jscoverage['plugins/autosubmit.js'][33]++; + me.addshortcutkey({"autosubmit": "ctrl+13"}); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/autotypeset.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/autotypeset.js new file mode 100644 index 000000000..86f561530 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/autotypeset.js @@ -0,0 +1,434 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/autotypeset.js']) { + _$jscoverage['plugins/autotypeset.js'] = []; + _$jscoverage['plugins/autotypeset.js'][11] = 0; + _$jscoverage['plugins/autotypeset.js'][13] = 0; + _$jscoverage['plugins/autotypeset.js'][28] = 0; + _$jscoverage['plugins/autotypeset.js'][47] = 0; + _$jscoverage['plugins/autotypeset.js'][48] = 0; + _$jscoverage['plugins/autotypeset.js'][50] = 0; + _$jscoverage['plugins/autotypeset.js'][51] = 0; + _$jscoverage['plugins/autotypeset.js'][52] = 0; + _$jscoverage['plugins/autotypeset.js'][53] = 0; + _$jscoverage['plugins/autotypeset.js'][54] = 0; + _$jscoverage['plugins/autotypeset.js'][55] = 0; + _$jscoverage['plugins/autotypeset.js'][56] = 0; + _$jscoverage['plugins/autotypeset.js'][60] = 0; + _$jscoverage['plugins/autotypeset.js'][63] = 0; + _$jscoverage['plugins/autotypeset.js'][68] = 0; + _$jscoverage['plugins/autotypeset.js'][69] = 0; + _$jscoverage['plugins/autotypeset.js'][70] = 0; + _$jscoverage['plugins/autotypeset.js'][71] = 0; + _$jscoverage['plugins/autotypeset.js'][72] = 0; + _$jscoverage['plugins/autotypeset.js'][76] = 0; + _$jscoverage['plugins/autotypeset.js'][77] = 0; + _$jscoverage['plugins/autotypeset.js'][78] = 0; + _$jscoverage['plugins/autotypeset.js'][79] = 0; + _$jscoverage['plugins/autotypeset.js'][80] = 0; + _$jscoverage['plugins/autotypeset.js'][82] = 0; + _$jscoverage['plugins/autotypeset.js'][83] = 0; + _$jscoverage['plugins/autotypeset.js'][85] = 0; + _$jscoverage['plugins/autotypeset.js'][87] = 0; + _$jscoverage['plugins/autotypeset.js'][90] = 0; + _$jscoverage['plugins/autotypeset.js'][92] = 0; + _$jscoverage['plugins/autotypeset.js'][93] = 0; + _$jscoverage['plugins/autotypeset.js'][96] = 0; + _$jscoverage['plugins/autotypeset.js'][97] = 0; + _$jscoverage['plugins/autotypeset.js'][99] = 0; + _$jscoverage['plugins/autotypeset.js'][103] = 0; + _$jscoverage['plugins/autotypeset.js'][104] = 0; + _$jscoverage['plugins/autotypeset.js'][105] = 0; + _$jscoverage['plugins/autotypeset.js'][108] = 0; + _$jscoverage['plugins/autotypeset.js'][110] = 0; + _$jscoverage['plugins/autotypeset.js'][111] = 0; + _$jscoverage['plugins/autotypeset.js'][112] = 0; + _$jscoverage['plugins/autotypeset.js'][113] = 0; + _$jscoverage['plugins/autotypeset.js'][114] = 0; + _$jscoverage['plugins/autotypeset.js'][115] = 0; + _$jscoverage['plugins/autotypeset.js'][116] = 0; + _$jscoverage['plugins/autotypeset.js'][118] = 0; + _$jscoverage['plugins/autotypeset.js'][123] = 0; + _$jscoverage['plugins/autotypeset.js'][124] = 0; + _$jscoverage['plugins/autotypeset.js'][125] = 0; + _$jscoverage['plugins/autotypeset.js'][126] = 0; + _$jscoverage['plugins/autotypeset.js'][127] = 0; + _$jscoverage['plugins/autotypeset.js'][130] = 0; + _$jscoverage['plugins/autotypeset.js'][131] = 0; + _$jscoverage['plugins/autotypeset.js'][136] = 0; + _$jscoverage['plugins/autotypeset.js'][137] = 0; + _$jscoverage['plugins/autotypeset.js'][138] = 0; + _$jscoverage['plugins/autotypeset.js'][140] = 0; + _$jscoverage['plugins/autotypeset.js'][141] = 0; + _$jscoverage['plugins/autotypeset.js'][150] = 0; + _$jscoverage['plugins/autotypeset.js'][152] = 0; + _$jscoverage['plugins/autotypeset.js'][153] = 0; + _$jscoverage['plugins/autotypeset.js'][155] = 0; + _$jscoverage['plugins/autotypeset.js'][159] = 0; + _$jscoverage['plugins/autotypeset.js'][160] = 0; + _$jscoverage['plugins/autotypeset.js'][161] = 0; + _$jscoverage['plugins/autotypeset.js'][162] = 0; + _$jscoverage['plugins/autotypeset.js'][166] = 0; + _$jscoverage['plugins/autotypeset.js'][167] = 0; + _$jscoverage['plugins/autotypeset.js'][168] = 0; + _$jscoverage['plugins/autotypeset.js'][170] = 0; + _$jscoverage['plugins/autotypeset.js'][171] = 0; + _$jscoverage['plugins/autotypeset.js'][172] = 0; + _$jscoverage['plugins/autotypeset.js'][173] = 0; + _$jscoverage['plugins/autotypeset.js'][174] = 0; + _$jscoverage['plugins/autotypeset.js'][175] = 0; + _$jscoverage['plugins/autotypeset.js'][176] = 0; + _$jscoverage['plugins/autotypeset.js'][177] = 0; + _$jscoverage['plugins/autotypeset.js'][178] = 0; + _$jscoverage['plugins/autotypeset.js'][180] = 0; + _$jscoverage['plugins/autotypeset.js'][181] = 0; + _$jscoverage['plugins/autotypeset.js'][183] = 0; + _$jscoverage['plugins/autotypeset.js'][191] = 0; + _$jscoverage['plugins/autotypeset.js'][192] = 0; + _$jscoverage['plugins/autotypeset.js'][194] = 0; + _$jscoverage['plugins/autotypeset.js'][195] = 0; + _$jscoverage['plugins/autotypeset.js'][196] = 0; + _$jscoverage['plugins/autotypeset.js'][197] = 0; + _$jscoverage['plugins/autotypeset.js'][198] = 0; + _$jscoverage['plugins/autotypeset.js'][200] = 0; + _$jscoverage['plugins/autotypeset.js'][201] = 0; + _$jscoverage['plugins/autotypeset.js'][203] = 0; + _$jscoverage['plugins/autotypeset.js'][204] = 0; + _$jscoverage['plugins/autotypeset.js'][208] = 0; + _$jscoverage['plugins/autotypeset.js'][209] = 0; + _$jscoverage['plugins/autotypeset.js'][210] = 0; + _$jscoverage['plugins/autotypeset.js'][217] = 0; + _$jscoverage['plugins/autotypeset.js'][218] = 0; + _$jscoverage['plugins/autotypeset.js'][219] = 0; + _$jscoverage['plugins/autotypeset.js'][227] = 0; + _$jscoverage['plugins/autotypeset.js'][228] = 0; + _$jscoverage['plugins/autotypeset.js'][229] = 0; + _$jscoverage['plugins/autotypeset.js'][233] = 0; + _$jscoverage['plugins/autotypeset.js'][234] = 0; + _$jscoverage['plugins/autotypeset.js'][237] = 0; + _$jscoverage['plugins/autotypeset.js'][238] = 0; + _$jscoverage['plugins/autotypeset.js'][241] = 0; + _$jscoverage['plugins/autotypeset.js'][243] = 0; + _$jscoverage['plugins/autotypeset.js'][244] = 0; + _$jscoverage['plugins/autotypeset.js'][245] = 0; + _$jscoverage['plugins/autotypeset.js'][247] = 0; +} +_$jscoverage['plugins/autotypeset.js'].source = ["///import core","///commands 自动排版","///commandsName autotypeset","///commandsTitle 自动排版","/*"," * 自动排版"," * @function"," * @name baidu.editor.execCommands"," */","","UE.plugins['autotypeset'] = function(){",""," this.setOpt({'autotypeset':{"," mergeEmptyline : true, //合并空行"," removeClass : true, //去掉冗余的class"," removeEmptyline : false, //去掉空行"," textAlign : \"left\", //段落的排版方式,可以是 left,right,center,justify 去掉这个属性表示不执行排版"," imageBlockLine : 'center', //图片的浮动方式,独占一行剧中,左右浮动,默认: center,left,right,none 去掉这个属性表示不执行排版"," pasteFilter : false, //根据规则过滤没事粘贴进来的内容"," clearFontSize : false, //去掉所有的内嵌字号,使用编辑器默认的字号"," clearFontFamily : false, //去掉所有的内嵌字体,使用编辑器默认的字体"," removeEmptyNode : false, // 去掉空节点"," //可以去掉的标签"," removeTagNames : utils.extend({div:1},dtd.$removeEmpty),"," indent : false, // 行首缩进"," indentValue : '2em' //行首缩进的大小"," }});"," var me = this,"," opt = me.options.autotypeset,"," remainClass = {"," 'selectTdClass':1,"," 'pagebreak':1,"," 'anchorclass':1"," },"," remainTag = {"," 'li':1"," },"," tags = {"," div:1,"," p:1,"," //trace:2183 这些也认为是行"," blockquote:1,center:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,"," span:1"," },"," highlightCont;"," //升级了版本,但配置项目里没有autotypeset"," if(!opt){"," return;"," }"," function isLine(node,notEmpty){"," if(!node || node.nodeType == 3)"," return 0;"," if(domUtils.isBr(node))"," return 1;"," if(node && node.parentNode && tags[node.tagName.toLowerCase()]){"," if(highlightCont && highlightCont.contains(node)"," ||"," node.getAttribute('pagebreak')"," ){"," return 0;"," }",""," return notEmpty ? !domUtils.isEmptyBlock(node) : domUtils.isEmptyBlock(node,new RegExp('[\\\\s'+domUtils.fillChar"," +']','g'));"," }"," }",""," function removeNotAttributeSpan(node){"," if(!node.style.cssText){"," domUtils.removeAttributes(node,['style']);"," if(node.tagName.toLowerCase() == 'span' && domUtils.hasNoAttributes(node)){"," domUtils.remove(node,true);"," }"," }"," }"," function autotype(type,html){"," var me = this,cont;"," if(html){"," if(!opt.pasteFilter){"," return;"," }"," cont = me.document.createElement('div');"," cont.innerHTML = html.html;"," }else{"," cont = me.document.body;"," }"," var nodes = domUtils.getElementsByTagName(cont,'*');",""," // 行首缩进,段落方向,段间距,段内间距"," for(var i=0,ci;ci=nodes[i++];){",""," if(me.fireEvent('excludeNodeinautotype',ci) === true){"," continue;"," }"," //font-size"," if(opt.clearFontSize && ci.style.fontSize){"," domUtils.removeStyle(ci,'font-size');",""," removeNotAttributeSpan(ci);",""," }"," //font-family"," if(opt.clearFontFamily && ci.style.fontFamily){"," domUtils.removeStyle(ci,'font-family');"," removeNotAttributeSpan(ci);"," }",""," if(isLine(ci)){"," //合并空行"," if(opt.mergeEmptyline ){"," var next = ci.nextSibling,tmpNode,isBr = domUtils.isBr(ci);"," while(isLine(next)){"," tmpNode = next;"," next = tmpNode.nextSibling;"," if(isBr && (!next || next && !domUtils.isBr(next))){"," break;"," }"," domUtils.remove(tmpNode);"," }",""," }"," //去掉空行,保留占位的空行"," if(opt.removeEmptyline && domUtils.inDoc(ci,cont) && !remainTag[ci.parentNode.tagName.toLowerCase()] ){"," if(domUtils.isBr(ci)){"," next = ci.nextSibling;"," if(next && !domUtils.isBr(next)){"," continue;"," }"," }"," domUtils.remove(ci);"," continue;",""," }",""," }"," if(isLine(ci,true) && ci.tagName != 'SPAN'){"," if(opt.indent){"," ci.style.textIndent = opt.indentValue;"," }"," if(opt.textAlign){"," ci.style.textAlign = opt.textAlign;"," }","// if(opt.lineHeight)","// ci.style.lineHeight = opt.lineHeight + 'cm';","",""," }",""," //去掉class,保留的class不去掉"," if(opt.removeClass && ci.className && !remainClass[ci.className.toLowerCase()]){",""," if(highlightCont && highlightCont.contains(ci)){"," continue;"," }"," domUtils.removeAttributes(ci,['class']);"," }",""," //表情不处理"," if(opt.imageBlockLine && ci.tagName.toLowerCase() == 'img' && !ci.getAttribute('emotion')){"," if(html){"," var img = ci;"," switch (opt.imageBlockLine){"," case 'left':"," case 'right':"," case 'none':"," var pN = img.parentNode,tmpNode,pre,next;"," while(dtd.$inline[pN.tagName] || pN.tagName == 'A'){"," pN = pN.parentNode;"," }"," tmpNode = pN;"," if(tmpNode.tagName == 'P' && domUtils.getStyle(tmpNode,'text-align') == 'center'){"," if(!domUtils.isBody(tmpNode) && domUtils.getChildCount(tmpNode,function(node){return !domUtils.isBr(node) && !domUtils.isWhitespace(node)}) == 1){"," pre = tmpNode.previousSibling;"," next = tmpNode.nextSibling;"," if(pre && next && pre.nodeType == 1 && next.nodeType == 1 && pre.tagName == next.tagName && domUtils.isBlockElm(pre)){"," pre.appendChild(tmpNode.firstChild);"," while(next.firstChild){"," pre.appendChild(next.firstChild);"," }"," domUtils.remove(tmpNode);"," domUtils.remove(next);"," }else{"," domUtils.setStyle(tmpNode,'text-align','');"," }","",""," }","",""," }"," domUtils.setStyle(img,'float',opt.imageBlockLine);"," break;"," case 'center':"," if(me.queryCommandValue('imagefloat') != 'center'){"," pN = img.parentNode;"," domUtils.setStyle(img,'float','none');"," tmpNode = img;"," while(pN && domUtils.getChildCount(pN,function(node){return !domUtils.isBr(node) && !domUtils.isWhitespace(node)}) == 1"," && (dtd.$inline[pN.tagName] || pN.tagName == 'A')){"," tmpNode = pN;"," pN = pN.parentNode;"," }"," var pNode = me.document.createElement('p');"," domUtils.setAttributes(pNode,{",""," style:'text-align:center'"," });"," tmpNode.parentNode.insertBefore(pNode,tmpNode);"," pNode.appendChild(tmpNode);"," domUtils.setStyle(tmpNode,'float','');",""," }","",""," }"," }else{"," var range = me.selection.getRange();"," range.selectNode(ci).select();"," me.execCommand('imagefloat',opt.imageBlockLine);"," }","","",""," }",""," //去掉冗余的标签"," if(opt.removeEmptyNode){"," if(opt.removeTagNames[ci.tagName.toLowerCase()] && domUtils.hasNoAttributes(ci) && domUtils.isEmptyBlock(ci)){"," domUtils.remove(ci);"," }"," }"," }"," if(html){"," html.html = cont.innerHTML;"," }"," }"," if(opt.pasteFilter){"," me.addListener('beforepaste',autotype);"," }",""," me.commands['autotypeset'] = {"," execCommand:function () {"," me.removeListener('beforepaste',autotype);"," if(opt.pasteFilter){"," me.addListener('beforepaste',autotype);"," }"," autotype.call(me)"," }",""," };","","};",""]; +_$jscoverage['plugins/autotypeset.js'][11]++; +UE.plugins.autotypeset = (function () { + _$jscoverage['plugins/autotypeset.js'][13]++; + this.setOpt({"autotypeset": {mergeEmptyline: true, removeClass: true, removeEmptyline: false, textAlign: "left", imageBlockLine: "center", pasteFilter: false, clearFontSize: false, clearFontFamily: false, removeEmptyNode: false, removeTagNames: utils.extend({div: 1}, dtd.$removeEmpty), indent: false, indentValue: "2em"}}); + _$jscoverage['plugins/autotypeset.js'][28]++; + var me = this, opt = me.options.autotypeset, remainClass = {"selectTdClass": 1, "pagebreak": 1, "anchorclass": 1}, remainTag = {"li": 1}, tags = {div: 1, p: 1, blockquote: 1, center: 1, h1: 1, h2: 1, h3: 1, h4: 1, h5: 1, h6: 1, span: 1}, highlightCont; + _$jscoverage['plugins/autotypeset.js'][47]++; + if ((! opt)) { + _$jscoverage['plugins/autotypeset.js'][48]++; + return; + } + _$jscoverage['plugins/autotypeset.js'][50]++; + function isLine(node, notEmpty) { + _$jscoverage['plugins/autotypeset.js'][51]++; + if (((! node) || (node.nodeType == 3))) { + _$jscoverage['plugins/autotypeset.js'][52]++; + return 0; + } + _$jscoverage['plugins/autotypeset.js'][53]++; + if (domUtils.isBr(node)) { + _$jscoverage['plugins/autotypeset.js'][54]++; + return 1; + } + _$jscoverage['plugins/autotypeset.js'][55]++; + if ((node && node.parentNode && tags[node.tagName.toLowerCase()])) { + _$jscoverage['plugins/autotypeset.js'][56]++; + if (((highlightCont && highlightCont.contains(node)) || node.getAttribute("pagebreak"))) { + _$jscoverage['plugins/autotypeset.js'][60]++; + return 0; + } + _$jscoverage['plugins/autotypeset.js'][63]++; + return (notEmpty? (! domUtils.isEmptyBlock(node)): domUtils.isEmptyBlock(node, new RegExp(("[\\s" + domUtils.fillChar + "]"), "g"))); + } +} + _$jscoverage['plugins/autotypeset.js'][68]++; + function removeNotAttributeSpan(node) { + _$jscoverage['plugins/autotypeset.js'][69]++; + if ((! node.style.cssText)) { + _$jscoverage['plugins/autotypeset.js'][70]++; + domUtils.removeAttributes(node, ["style"]); + _$jscoverage['plugins/autotypeset.js'][71]++; + if (((node.tagName.toLowerCase() == "span") && domUtils.hasNoAttributes(node))) { + _$jscoverage['plugins/autotypeset.js'][72]++; + domUtils.remove(node, true); + } + } +} + _$jscoverage['plugins/autotypeset.js'][76]++; + function autotype(type, html) { + _$jscoverage['plugins/autotypeset.js'][77]++; + var me = this, cont; + _$jscoverage['plugins/autotypeset.js'][78]++; + if (html) { + _$jscoverage['plugins/autotypeset.js'][79]++; + if ((! opt.pasteFilter)) { + _$jscoverage['plugins/autotypeset.js'][80]++; + return; + } + _$jscoverage['plugins/autotypeset.js'][82]++; + cont = me.document.createElement("div"); + _$jscoverage['plugins/autotypeset.js'][83]++; + cont.innerHTML = html.html; + } + else { + _$jscoverage['plugins/autotypeset.js'][85]++; + cont = me.document.body; + } + _$jscoverage['plugins/autotypeset.js'][87]++; + var nodes = domUtils.getElementsByTagName(cont, "*"); + _$jscoverage['plugins/autotypeset.js'][90]++; + for (var i = 0, ci; (ci = nodes[(i++)]);) { + _$jscoverage['plugins/autotypeset.js'][92]++; + if ((me.fireEvent("excludeNodeinautotype", ci) === true)) { + _$jscoverage['plugins/autotypeset.js'][93]++; + continue; + } + _$jscoverage['plugins/autotypeset.js'][96]++; + if ((opt.clearFontSize && ci.style.fontSize)) { + _$jscoverage['plugins/autotypeset.js'][97]++; + domUtils.removeStyle(ci, "font-size"); + _$jscoverage['plugins/autotypeset.js'][99]++; + removeNotAttributeSpan(ci); + } + _$jscoverage['plugins/autotypeset.js'][103]++; + if ((opt.clearFontFamily && ci.style.fontFamily)) { + _$jscoverage['plugins/autotypeset.js'][104]++; + domUtils.removeStyle(ci, "font-family"); + _$jscoverage['plugins/autotypeset.js'][105]++; + removeNotAttributeSpan(ci); + } + _$jscoverage['plugins/autotypeset.js'][108]++; + if (isLine(ci)) { + _$jscoverage['plugins/autotypeset.js'][110]++; + if (opt.mergeEmptyline) { + _$jscoverage['plugins/autotypeset.js'][111]++; + var next = ci.nextSibling, tmpNode, isBr = domUtils.isBr(ci); + _$jscoverage['plugins/autotypeset.js'][112]++; + while (isLine(next)) { + _$jscoverage['plugins/autotypeset.js'][113]++; + tmpNode = next; + _$jscoverage['plugins/autotypeset.js'][114]++; + next = tmpNode.nextSibling; + _$jscoverage['plugins/autotypeset.js'][115]++; + if ((isBr && ((! next) || (next && (! domUtils.isBr(next)))))) { + _$jscoverage['plugins/autotypeset.js'][116]++; + break; + } + _$jscoverage['plugins/autotypeset.js'][118]++; + domUtils.remove(tmpNode); +} + } + _$jscoverage['plugins/autotypeset.js'][123]++; + if ((opt.removeEmptyline && domUtils.inDoc(ci, cont) && (! remainTag[ci.parentNode.tagName.toLowerCase()]))) { + _$jscoverage['plugins/autotypeset.js'][124]++; + if (domUtils.isBr(ci)) { + _$jscoverage['plugins/autotypeset.js'][125]++; + next = ci.nextSibling; + _$jscoverage['plugins/autotypeset.js'][126]++; + if ((next && (! domUtils.isBr(next)))) { + _$jscoverage['plugins/autotypeset.js'][127]++; + continue; + } + } + _$jscoverage['plugins/autotypeset.js'][130]++; + domUtils.remove(ci); + _$jscoverage['plugins/autotypeset.js'][131]++; + continue; + } + } + _$jscoverage['plugins/autotypeset.js'][136]++; + if ((isLine(ci, true) && (ci.tagName != "SPAN"))) { + _$jscoverage['plugins/autotypeset.js'][137]++; + if (opt.indent) { + _$jscoverage['plugins/autotypeset.js'][138]++; + ci.style.textIndent = opt.indentValue; + } + _$jscoverage['plugins/autotypeset.js'][140]++; + if (opt.textAlign) { + _$jscoverage['plugins/autotypeset.js'][141]++; + ci.style.textAlign = opt.textAlign; + } + } + _$jscoverage['plugins/autotypeset.js'][150]++; + if ((opt.removeClass && ci.className && (! remainClass[ci.className.toLowerCase()]))) { + _$jscoverage['plugins/autotypeset.js'][152]++; + if ((highlightCont && highlightCont.contains(ci))) { + _$jscoverage['plugins/autotypeset.js'][153]++; + continue; + } + _$jscoverage['plugins/autotypeset.js'][155]++; + domUtils.removeAttributes(ci, ["class"]); + } + _$jscoverage['plugins/autotypeset.js'][159]++; + if ((opt.imageBlockLine && (ci.tagName.toLowerCase() == "img") && (! ci.getAttribute("emotion")))) { + _$jscoverage['plugins/autotypeset.js'][160]++; + if (html) { + _$jscoverage['plugins/autotypeset.js'][161]++; + var img = ci; + _$jscoverage['plugins/autotypeset.js'][162]++; + switch (opt.imageBlockLine) { + case "left": + case "right": + case "none": + _$jscoverage['plugins/autotypeset.js'][166]++; + var pN = img.parentNode, tmpNode = tmpNode, pre, next = next; + _$jscoverage['plugins/autotypeset.js'][167]++; + while ((dtd.$inline[pN.tagName] || (pN.tagName == "A"))) { + _$jscoverage['plugins/autotypeset.js'][168]++; + pN = pN.parentNode; +} + _$jscoverage['plugins/autotypeset.js'][170]++; + tmpNode = pN; + _$jscoverage['plugins/autotypeset.js'][171]++; + if (((tmpNode.tagName == "P") && (domUtils.getStyle(tmpNode, "text-align") == "center"))) { + _$jscoverage['plugins/autotypeset.js'][172]++; + if (((! domUtils.isBody(tmpNode)) && (domUtils.getChildCount(tmpNode, (function (node) { + _$jscoverage['plugins/autotypeset.js'][172]++; + return ((! domUtils.isBr(node)) && (! domUtils.isWhitespace(node))); +})) == 1))) { + _$jscoverage['plugins/autotypeset.js'][173]++; + pre = tmpNode.previousSibling; + _$jscoverage['plugins/autotypeset.js'][174]++; + next = tmpNode.nextSibling; + _$jscoverage['plugins/autotypeset.js'][175]++; + if ((pre && next && (pre.nodeType == 1) && (next.nodeType == 1) && (pre.tagName == next.tagName) && domUtils.isBlockElm(pre))) { + _$jscoverage['plugins/autotypeset.js'][176]++; + pre.appendChild(tmpNode.firstChild); + _$jscoverage['plugins/autotypeset.js'][177]++; + while (next.firstChild) { + _$jscoverage['plugins/autotypeset.js'][178]++; + pre.appendChild(next.firstChild); +} + _$jscoverage['plugins/autotypeset.js'][180]++; + domUtils.remove(tmpNode); + _$jscoverage['plugins/autotypeset.js'][181]++; + domUtils.remove(next); + } + else { + _$jscoverage['plugins/autotypeset.js'][183]++; + domUtils.setStyle(tmpNode, "text-align", ""); + } + } + } + _$jscoverage['plugins/autotypeset.js'][191]++; + domUtils.setStyle(img, "float", opt.imageBlockLine); + _$jscoverage['plugins/autotypeset.js'][192]++; + break; + case "center": + _$jscoverage['plugins/autotypeset.js'][194]++; + if ((me.queryCommandValue("imagefloat") != "center")) { + _$jscoverage['plugins/autotypeset.js'][195]++; + pN = img.parentNode; + _$jscoverage['plugins/autotypeset.js'][196]++; + domUtils.setStyle(img, "float", "none"); + _$jscoverage['plugins/autotypeset.js'][197]++; + tmpNode = img; + _$jscoverage['plugins/autotypeset.js'][198]++; + while ((pN && (domUtils.getChildCount(pN, (function (node) { + _$jscoverage['plugins/autotypeset.js'][198]++; + return ((! domUtils.isBr(node)) && (! domUtils.isWhitespace(node))); +})) == 1) && (dtd.$inline[pN.tagName] || (pN.tagName == "A")))) { + _$jscoverage['plugins/autotypeset.js'][200]++; + tmpNode = pN; + _$jscoverage['plugins/autotypeset.js'][201]++; + pN = pN.parentNode; +} + _$jscoverage['plugins/autotypeset.js'][203]++; + var pNode = me.document.createElement("p"); + _$jscoverage['plugins/autotypeset.js'][204]++; + domUtils.setAttributes(pNode, {style: "text-align:center"}); + _$jscoverage['plugins/autotypeset.js'][208]++; + tmpNode.parentNode.insertBefore(pNode, tmpNode); + _$jscoverage['plugins/autotypeset.js'][209]++; + pNode.appendChild(tmpNode); + _$jscoverage['plugins/autotypeset.js'][210]++; + domUtils.setStyle(tmpNode, "float", ""); + } + } + } + else { + _$jscoverage['plugins/autotypeset.js'][217]++; + var range = me.selection.getRange(); + _$jscoverage['plugins/autotypeset.js'][218]++; + range.selectNode(ci).select(); + _$jscoverage['plugins/autotypeset.js'][219]++; + me.execCommand("imagefloat", opt.imageBlockLine); + } + } + _$jscoverage['plugins/autotypeset.js'][227]++; + if (opt.removeEmptyNode) { + _$jscoverage['plugins/autotypeset.js'][228]++; + if ((opt.removeTagNames[ci.tagName.toLowerCase()] && domUtils.hasNoAttributes(ci) && domUtils.isEmptyBlock(ci))) { + _$jscoverage['plugins/autotypeset.js'][229]++; + domUtils.remove(ci); + } + } +} + _$jscoverage['plugins/autotypeset.js'][233]++; + if (html) { + _$jscoverage['plugins/autotypeset.js'][234]++; + html.html = cont.innerHTML; + } +} + _$jscoverage['plugins/autotypeset.js'][237]++; + if (opt.pasteFilter) { + _$jscoverage['plugins/autotypeset.js'][238]++; + me.addListener("beforepaste", autotype); + } + _$jscoverage['plugins/autotypeset.js'][241]++; + me.commands.autotypeset = {execCommand: (function () { + _$jscoverage['plugins/autotypeset.js'][243]++; + me.removeListener("beforepaste", autotype); + _$jscoverage['plugins/autotypeset.js'][244]++; + if (opt.pasteFilter) { + _$jscoverage['plugins/autotypeset.js'][245]++; + me.addListener("beforepaste", autotype); + } + _$jscoverage['plugins/autotypeset.js'][247]++; + autotype.call(me); +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/background.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/background.js new file mode 100644 index 000000000..a36521711 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/background.js @@ -0,0 +1,92 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/background.js']) { + _$jscoverage['plugins/background.js'] = []; + _$jscoverage['plugins/background.js'][6] = 0; + _$jscoverage['plugins/background.js'][7] = 0; + _$jscoverage['plugins/background.js'][8] = 0; + _$jscoverage['plugins/background.js'][9] = 0; + _$jscoverage['plugins/background.js'][12] = 0; + _$jscoverage['plugins/background.js'][13] = 0; + _$jscoverage['plugins/background.js'][15] = 0; + _$jscoverage['plugins/background.js'][17] = 0; + _$jscoverage['plugins/background.js'][18] = 0; + _$jscoverage['plugins/background.js'][25] = 0; + _$jscoverage['plugins/background.js'][26] = 0; + _$jscoverage['plugins/background.js'][27] = 0; + _$jscoverage['plugins/background.js'][30] = 0; + _$jscoverage['plugins/background.js'][31] = 0; +} +_$jscoverage['plugins/background.js'].source = ["///import core","///commands 插入背景","///commandsName background","///commandsTitle 插入背景","///commandsDialog dialogs\\background","UE.plugins['background'] = function(){"," var me = this;"," me.addListener(\"getAllHtml\",function(type,headHtml){"," var body = this.body,"," su = domUtils.getComputedStyle(body,\"background-image\"),"," url=\"\";"," if(su.indexOf(me.options.imagePath)>0){"," url = su.substring(su.indexOf(me.options.imagePath),su.length-1).replace(/\"|\\(|\\)/ig,\"\");"," }else{"," url = su!=\"none\" ? su.replace(/url\\(\"?|\"?\\)/ig,\"\"):\"\";"," }"," var html = '<style type=\"text/css\">body{';"," var bgObj = {"," \"background-color\" : domUtils.getComputedStyle(body,\"background-color\")||\"#ffffff\","," 'background-image' : url ? 'url('+url+')' : '',"," 'background-repeat':domUtils.getComputedStyle(body,\"background-repeat\")||\"\","," 'background-position': browser.ie?(domUtils.getComputedStyle(body,\"background-position-x\")+\" \"+domUtils.getComputedStyle(body,\"background-position-y\")):domUtils.getComputedStyle(body,\"background-position\"),"," 'height':domUtils.getComputedStyle(body,\"height\")"," };"," for ( var name in bgObj ) {"," if ( bgObj.hasOwnProperty( name ) ) {"," html += name+\":\"+bgObj[name]+\";\";"," }"," }"," html += '}</style> ';"," headHtml.push(html);"," });","}"]; +_$jscoverage['plugins/background.js'][6]++; +UE.plugins.background = (function () { + _$jscoverage['plugins/background.js'][7]++; + var me = this; + _$jscoverage['plugins/background.js'][8]++; + me.addListener("getAllHtml", (function (type, headHtml) { + _$jscoverage['plugins/background.js'][9]++; + var body = this.body, su = domUtils.getComputedStyle(body, "background-image"), url = ""; + _$jscoverage['plugins/background.js'][12]++; + if ((su.indexOf(me.options.imagePath) > 0)) { + _$jscoverage['plugins/background.js'][13]++; + url = su.substring(su.indexOf(me.options.imagePath), (su.length - 1)).replace(/"|\(|\)/gi, ""); + } + else { + _$jscoverage['plugins/background.js'][15]++; + url = ((su != "none")? su.replace(/url\("?|"?\)/gi, ""): ""); + } + _$jscoverage['plugins/background.js'][17]++; + var html = " "; + _$jscoverage['plugins/background.js'][31]++; + headHtml.push(html); +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/basestyle.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/basestyle.js new file mode 100644 index 000000000..5022b1b24 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/basestyle.js @@ -0,0 +1,159 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/basestyle.js']) { + _$jscoverage['plugins/basestyle.js'] = []; + _$jscoverage['plugins/basestyle.js'][7] = 0; + _$jscoverage['plugins/basestyle.js'][138] = 0; + _$jscoverage['plugins/basestyle.js'][145] = 0; + _$jscoverage['plugins/basestyle.js'][149] = 0; + _$jscoverage['plugins/basestyle.js'][154] = 0; + _$jscoverage['plugins/basestyle.js'][155] = 0; + _$jscoverage['plugins/basestyle.js'][156] = 0; + _$jscoverage['plugins/basestyle.js'][158] = 0; + _$jscoverage['plugins/basestyle.js'][159] = 0; + _$jscoverage['plugins/basestyle.js'][161] = 0; + _$jscoverage['plugins/basestyle.js'][165] = 0; + _$jscoverage['plugins/basestyle.js'][166] = 0; + _$jscoverage['plugins/basestyle.js'][167] = 0; + _$jscoverage['plugins/basestyle.js'][169] = 0; + _$jscoverage['plugins/basestyle.js'][170] = 0; + _$jscoverage['plugins/basestyle.js'][171] = 0; + _$jscoverage['plugins/basestyle.js'][172] = 0; + _$jscoverage['plugins/basestyle.js'][173] = 0; + _$jscoverage['plugins/basestyle.js'][174] = 0; + _$jscoverage['plugins/basestyle.js'][175] = 0; + _$jscoverage['plugins/basestyle.js'][177] = 0; + _$jscoverage['plugins/basestyle.js'][178] = 0; + _$jscoverage['plugins/basestyle.js'][179] = 0; + _$jscoverage['plugins/basestyle.js'][180] = 0; + _$jscoverage['plugins/basestyle.js'][185] = 0; + _$jscoverage['plugins/basestyle.js'][187] = 0; + _$jscoverage['plugins/basestyle.js'][189] = 0; + _$jscoverage['plugins/basestyle.js'][190] = 0; + _$jscoverage['plugins/basestyle.js'][191] = 0; + _$jscoverage['plugins/basestyle.js'][194] = 0; + _$jscoverage['plugins/basestyle.js'][196] = 0; + _$jscoverage['plugins/basestyle.js'][199] = 0; +} +_$jscoverage['plugins/basestyle.js'].source = ["/**"," * B、I、sub、super命令支持"," * @file"," * @since 1.2.6.1"," */","","UE.plugins['basestyle'] = function(){",""," /**"," * 字体加粗, 对已加粗的文本内容执行该命令, 将取消加粗"," * @command bold"," * @param { String } cmd 命令字符串"," * @method execCommand"," * @example"," * ```javascript"," * //editor是编辑器实例"," * //对当前选中的文本内容执行加粗操作"," * //第一次执行, 文本内容加粗"," * editor.execCommand( 'bold' );"," *"," * //第二次执行, 文本内容取消加粗"," * editor.execCommand( 'bold' );"," * ```"," */",""," /**"," * 获取当前选中的文本内容的加粗状态"," * @command bold"," * @param { String } cmd 命令字符串"," * @method queryCommandState"," * @return { int } 如果当前选中的所有文本内容已经被加粗, 则返回1, 否则返回0"," * @example"," * ```javascript"," * //editor是编辑器实例"," * //获取当前选中的文本内容的加粗状态"," * //output: 1 或者 0"," * console.log( editor.queryCommandState( 'bold' ) );"," * ```"," */",""," /**"," * 字体倾斜, 对已倾斜的文本内容执行该命令, 将取消倾斜"," * @command italic"," * @param { String } cmd 命令字符串"," * @method execCommand"," * @example"," * ```javascript"," * //editor是编辑器实例"," * //对当前选中的文本内容执行斜体操作"," * //第一次操作, 文本内容将变成斜体"," * editor.execCommand( 'italic' );"," *"," * //再次对同一文本内容执行, 则文本内容将恢复正常"," * editor.execCommand( 'italic' );"," * ```"," */",""," /**"," * 获取当前选中的文本内容的倾斜状态"," * @command italic"," * @method queryCommandState"," * @param { String } cmd 命令字符串"," * @return { int } 如果当前选中的所有文本内容已经是斜体, 则返回1, 否则返回0"," * @example"," * ```javascript"," * //editor是编辑器实例"," * //获取当前选中的文本内容的倾斜状态"," * //output: 1 或者 0"," * console.log( editor.queryCommandState( 'italic' ) );"," * ```"," */",""," /**"," * 下标文本, 把选中的文本内容切换成下标文本, 如果当前选中的文本已经是下标, 则该操作会把文本内容还原成"," * 正常文本"," * @command subscript"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * //editor是编辑器实例"," * //对当前选中的文本内容执行下标操作"," * //第一次操作, 文本内容将变成下标文本"," * editor.execCommand( 'subscript' );"," *"," * //再次对同一文本内容执行, 则文本内容将恢复正常"," * editor.execCommand( 'subscript' );"," * ```"," */",""," /**"," * 获取当前选中的文本内容的下标状态"," * @command subscript"," * @method queryCommandState"," * @param { String } cmd 命令字符串"," * @return { int } 如果当前选中的所有文本内容已经是下标文本, 则返回1, 否则返回0"," * @example"," * ```javascript"," * //editor是编辑器实例"," * //获取当前选中的文本内容的下标状态"," * //output: 1 或者 0"," * console.log( editor.queryCommandState( 'subscript' ) );"," * ```"," */",""," /**"," * 上标文本, 把选中的文本内容切换成上标文本, 如果当前选中的文本已经是上标, 则该操作会把文本内容还原成"," * 正常文本"," * @command superscript"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * //editor是编辑器实例"," * //对当前选中的文本内容执行上标操作"," * //第一次操作, 文本内容将变成上标文本"," * editor.execCommand( 'superscript' );"," *"," * //再次对同一文本内容执行, 则文本内容将恢复正常"," * editor.execCommand( 'superscript' );"," * ```"," */",""," /**"," * 获取当前选中的文本内容的上标状态"," * @command superscript"," * @method queryCommandState"," * @param { String } cmd 命令字符串"," * @return { int } 如果当前选中的所有文本内容已经是上标文本, 则返回1, 否则返回0"," * @example"," * ```javascript"," * //editor是编辑器实例"," * //获取当前选中的文本内容的上标状态"," * //output: 1 或者 0"," * console.log( editor.queryCommandState( 'superscript' ) );"," * ```"," */"," var basestyles = {"," 'bold':['strong','b'],"," 'italic':['em','i'],"," 'subscript':['sub'],"," 'superscript':['sup']"," },"," getObj = function(editor,tagNames){"," return domUtils.filterNodeList(editor.selection.getStartElementPath(),tagNames);"," },"," me = this;"," //添加快捷键"," me.addshortcutkey({"," \"Bold\" : \"ctrl+66\",//^B"," \"Italic\" : \"ctrl+73\", //^I"," \"Underline\" : \"ctrl+85\"//^U"," });"," me.addInputRule(function(root){"," utils.each(root.getNodesByTagName('b i'),function(node){"," switch (node.tagName){"," case 'b':"," node.tagName = 'strong';"," break;"," case 'i':"," node.tagName = 'em';"," }"," });"," });"," for ( var style in basestyles ) {"," (function( cmd, tagNames ) {"," me.commands[cmd] = {"," execCommand : function( cmdName ) {"," var range = me.selection.getRange(),obj = getObj(this,tagNames);"," if ( range.collapsed ) {"," if ( obj ) {"," var tmpText = me.document.createTextNode('');"," range.insertNode( tmpText ).removeInlineStyle( tagNames );"," range.setStartBefore(tmpText);"," domUtils.remove(tmpText);"," } else {"," var tmpNode = range.document.createElement( tagNames[0] );"," if(cmdName == 'superscript' || cmdName == 'subscript'){"," tmpText = me.document.createTextNode('');"," range.insertNode(tmpText)"," .removeInlineStyle(['sub','sup'])"," .setStartBefore(tmpText)"," .collapse(true);"," }"," range.insertNode( tmpNode ).setStart( tmpNode, 0 );"," }"," range.collapse( true );"," } else {"," if(cmdName == 'superscript' || cmdName == 'subscript'){"," if(!obj || obj.tagName.toLowerCase() != cmdName){"," range.removeInlineStyle(['sub','sup']);"," }"," }"," obj ? range.removeInlineStyle( tagNames ) : range.applyInlineStyle( tagNames[0] );"," }"," range.select();"," },"," queryCommandState : function() {"," return getObj(this,tagNames) ? 1 : 0;"," }"," };"," })( style, basestyles[style] );"," }","};",""]; +_$jscoverage['plugins/basestyle.js'][7]++; +UE.plugins.basestyle = (function () { + _$jscoverage['plugins/basestyle.js'][138]++; + var basestyles = {"bold": ["strong", "b"], "italic": ["em", "i"], "subscript": ["sub"], "superscript": ["sup"]}, getObj = (function (editor, tagNames) { + _$jscoverage['plugins/basestyle.js'][145]++; + return domUtils.filterNodeList(editor.selection.getStartElementPath(), tagNames); +}), me = this; + _$jscoverage['plugins/basestyle.js'][149]++; + me.addshortcutkey({"Bold": "ctrl+66", "Italic": "ctrl+73", "Underline": "ctrl+85"}); + _$jscoverage['plugins/basestyle.js'][154]++; + me.addInputRule((function (root) { + _$jscoverage['plugins/basestyle.js'][155]++; + utils.each(root.getNodesByTagName("b i"), (function (node) { + _$jscoverage['plugins/basestyle.js'][156]++; + switch (node.tagName) { + case "b": + _$jscoverage['plugins/basestyle.js'][158]++; + node.tagName = "strong"; + _$jscoverage['plugins/basestyle.js'][159]++; + break; + case "i": + _$jscoverage['plugins/basestyle.js'][161]++; + node.tagName = "em"; + } +})); +})); + _$jscoverage['plugins/basestyle.js'][165]++; + for (var style in basestyles) { + _$jscoverage['plugins/basestyle.js'][166]++; + (function (cmd, tagNames) { + _$jscoverage['plugins/basestyle.js'][167]++; + me.commands[cmd] = {execCommand: (function (cmdName) { + _$jscoverage['plugins/basestyle.js'][169]++; + var range = me.selection.getRange(), obj = getObj(this, tagNames); + _$jscoverage['plugins/basestyle.js'][170]++; + if (range.collapsed) { + _$jscoverage['plugins/basestyle.js'][171]++; + if (obj) { + _$jscoverage['plugins/basestyle.js'][172]++; + var tmpText = me.document.createTextNode(""); + _$jscoverage['plugins/basestyle.js'][173]++; + range.insertNode(tmpText).removeInlineStyle(tagNames); + _$jscoverage['plugins/basestyle.js'][174]++; + range.setStartBefore(tmpText); + _$jscoverage['plugins/basestyle.js'][175]++; + domUtils.remove(tmpText); + } + else { + _$jscoverage['plugins/basestyle.js'][177]++; + var tmpNode = range.document.createElement(tagNames[0]); + _$jscoverage['plugins/basestyle.js'][178]++; + if (((cmdName == "superscript") || (cmdName == "subscript"))) { + _$jscoverage['plugins/basestyle.js'][179]++; + tmpText = me.document.createTextNode(""); + _$jscoverage['plugins/basestyle.js'][180]++; + range.insertNode(tmpText).removeInlineStyle(["sub", "sup"]).setStartBefore(tmpText).collapse(true); + } + _$jscoverage['plugins/basestyle.js'][185]++; + range.insertNode(tmpNode).setStart(tmpNode, 0); + } + _$jscoverage['plugins/basestyle.js'][187]++; + range.collapse(true); + } + else { + _$jscoverage['plugins/basestyle.js'][189]++; + if (((cmdName == "superscript") || (cmdName == "subscript"))) { + _$jscoverage['plugins/basestyle.js'][190]++; + if (((! obj) || (obj.tagName.toLowerCase() != cmdName))) { + _$jscoverage['plugins/basestyle.js'][191]++; + range.removeInlineStyle(["sub", "sup"]); + } + } + _$jscoverage['plugins/basestyle.js'][194]++; + (obj? range.removeInlineStyle(tagNames): range.applyInlineStyle(tagNames[0])); + } + _$jscoverage['plugins/basestyle.js'][196]++; + range.select(); +}), queryCommandState: (function () { + _$jscoverage['plugins/basestyle.js'][199]++; + return (getObj(this, tagNames)? 1: 0); +})}; +})(style, basestyles[style]); +} +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/blockquote.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/blockquote.js new file mode 100644 index 000000000..af7ef670e --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/blockquote.js @@ -0,0 +1,287 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/blockquote.js']) { + _$jscoverage['plugins/blockquote.js'] = []; + _$jscoverage['plugins/blockquote.js'][44] = 0; + _$jscoverage['plugins/blockquote.js'][45] = 0; + _$jscoverage['plugins/blockquote.js'][46] = 0; + _$jscoverage['plugins/blockquote.js'][47] = 0; + _$jscoverage['plugins/blockquote.js'][49] = 0; + _$jscoverage['plugins/blockquote.js'][51] = 0; + _$jscoverage['plugins/blockquote.js'][56] = 0; + _$jscoverage['plugins/blockquote.js'][58] = 0; + _$jscoverage['plugins/blockquote.js'][59] = 0; + _$jscoverage['plugins/blockquote.js'][62] = 0; + _$jscoverage['plugins/blockquote.js'][65] = 0; + _$jscoverage['plugins/blockquote.js'][66] = 0; + _$jscoverage['plugins/blockquote.js'][69] = 0; + _$jscoverage['plugins/blockquote.js'][70] = 0; + _$jscoverage['plugins/blockquote.js'][72] = 0; + _$jscoverage['plugins/blockquote.js'][75] = 0; + _$jscoverage['plugins/blockquote.js'][76] = 0; + _$jscoverage['plugins/blockquote.js'][77] = 0; + _$jscoverage['plugins/blockquote.js'][78] = 0; + _$jscoverage['plugins/blockquote.js'][79] = 0; + _$jscoverage['plugins/blockquote.js'][81] = 0; + _$jscoverage['plugins/blockquote.js'][87] = 0; + _$jscoverage['plugins/blockquote.js'][88] = 0; + _$jscoverage['plugins/blockquote.js'][89] = 0; + _$jscoverage['plugins/blockquote.js'][90] = 0; + _$jscoverage['plugins/blockquote.js'][91] = 0; + _$jscoverage['plugins/blockquote.js'][92] = 0; + _$jscoverage['plugins/blockquote.js'][101] = 0; + _$jscoverage['plugins/blockquote.js'][107] = 0; + _$jscoverage['plugins/blockquote.js'][108] = 0; + _$jscoverage['plugins/blockquote.js'][109] = 0; + _$jscoverage['plugins/blockquote.js'][110] = 0; + _$jscoverage['plugins/blockquote.js'][111] = 0; + _$jscoverage['plugins/blockquote.js'][112] = 0; + _$jscoverage['plugins/blockquote.js'][114] = 0; + _$jscoverage['plugins/blockquote.js'][117] = 0; + _$jscoverage['plugins/blockquote.js'][120] = 0; + _$jscoverage['plugins/blockquote.js'][122] = 0; + _$jscoverage['plugins/blockquote.js'][123] = 0; + _$jscoverage['plugins/blockquote.js'][124] = 0; + _$jscoverage['plugins/blockquote.js'][126] = 0; + _$jscoverage['plugins/blockquote.js'][128] = 0; + _$jscoverage['plugins/blockquote.js'][131] = 0; + _$jscoverage['plugins/blockquote.js'][132] = 0; + _$jscoverage['plugins/blockquote.js'][136] = 0; + _$jscoverage['plugins/blockquote.js'][137] = 0; + _$jscoverage['plugins/blockquote.js'][138] = 0; + _$jscoverage['plugins/blockquote.js'][140] = 0; + _$jscoverage['plugins/blockquote.js'][141] = 0; + _$jscoverage['plugins/blockquote.js'][143] = 0; + _$jscoverage['plugins/blockquote.js'][146] = 0; + _$jscoverage['plugins/blockquote.js'][149] = 0; + _$jscoverage['plugins/blockquote.js'][151] = 0; + _$jscoverage['plugins/blockquote.js'][152] = 0; + _$jscoverage['plugins/blockquote.js'][153] = 0; + _$jscoverage['plugins/blockquote.js'][156] = 0; + _$jscoverage['plugins/blockquote.js'][157] = 0; + _$jscoverage['plugins/blockquote.js'][163] = 0; + _$jscoverage['plugins/blockquote.js'][164] = 0; + _$jscoverage['plugins/blockquote.js'][165] = 0; + _$jscoverage['plugins/blockquote.js'][166] = 0; + _$jscoverage['plugins/blockquote.js'][168] = 0; + _$jscoverage['plugins/blockquote.js'][169] = 0; + _$jscoverage['plugins/blockquote.js'][170] = 0; + _$jscoverage['plugins/blockquote.js'][171] = 0; + _$jscoverage['plugins/blockquote.js'][176] = 0; + _$jscoverage['plugins/blockquote.js'][179] = 0; +} +_$jscoverage['plugins/blockquote.js'].source = ["/**"," * 添加引用"," * @file"," * @since 1.2.6.1"," */","","/**"," * 根据选区位置对标签添加引用"," * @command blockquote"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'blockquote' );"," * ```"," */","","/**"," * 根据选区位置对标签添加引用"," * @command blockquote"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param { Object } attrs 节点属性"," * @example"," * ```javascript"," * editor.execCommand( 'blockquote',{"," * color:'#000'"," * } );"," * ```"," */","","/**"," * 返回当前选区位置是否在引用标签内"," * @command blockquote"," * @method queryCommandState"," * @param { String } cmd 命令字符串"," * @return { int } 0为是,-1为不是"," * @example"," * ```javascript"," * editor.queryCommandState( 'blockquote' );"," * ```"," */","","UE.plugins['blockquote'] = function(){"," var me = this;"," function getObj(editor){"," return domUtils.filterNodeList(editor.selection.getStartElementPath(),'blockquote');"," }"," me.commands['blockquote'] = {"," execCommand : function( cmdName, attrs ) {"," var range = this.selection.getRange(),"," obj = getObj(this),"," blockquote = dtd.blockquote,"," bookmark = range.createBookmark();",""," if ( obj ) {",""," var start = range.startContainer,"," startBlock = domUtils.isBlockElm(start) ? start : domUtils.findParent(start,function(node){return domUtils.isBlockElm(node)}),",""," end = range.endContainer,"," endBlock = domUtils.isBlockElm(end) ? end : domUtils.findParent(end,function(node){return domUtils.isBlockElm(node)});",""," //处理一下li"," startBlock = domUtils.findParentByTagName(startBlock,'li',true) || startBlock;"," endBlock = domUtils.findParentByTagName(endBlock,'li',true) || endBlock;","",""," if(startBlock.tagName == 'LI' || startBlock.tagName == 'TD' || startBlock === obj || domUtils.isBody(startBlock)){"," domUtils.remove(obj,true);"," }else{"," domUtils.breakParent(startBlock,obj);"," }",""," if(startBlock !== endBlock){"," obj = domUtils.findParentByTagName(endBlock,'blockquote');"," if(obj){"," if(endBlock.tagName == 'LI' || endBlock.tagName == 'TD'|| domUtils.isBody(endBlock)){"," obj.parentNode && domUtils.remove(obj,true);"," }else{"," domUtils.breakParent(endBlock,obj);"," }",""," }"," }",""," var blockquotes = domUtils.getElementsByTagName(this.document,'blockquote');"," for(var i=0,bi;bi=blockquotes[i++];){"," if(!bi.childNodes.length){"," domUtils.remove(bi);"," }else if(domUtils.getPosition(bi,startBlock)&domUtils.POSITION_FOLLOWING && domUtils.getPosition(bi,endBlock)&domUtils.POSITION_PRECEDING){"," domUtils.remove(bi,true);"," }"," }","","","",""," } else {",""," var tmpRange = range.cloneRange(),"," node = tmpRange.startContainer.nodeType == 1 ? tmpRange.startContainer : tmpRange.startContainer.parentNode,"," preNode = node,"," doEnd = 1;",""," //调整开始"," while ( 1 ) {"," if ( domUtils.isBody(node) ) {"," if ( preNode !== node ) {"," if ( range.collapsed ) {"," tmpRange.selectNode( preNode );"," doEnd = 0;"," } else {"," tmpRange.setStartBefore( preNode );"," }"," }else{"," tmpRange.setStart(node,0);"," }",""," break;"," }"," if ( !blockquote[node.tagName] ) {"," if ( range.collapsed ) {"," tmpRange.selectNode( preNode );"," } else{"," tmpRange.setStartBefore( preNode);"," }"," break;"," }",""," preNode = node;"," node = node.parentNode;"," }",""," //调整结束"," if ( doEnd ) {"," preNode = node = node = tmpRange.endContainer.nodeType == 1 ? tmpRange.endContainer : tmpRange.endContainer.parentNode;"," while ( 1 ) {",""," if ( domUtils.isBody( node ) ) {"," if ( preNode !== node ) {",""," tmpRange.setEndAfter( preNode );",""," } else {"," tmpRange.setEnd( node, node.childNodes.length );"," }",""," break;"," }"," if ( !blockquote[node.tagName] ) {"," tmpRange.setEndAfter( preNode );"," break;"," }",""," preNode = node;"," node = node.parentNode;"," }",""," }","",""," node = range.document.createElement( 'blockquote' );"," domUtils.setAttributes( node, attrs );"," node.appendChild( tmpRange.extractContents() );"," tmpRange.insertNode( node );"," //去除重复的"," var childs = domUtils.getElementsByTagName(node,'blockquote');"," for(var i=0,ci;ci=childs[i++];){"," if(ci.parentNode){"," domUtils.remove(ci,true);"," }"," }",""," }"," range.moveToBookmark( bookmark ).select();"," },"," queryCommandState : function() {"," return getObj(this) ? 1 : 0;"," }"," };","};",""]; +_$jscoverage['plugins/blockquote.js'][44]++; +UE.plugins.blockquote = (function () { + _$jscoverage['plugins/blockquote.js'][45]++; + var me = this; + _$jscoverage['plugins/blockquote.js'][46]++; + function getObj(editor) { + _$jscoverage['plugins/blockquote.js'][47]++; + return domUtils.filterNodeList(editor.selection.getStartElementPath(), "blockquote"); +} + _$jscoverage['plugins/blockquote.js'][49]++; + me.commands.blockquote = {execCommand: (function (cmdName, attrs) { + _$jscoverage['plugins/blockquote.js'][51]++; + var range = this.selection.getRange(), obj = getObj(this), blockquote = dtd.blockquote, bookmark = range.createBookmark(); + _$jscoverage['plugins/blockquote.js'][56]++; + if (obj) { + _$jscoverage['plugins/blockquote.js'][58]++; + var start = range.startContainer, startBlock = (domUtils.isBlockElm(start)? start: domUtils.findParent(start, (function (node) { + _$jscoverage['plugins/blockquote.js'][59]++; + return domUtils.isBlockElm(node); +}))), end = range.endContainer, endBlock = (domUtils.isBlockElm(end)? end: domUtils.findParent(end, (function (node) { + _$jscoverage['plugins/blockquote.js'][62]++; + return domUtils.isBlockElm(node); +}))); + _$jscoverage['plugins/blockquote.js'][65]++; + startBlock = (domUtils.findParentByTagName(startBlock, "li", true) || startBlock); + _$jscoverage['plugins/blockquote.js'][66]++; + endBlock = (domUtils.findParentByTagName(endBlock, "li", true) || endBlock); + _$jscoverage['plugins/blockquote.js'][69]++; + if (((startBlock.tagName == "LI") || (startBlock.tagName == "TD") || (startBlock === obj) || domUtils.isBody(startBlock))) { + _$jscoverage['plugins/blockquote.js'][70]++; + domUtils.remove(obj, true); + } + else { + _$jscoverage['plugins/blockquote.js'][72]++; + domUtils.breakParent(startBlock, obj); + } + _$jscoverage['plugins/blockquote.js'][75]++; + if ((startBlock !== endBlock)) { + _$jscoverage['plugins/blockquote.js'][76]++; + obj = domUtils.findParentByTagName(endBlock, "blockquote"); + _$jscoverage['plugins/blockquote.js'][77]++; + if (obj) { + _$jscoverage['plugins/blockquote.js'][78]++; + if (((endBlock.tagName == "LI") || (endBlock.tagName == "TD") || domUtils.isBody(endBlock))) { + _$jscoverage['plugins/blockquote.js'][79]++; + (obj.parentNode && domUtils.remove(obj, true)); + } + else { + _$jscoverage['plugins/blockquote.js'][81]++; + domUtils.breakParent(endBlock, obj); + } + } + } + _$jscoverage['plugins/blockquote.js'][87]++; + var blockquotes = domUtils.getElementsByTagName(this.document, "blockquote"); + _$jscoverage['plugins/blockquote.js'][88]++; + for (var i = 0, bi; (bi = blockquotes[(i++)]);) { + _$jscoverage['plugins/blockquote.js'][89]++; + if ((! bi.childNodes.length)) { + _$jscoverage['plugins/blockquote.js'][90]++; + domUtils.remove(bi); + } + else { + _$jscoverage['plugins/blockquote.js'][91]++; + if (((domUtils.getPosition(bi, startBlock) & domUtils.POSITION_FOLLOWING) && (domUtils.getPosition(bi, endBlock) & domUtils.POSITION_PRECEDING))) { + _$jscoverage['plugins/blockquote.js'][92]++; + domUtils.remove(bi, true); + } + } +} + } + else { + _$jscoverage['plugins/blockquote.js'][101]++; + var tmpRange = range.cloneRange(), node = ((tmpRange.startContainer.nodeType == 1)? tmpRange.startContainer: tmpRange.startContainer.parentNode), preNode = node, doEnd = 1; + _$jscoverage['plugins/blockquote.js'][107]++; + while (true) { + _$jscoverage['plugins/blockquote.js'][108]++; + if (domUtils.isBody(node)) { + _$jscoverage['plugins/blockquote.js'][109]++; + if ((preNode !== node)) { + _$jscoverage['plugins/blockquote.js'][110]++; + if (range.collapsed) { + _$jscoverage['plugins/blockquote.js'][111]++; + tmpRange.selectNode(preNode); + _$jscoverage['plugins/blockquote.js'][112]++; + doEnd = 0; + } + else { + _$jscoverage['plugins/blockquote.js'][114]++; + tmpRange.setStartBefore(preNode); + } + } + else { + _$jscoverage['plugins/blockquote.js'][117]++; + tmpRange.setStart(node, 0); + } + _$jscoverage['plugins/blockquote.js'][120]++; + break; + } + _$jscoverage['plugins/blockquote.js'][122]++; + if ((! blockquote[node.tagName])) { + _$jscoverage['plugins/blockquote.js'][123]++; + if (range.collapsed) { + _$jscoverage['plugins/blockquote.js'][124]++; + tmpRange.selectNode(preNode); + } + else { + _$jscoverage['plugins/blockquote.js'][126]++; + tmpRange.setStartBefore(preNode); + } + _$jscoverage['plugins/blockquote.js'][128]++; + break; + } + _$jscoverage['plugins/blockquote.js'][131]++; + preNode = node; + _$jscoverage['plugins/blockquote.js'][132]++; + node = node.parentNode; +} + _$jscoverage['plugins/blockquote.js'][136]++; + if (doEnd) { + _$jscoverage['plugins/blockquote.js'][137]++; + preNode = (node = (node = ((tmpRange.endContainer.nodeType == 1)? tmpRange.endContainer: tmpRange.endContainer.parentNode))); + _$jscoverage['plugins/blockquote.js'][138]++; + while (true) { + _$jscoverage['plugins/blockquote.js'][140]++; + if (domUtils.isBody(node)) { + _$jscoverage['plugins/blockquote.js'][141]++; + if ((preNode !== node)) { + _$jscoverage['plugins/blockquote.js'][143]++; + tmpRange.setEndAfter(preNode); + } + else { + _$jscoverage['plugins/blockquote.js'][146]++; + tmpRange.setEnd(node, node.childNodes.length); + } + _$jscoverage['plugins/blockquote.js'][149]++; + break; + } + _$jscoverage['plugins/blockquote.js'][151]++; + if ((! blockquote[node.tagName])) { + _$jscoverage['plugins/blockquote.js'][152]++; + tmpRange.setEndAfter(preNode); + _$jscoverage['plugins/blockquote.js'][153]++; + break; + } + _$jscoverage['plugins/blockquote.js'][156]++; + preNode = node; + _$jscoverage['plugins/blockquote.js'][157]++; + node = node.parentNode; +} + } + _$jscoverage['plugins/blockquote.js'][163]++; + node = range.document.createElement("blockquote"); + _$jscoverage['plugins/blockquote.js'][164]++; + domUtils.setAttributes(node, attrs); + _$jscoverage['plugins/blockquote.js'][165]++; + node.appendChild(tmpRange.extractContents()); + _$jscoverage['plugins/blockquote.js'][166]++; + tmpRange.insertNode(node); + _$jscoverage['plugins/blockquote.js'][168]++; + var childs = domUtils.getElementsByTagName(node, "blockquote"); + _$jscoverage['plugins/blockquote.js'][169]++; + for (var i = 0, ci; (ci = childs[(i++)]);) { + _$jscoverage['plugins/blockquote.js'][170]++; + if (ci.parentNode) { + _$jscoverage['plugins/blockquote.js'][171]++; + domUtils.remove(ci, true); + } +} + } + _$jscoverage['plugins/blockquote.js'][176]++; + range.moveToBookmark(bookmark).select(); +}), queryCommandState: (function () { + _$jscoverage['plugins/blockquote.js'][179]++; + return (getObj(this)? 1: 0); +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/catchremoteimage.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/catchremoteimage.js new file mode 100644 index 000000000..a27962630 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/catchremoteimage.js @@ -0,0 +1,192 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/catchremoteimage.js']) { + _$jscoverage['plugins/catchremoteimage.js'] = []; + _$jscoverage['plugins/catchremoteimage.js'][9] = 0; + _$jscoverage['plugins/catchremoteimage.js'][10] = 0; + _$jscoverage['plugins/catchremoteimage.js'][11] = 0; + _$jscoverage['plugins/catchremoteimage.js'][13] = 0; + _$jscoverage['plugins/catchremoteimage.js'][14] = 0; + _$jscoverage['plugins/catchremoteimage.js'][20] = 0; + _$jscoverage['plugins/catchremoteimage.js'][24] = 0; + _$jscoverage['plugins/catchremoteimage.js'][25] = 0; + _$jscoverage['plugins/catchremoteimage.js'][26] = 0; + _$jscoverage['plugins/catchremoteimage.js'][31] = 0; + _$jscoverage['plugins/catchremoteimage.js'][32] = 0; + _$jscoverage['plugins/catchremoteimage.js'][35] = 0; + _$jscoverage['plugins/catchremoteimage.js'][36] = 0; + _$jscoverage['plugins/catchremoteimage.js'][39] = 0; + _$jscoverage['plugins/catchremoteimage.js'][40] = 0; + _$jscoverage['plugins/catchremoteimage.js'][41] = 0; + _$jscoverage['plugins/catchremoteimage.js'][42] = 0; + _$jscoverage['plugins/catchremoteimage.js'][43] = 0; + _$jscoverage['plugins/catchremoteimage.js'][44] = 0; + _$jscoverage['plugins/catchremoteimage.js'][45] = 0; + _$jscoverage['plugins/catchremoteimage.js'][48] = 0; + _$jscoverage['plugins/catchremoteimage.js'][50] = 0; + _$jscoverage['plugins/catchremoteimage.js'][51] = 0; + _$jscoverage['plugins/catchremoteimage.js'][52] = 0; + _$jscoverage['plugins/catchremoteimage.js'][54] = 0; + _$jscoverage['plugins/catchremoteimage.js'][55] = 0; + _$jscoverage['plugins/catchremoteimage.js'][56] = 0; + _$jscoverage['plugins/catchremoteimage.js'][59] = 0; + _$jscoverage['plugins/catchremoteimage.js'][60] = 0; + _$jscoverage['plugins/catchremoteimage.js'][63] = 0; + _$jscoverage['plugins/catchremoteimage.js'][64] = 0; + _$jscoverage['plugins/catchremoteimage.js'][66] = 0; + _$jscoverage['plugins/catchremoteimage.js'][68] = 0; + _$jscoverage['plugins/catchremoteimage.js'][70] = 0; + _$jscoverage['plugins/catchremoteimage.js'][71] = 0; + _$jscoverage['plugins/catchremoteimage.js'][72] = 0; + _$jscoverage['plugins/catchremoteimage.js'][73] = 0; + _$jscoverage['plugins/catchremoteimage.js'][74] = 0; + _$jscoverage['plugins/catchremoteimage.js'][76] = 0; + _$jscoverage['plugins/catchremoteimage.js'][77] = 0; + _$jscoverage['plugins/catchremoteimage.js'][81] = 0; + _$jscoverage['plugins/catchremoteimage.js'][85] = 0; + _$jscoverage['plugins/catchremoteimage.js'][89] = 0; +} +_$jscoverage['plugins/catchremoteimage.js'].source = ["///import core","///commands 远程图片抓取","///commandsName catchRemoteImage,catchremoteimageenable","///commandsTitle 远程图片抓取","/*"," * 远程图片抓取,当开启本插件时所有不符合本地域名的图片都将被抓取成为本地服务器上的图片"," *"," */","UE.plugins['catchremoteimage'] = function () {"," if (this.options.catchRemoteImageEnable===false){"," return;"," }"," var me = this;"," this.setOpt({"," localDomain:[\"127.0.0.1\",\"localhost\",\"img.baidu.com\"],"," separater:'ue_separate_ue',"," catchFieldName:\"upfile\","," catchRemoteImageEnable:true"," });"," var ajax = UE.ajax,"," localDomain = me.options.localDomain ,"," catcherUrl = me.options.catcherUrl,"," separater = me.options.separater;"," function catchremoteimage(imgs, callbacks) {"," var submitStr = imgs.join(separater);"," var tmpOption = {"," timeout:60000, //单位:毫秒,回调请求超时设置。目标用户如果网速不是很快的话此处建议设置一个较大的数值"," onsuccess:callbacks[\"success\"],"," onerror:callbacks[\"error\"]"," };"," tmpOption[me.options.catchFieldName] = submitStr;"," ajax.request(catcherUrl, tmpOption);"," }",""," me.addListener(\"afterpaste\", function () {"," me.fireEvent(\"catchRemoteImage\");"," });",""," me.addListener(\"catchRemoteImage\", function () {"," var remoteImages = [];"," var imgs = domUtils.getElementsByTagName(me.document, \"img\");"," var test = function (src,urls) {"," for (var j = 0, url; url = urls[j++];) {"," if (src.indexOf(url) !== -1) {"," return true;"," }"," }"," return false;"," };"," for (var i = 0, ci; ci = imgs[i++];) {"," if (ci.getAttribute(\"word_img\")){"," continue;"," }"," var src = ci.getAttribute(\"_src\") || ci.src || \"\";"," if (/^(https?|ftp):/i.test(src) && !test(src,localDomain)) {"," remoteImages.push(src);"," }"," }"," if (remoteImages.length) {"," catchremoteimage(remoteImages, {"," //成功抓取"," success:function (xhr) {"," try {"," var info = eval(\"(\" + xhr.responseText + \")\");"," } catch (e) {"," return;"," }"," var srcUrls = info.srcUrl.split(separater),"," urls = info.url.split(separater);"," for (var i = 0, ci; ci = imgs[i++];) {"," var src = ci.getAttribute(\"_src\") || ci.src || \"\";"," for (var j = 0, cj; cj = srcUrls[j++];) {"," var url = urls[j - 1];"," if (src == cj && url != \"error\") { //抓取失败时不做替换处理"," //地址修正"," var newSrc = me.options.catcherPath + url;"," domUtils.setAttributes(ci, {"," \"src\":newSrc,"," \"_src\":newSrc"," });"," break;"," }"," }"," }"," me.fireEvent('catchremotesuccess')"," },"," //回调失败,本次请求超时"," error:function () {"," me.fireEvent(\"catchremoteerror\");"," }"," });"," }",""," });","};"]; +_$jscoverage['plugins/catchremoteimage.js'][9]++; +UE.plugins.catchremoteimage = (function () { + _$jscoverage['plugins/catchremoteimage.js'][10]++; + if ((this.options.catchRemoteImageEnable === false)) { + _$jscoverage['plugins/catchremoteimage.js'][11]++; + return; + } + _$jscoverage['plugins/catchremoteimage.js'][13]++; + var me = this; + _$jscoverage['plugins/catchremoteimage.js'][14]++; + this.setOpt({localDomain: ["127.0.0.1", "localhost", "img.baidu.com"], separater: "ue_separate_ue", catchFieldName: "upfile", catchRemoteImageEnable: true}); + _$jscoverage['plugins/catchremoteimage.js'][20]++; + var ajax = UE.ajax, localDomain = me.options.localDomain, catcherUrl = me.options.catcherUrl, separater = me.options.separater; + _$jscoverage['plugins/catchremoteimage.js'][24]++; + function catchremoteimage(imgs, callbacks) { + _$jscoverage['plugins/catchremoteimage.js'][25]++; + var submitStr = imgs.join(separater); + _$jscoverage['plugins/catchremoteimage.js'][26]++; + var tmpOption = {timeout: 60000, onsuccess: callbacks.success, onerror: callbacks.error}; + _$jscoverage['plugins/catchremoteimage.js'][31]++; + tmpOption[me.options.catchFieldName] = submitStr; + _$jscoverage['plugins/catchremoteimage.js'][32]++; + ajax.request(catcherUrl, tmpOption); +} + _$jscoverage['plugins/catchremoteimage.js'][35]++; + me.addListener("afterpaste", (function () { + _$jscoverage['plugins/catchremoteimage.js'][36]++; + me.fireEvent("catchRemoteImage"); +})); + _$jscoverage['plugins/catchremoteimage.js'][39]++; + me.addListener("catchRemoteImage", (function () { + _$jscoverage['plugins/catchremoteimage.js'][40]++; + var remoteImages = []; + _$jscoverage['plugins/catchremoteimage.js'][41]++; + var imgs = domUtils.getElementsByTagName(me.document, "img"); + _$jscoverage['plugins/catchremoteimage.js'][42]++; + var test = (function (src, urls) { + _$jscoverage['plugins/catchremoteimage.js'][43]++; + for (var j = 0, url; (url = urls[(j++)]);) { + _$jscoverage['plugins/catchremoteimage.js'][44]++; + if ((src.indexOf(url) !== -1)) { + _$jscoverage['plugins/catchremoteimage.js'][45]++; + return true; + } +} + _$jscoverage['plugins/catchremoteimage.js'][48]++; + return false; +}); + _$jscoverage['plugins/catchremoteimage.js'][50]++; + for (var i = 0, ci; (ci = imgs[(i++)]);) { + _$jscoverage['plugins/catchremoteimage.js'][51]++; + if (ci.getAttribute("word_img")) { + _$jscoverage['plugins/catchremoteimage.js'][52]++; + continue; + } + _$jscoverage['plugins/catchremoteimage.js'][54]++; + var src = (ci.getAttribute("_src") || ci.src || ""); + _$jscoverage['plugins/catchremoteimage.js'][55]++; + if ((/^(https?|ftp):/i.test(src) && (! test(src, localDomain)))) { + _$jscoverage['plugins/catchremoteimage.js'][56]++; + remoteImages.push(src); + } +} + _$jscoverage['plugins/catchremoteimage.js'][59]++; + if (remoteImages.length) { + _$jscoverage['plugins/catchremoteimage.js'][60]++; + catchremoteimage(remoteImages, {success: (function (xhr) { + _$jscoverage['plugins/catchremoteimage.js'][63]++; + try { + _$jscoverage['plugins/catchremoteimage.js'][64]++; + var info = eval(("(" + xhr.responseText + ")")); + } + catch (e) { + _$jscoverage['plugins/catchremoteimage.js'][66]++; + return; + } + _$jscoverage['plugins/catchremoteimage.js'][68]++; + var srcUrls = info.srcUrl.split(separater), urls = info.url.split(separater); + _$jscoverage['plugins/catchremoteimage.js'][70]++; + for (var i = 0, ci; (ci = imgs[(i++)]);) { + _$jscoverage['plugins/catchremoteimage.js'][71]++; + var src = (ci.getAttribute("_src") || ci.src || ""); + _$jscoverage['plugins/catchremoteimage.js'][72]++; + for (var j = 0, cj; (cj = srcUrls[(j++)]);) { + _$jscoverage['plugins/catchremoteimage.js'][73]++; + var url = urls[(j - 1)]; + _$jscoverage['plugins/catchremoteimage.js'][74]++; + if (((src == cj) && (url != "error"))) { + _$jscoverage['plugins/catchremoteimage.js'][76]++; + var newSrc = (me.options.catcherPath + url); + _$jscoverage['plugins/catchremoteimage.js'][77]++; + domUtils.setAttributes(ci, {"src": newSrc, "_src": newSrc}); + _$jscoverage['plugins/catchremoteimage.js'][81]++; + break; + } +} +} + _$jscoverage['plugins/catchremoteimage.js'][85]++; + me.fireEvent("catchremotesuccess"); +}), error: (function () { + _$jscoverage['plugins/catchremoteimage.js'][89]++; + me.fireEvent("catchremoteerror"); +})}); + } +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/cleardoc.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/cleardoc.js new file mode 100644 index 000000000..0feece8fb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/cleardoc.js @@ -0,0 +1,75 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/cleardoc.js']) { + _$jscoverage['plugins/cleardoc.js'] = []; + _$jscoverage['plugins/cleardoc.js'][19] = 0; + _$jscoverage['plugins/cleardoc.js'][21] = 0; + _$jscoverage['plugins/cleardoc.js'][24] = 0; + _$jscoverage['plugins/cleardoc.js'][25] = 0; + _$jscoverage['plugins/cleardoc.js'][26] = 0; + _$jscoverage['plugins/cleardoc.js'][28] = 0; + _$jscoverage['plugins/cleardoc.js'][29] = 0; + _$jscoverage['plugins/cleardoc.js'][31] = 0; + _$jscoverage['plugins/cleardoc.js'][32] = 0; +} +_$jscoverage['plugins/cleardoc.js'].source = ["/**"," * 清空文档插件"," * @file"," * @since 1.2.6.1"," */","","/**"," * 清空文档命令"," * @command cleardoc"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * //editor 是编辑器实例"," * editor.execCommand('cleardoc');"," * ```"," */","","UE.commands['cleardoc'] = {"," execCommand : function( cmdName) {"," var me = this,"," enterTag = me.options.enterTag,"," range = me.selection.getRange();"," if(enterTag == \"br\"){"," me.body.innerHTML = \"<br/>\";"," range.setStart(me.body,0).setCursor();"," }else{"," me.body.innerHTML = \"<p>\"+(ie ? \"\" : \"<br/>\")+\"</p>\";"," range.setStart(me.body.firstChild,0).setCursor(false,true);"," }"," setTimeout(function(){"," me.fireEvent(\"clearDoc\");"," },0);",""," }","};",""]; +_$jscoverage['plugins/cleardoc.js'][19]++; +UE.commands.cleardoc = {execCommand: (function (cmdName) { + _$jscoverage['plugins/cleardoc.js'][21]++; + var me = this, enterTag = me.options.enterTag, range = me.selection.getRange(); + _$jscoverage['plugins/cleardoc.js'][24]++; + if ((enterTag == "br")) { + _$jscoverage['plugins/cleardoc.js'][25]++; + me.body.innerHTML = "
    "; + _$jscoverage['plugins/cleardoc.js'][26]++; + range.setStart(me.body, 0).setCursor(); + } + else { + _$jscoverage['plugins/cleardoc.js'][28]++; + me.body.innerHTML = ("

    " + (ie? "": "
    ") + "

    "); + _$jscoverage['plugins/cleardoc.js'][29]++; + range.setStart(me.body.firstChild, 0).setCursor(false, true); + } + _$jscoverage['plugins/cleardoc.js'][31]++; + setTimeout((function () { + _$jscoverage['plugins/cleardoc.js'][32]++; + me.fireEvent("clearDoc"); +}), 0); +})}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/contextmenu.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/contextmenu.js new file mode 100644 index 000000000..69e001c82 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/contextmenu.js @@ -0,0 +1,413 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/contextmenu.js']) { + _$jscoverage['plugins/contextmenu.js'] = []; + _$jscoverage['plugins/contextmenu.js'][12] = 0; + _$jscoverage['plugins/contextmenu.js'][13] = 0; + _$jscoverage['plugins/contextmenu.js'][27] = 0; + _$jscoverage['plugins/contextmenu.js'][28] = 0; + _$jscoverage['plugins/contextmenu.js'][159] = 0; + _$jscoverage['plugins/contextmenu.js'][160] = 0; + _$jscoverage['plugins/contextmenu.js'][162] = 0; + _$jscoverage['plugins/contextmenu.js'][169] = 0; + _$jscoverage['plugins/contextmenu.js'][170] = 0; + _$jscoverage['plugins/contextmenu.js'][172] = 0; + _$jscoverage['plugins/contextmenu.js'][194] = 0; + _$jscoverage['plugins/contextmenu.js'][195] = 0; + _$jscoverage['plugins/contextmenu.js'][197] = 0; + _$jscoverage['plugins/contextmenu.js'][205] = 0; + _$jscoverage['plugins/contextmenu.js'][206] = 0; + _$jscoverage['plugins/contextmenu.js'][208] = 0; + _$jscoverage['plugins/contextmenu.js'][209] = 0; + _$jscoverage['plugins/contextmenu.js'][210] = 0; + _$jscoverage['plugins/contextmenu.js'][218] = 0; + _$jscoverage['plugins/contextmenu.js'][219] = 0; + _$jscoverage['plugins/contextmenu.js'][221] = 0; + _$jscoverage['plugins/contextmenu.js'][222] = 0; + _$jscoverage['plugins/contextmenu.js'][223] = 0; + _$jscoverage['plugins/contextmenu.js'][237] = 0; + _$jscoverage['plugins/contextmenu.js'][244] = 0; + _$jscoverage['plugins/contextmenu.js'][251] = 0; + _$jscoverage['plugins/contextmenu.js'][258] = 0; + _$jscoverage['plugins/contextmenu.js'][265] = 0; + _$jscoverage['plugins/contextmenu.js'][272] = 0; + _$jscoverage['plugins/contextmenu.js'][357] = 0; + _$jscoverage['plugins/contextmenu.js'][360] = 0; + _$jscoverage['plugins/contextmenu.js'][367] = 0; + _$jscoverage['plugins/contextmenu.js'][370] = 0; + _$jscoverage['plugins/contextmenu.js'][376] = 0; + _$jscoverage['plugins/contextmenu.js'][377] = 0; + _$jscoverage['plugins/contextmenu.js'][379] = 0; + _$jscoverage['plugins/contextmenu.js'][383] = 0; + _$jscoverage['plugins/contextmenu.js'][384] = 0; + _$jscoverage['plugins/contextmenu.js'][386] = 0; + _$jscoverage['plugins/contextmenu.js'][388] = 0; + _$jscoverage['plugins/contextmenu.js'][390] = 0; + _$jscoverage['plugins/contextmenu.js'][391] = 0; + _$jscoverage['plugins/contextmenu.js'][392] = 0; + _$jscoverage['plugins/contextmenu.js'][393] = 0; + _$jscoverage['plugins/contextmenu.js'][395] = 0; + _$jscoverage['plugins/contextmenu.js'][396] = 0; + _$jscoverage['plugins/contextmenu.js'][397] = 0; + _$jscoverage['plugins/contextmenu.js'][398] = 0; + _$jscoverage['plugins/contextmenu.js'][399] = 0; + _$jscoverage['plugins/contextmenu.js'][400] = 0; + _$jscoverage['plugins/contextmenu.js'][402] = 0; + _$jscoverage['plugins/contextmenu.js'][403] = 0; + _$jscoverage['plugins/contextmenu.js'][404] = 0; + _$jscoverage['plugins/contextmenu.js'][405] = 0; + _$jscoverage['plugins/contextmenu.js'][406] = 0; + _$jscoverage['plugins/contextmenu.js'][407] = 0; + _$jscoverage['plugins/contextmenu.js'][409] = 0; + _$jscoverage['plugins/contextmenu.js'][412] = 0; + _$jscoverage['plugins/contextmenu.js'][414] = 0; + _$jscoverage['plugins/contextmenu.js'][418] = 0; + _$jscoverage['plugins/contextmenu.js'][420] = 0; + _$jscoverage['plugins/contextmenu.js'][427] = 0; + _$jscoverage['plugins/contextmenu.js'][428] = 0; + _$jscoverage['plugins/contextmenu.js'][429] = 0; + _$jscoverage['plugins/contextmenu.js'][431] = 0; + _$jscoverage['plugins/contextmenu.js'][433] = 0; + _$jscoverage['plugins/contextmenu.js'][435] = 0; + _$jscoverage['plugins/contextmenu.js'][437] = 0; + _$jscoverage['plugins/contextmenu.js'][439] = 0; + _$jscoverage['plugins/contextmenu.js'][441] = 0; + _$jscoverage['plugins/contextmenu.js'][443] = 0; + _$jscoverage['plugins/contextmenu.js'][446] = 0; + _$jscoverage['plugins/contextmenu.js'][459] = 0; + _$jscoverage['plugins/contextmenu.js'][462] = 0; + _$jscoverage['plugins/contextmenu.js'][463] = 0; + _$jscoverage['plugins/contextmenu.js'][464] = 0; + _$jscoverage['plugins/contextmenu.js'][466] = 0; + _$jscoverage['plugins/contextmenu.js'][467] = 0; + _$jscoverage['plugins/contextmenu.js'][470] = 0; + _$jscoverage['plugins/contextmenu.js'][474] = 0; + _$jscoverage['plugins/contextmenu.js'][476] = 0; + _$jscoverage['plugins/contextmenu.js'][485] = 0; + _$jscoverage['plugins/contextmenu.js'][486] = 0; + _$jscoverage['plugins/contextmenu.js'][489] = 0; + _$jscoverage['plugins/contextmenu.js'][494] = 0; + _$jscoverage['plugins/contextmenu.js'][495] = 0; + _$jscoverage['plugins/contextmenu.js'][497] = 0; + _$jscoverage['plugins/contextmenu.js'][499] = 0; + _$jscoverage['plugins/contextmenu.js'][500] = 0; + _$jscoverage['plugins/contextmenu.js'][501] = 0; + _$jscoverage['plugins/contextmenu.js'][502] = 0; + _$jscoverage['plugins/contextmenu.js'][503] = 0; + _$jscoverage['plugins/contextmenu.js'][505] = 0; + _$jscoverage['plugins/contextmenu.js'][507] = 0; + _$jscoverage['plugins/contextmenu.js'][508] = 0; + _$jscoverage['plugins/contextmenu.js'][509] = 0; +} +_$jscoverage['plugins/contextmenu.js'].source = ["///import core","///commands 右键菜单","///commandsName ContextMenu","///commandsTitle 右键菜单","/*"," * 右键菜单"," * @function"," * @name baidu.editor.plugins.contextmenu"," * @author zhanyi"," */","","UE.plugins['contextmenu'] = function () {"," var me = this,"," lang = me.getLang( \"contextMenu\" ),"," menu,"," items = me.options.contextMenu || ["," {label:lang['selectall'], cmdName:'selectall'},"," {"," label:lang.deletecode,"," cmdName:'highlightcode',"," icon:'deletehighlightcode'"," },"," {"," label:lang.cleardoc,"," cmdName:'cleardoc',"," exec:function () {"," if ( confirm( lang.confirmclear ) ) {"," this.execCommand( 'cleardoc' );"," }"," }"," },"," '-',"," {"," label:lang.unlink,"," cmdName:'unlink'"," },"," '-',"," {"," group:lang.paragraph,"," icon:'justifyjustify',"," subMenu:["," {"," label:lang.justifyleft,"," cmdName:'justify',"," value:'left'"," },"," {"," label:lang.justifyright,"," cmdName:'justify',"," value:'right'"," },"," {"," label:lang.justifycenter,"," cmdName:'justify',"," value:'center'"," },"," {"," label:lang.justifyjustify,"," cmdName:'justify',"," value:'justify'"," }"," ]"," },"," '-',"," {"," group:lang.table,"," icon:'table',"," subMenu:["," {"," label:lang.inserttable,"," cmdName:'inserttable'"," },"," {"," label:lang.deletetable,"," cmdName:'deletetable'"," },"," '-',"," {"," label:lang.deleterow,"," cmdName:'deleterow'"," },"," {"," label:lang.deletecol,"," cmdName:'deletecol'"," },"," {"," label:lang.insertcol,"," cmdName:'insertcol'"," },"," {"," label:lang.insertcolnext,"," cmdName:'insertcolnext'"," },"," {"," label:lang.insertrow,"," cmdName:'insertrow'"," },"," {"," label:lang.insertrownext,"," cmdName:'insertrownext'"," },"," '-',"," {"," label:lang.insertcaption,"," cmdName:'insertcaption'"," },"," {"," label:lang.deletecaption,"," cmdName:'deletecaption'"," },"," {"," label:lang.inserttitle,"," cmdName:'inserttitle'"," },"," {"," label:lang.deletetitle,"," cmdName:'deletetitle'"," },"," '-',"," {"," label:lang.mergecells,"," cmdName:'mergecells'"," },"," {"," label:lang.mergeright,"," cmdName:'mergeright'"," },"," {"," label:lang.mergedown,"," cmdName:'mergedown'"," },"," '-',"," {"," label:lang.splittorows,"," cmdName:'splittorows'"," },"," {"," label:lang.splittocols,"," cmdName:'splittocols'"," },"," {"," label:lang.splittocells,"," cmdName:'splittocells'"," },"," '-',"," {"," label:lang.averageDiseRow,"," cmdName:'averagedistributerow'"," },"," {"," label:lang.averageDisCol,"," cmdName:'averagedistributecol'"," },"," '-',"," {"," label:lang.edittd,"," cmdName:'edittd',"," exec:function () {"," if ( UE.ui['edittd'] ) {"," new UE.ui['edittd']( this );"," }"," this.getDialog('edittd').open();"," }"," },"," {"," label:lang.edittable,"," cmdName:'edittable',"," exec:function () {"," if ( UE.ui['edittable'] ) {"," new UE.ui['edittable']( this );"," }"," this.getDialog('edittable').open();"," }"," }"," ]"," },"," {"," group:lang.tablesort,"," icon:'tablesort',"," subMenu:["," {"," label:lang.reversecurrent,"," cmdName:'sorttable',"," value:1"," },"," {"," label:lang.orderbyasc,"," cmdName:'sorttable'"," },"," {"," label:lang.reversebyasc,"," cmdName:'sorttable',"," exec:function(){"," this.execCommand(\"sorttable\",function(td1,td2){"," var value1 = td1.innerHTML,"," value2 = td2.innerHTML;"," return value2.localeCompare(value1);"," });"," }"," },"," {"," label:lang.orderbynum,"," cmdName:'sorttable',"," exec:function(){"," this.execCommand(\"sorttable\",function(td1,td2){"," var value1 = td1[browser.ie ? 'innerText':'textContent'].match(/\\d+/),"," value2 = td2[browser.ie ? 'innerText':'textContent'].match(/\\d+/);"," if(value1) value1 = +value1[0];"," if(value2) value2 = +value2[0];"," return (value1||0) - (value2||0);"," });"," }"," },"," {"," label:lang.reversebynum,"," cmdName:'sorttable',"," exec:function(){"," this.execCommand(\"sorttable\",function(td1,td2){"," var value1 = td1[browser.ie ? 'innerText':'textContent'].match(/\\d+/),"," value2 = td2[browser.ie ? 'innerText':'textContent'].match(/\\d+/);"," if(value1) value1 = +value1[0];"," if(value2) value2 = +value2[0];"," return (value2||0) - (value1||0);"," });"," }"," }"," ]"," },"," {"," group:lang.borderbk,"," icon:'borderBack',"," subMenu:["," {"," label:lang.setcolor,"," cmdName:\"interlacetable\","," exec:function(){"," this.execCommand(\"interlacetable\");"," }"," },"," {"," label:lang.unsetcolor,"," cmdName:\"uninterlacetable\","," exec:function(){"," this.execCommand(\"uninterlacetable\");"," }"," },"," {"," label:lang.setbackground,"," cmdName:\"settablebackground\","," exec:function(){"," this.execCommand(\"settablebackground\",{repeat:true,colorList:[\"#bbb\",\"#ccc\"]});"," }"," },"," {"," label:lang.unsetbackground,"," cmdName:\"cleartablebackground\","," exec:function(){"," this.execCommand(\"cleartablebackground\");"," }"," },"," {"," label:lang.redandblue,"," cmdName:\"settablebackground\","," exec:function(){"," this.execCommand(\"settablebackground\",{repeat:true,colorList:[\"red\",\"blue\"]});"," }"," },"," {"," label:lang.threecolorgradient,"," cmdName:\"settablebackground\","," exec:function(){"," this.execCommand(\"settablebackground\",{repeat:true,colorList:[\"#aaa\",\"#bbb\",\"#ccc\"]});"," }"," }"," ]"," },"," {"," group:lang.aligntd,"," icon:'aligntd',"," subMenu:["," {"," cmdName:'cellalignment',"," value:{align:'left',vAlign:'top'}"," },"," {"," cmdName:'cellalignment',"," value:{align:'center',vAlign:'top'}"," },"," {"," cmdName:'cellalignment',"," value:{align:'right',vAlign:'top'}"," },"," {"," cmdName:'cellalignment',"," value:{align:'left',vAlign:'middle'}"," },"," {"," cmdName:'cellalignment',"," value:{align:'center',vAlign:'middle'}"," },"," {"," cmdName:'cellalignment',"," value:{align:'right',vAlign:'middle'}"," },"," {"," cmdName:'cellalignment',"," value:{align:'left',vAlign:'bottom'}"," },"," {"," cmdName:'cellalignment',"," value:{align:'center',vAlign:'bottom'}"," },"," {"," cmdName:'cellalignment',"," value:{align:'right',vAlign:'bottom'}"," }"," ]"," },"," {"," group:lang.aligntable,"," icon:'aligntable',"," subMenu:["," {"," cmdName:'tablealignment',"," className: 'left',"," label:lang.tableleft,"," value:\"left\""," },"," {"," cmdName:'tablealignment',"," className: 'center',"," label:lang.tablecenter,"," value:\"center\""," },"," {"," cmdName:'tablealignment',"," className: 'right',"," label:lang.tableright,"," value:\"right\""," }"," ]"," },"," '-',"," {"," label:lang.insertparagraphbefore,"," cmdName:'insertparagraph',"," value:true"," },"," {"," label:lang.insertparagraphafter,"," cmdName:'insertparagraph'"," },"," {"," label:lang['copy'],"," cmdName:'copy',"," exec:function () {"," alert( lang.copymsg );"," },"," query:function () {"," return 0;"," }"," },"," {"," label:lang['paste'],"," cmdName:'paste',"," exec:function () {"," alert( lang.pastemsg );"," },"," query:function () {"," return 0;"," }"," },{"," label:lang['highlightcode'],"," cmdName:'highlightcode',"," exec:function () {"," if ( UE.ui['highlightcode'] ) {"," new UE.ui['highlightcode']( this );"," }"," this.ui._dialogs['highlightcodeDialog'].open();"," }"," }"," ];"," if ( !items.length ) {"," return;"," }"," var uiUtils = UE.ui.uiUtils;",""," me.addListener( 'contextmenu', function ( type, evt ) {",""," var offset = uiUtils.getViewportOffsetByEvent( evt );"," me.fireEvent( 'beforeselectionchange' );"," if ( menu ) {"," menu.destroy();"," }"," for ( var i = 0, ti, contextItems = []; ti = items[i]; i++ ) {"," var last;"," (function ( item ) {"," if ( item == '-' ) {"," if ( (last = contextItems[contextItems.length - 1 ] ) && last !== '-' ) {"," contextItems.push( '-' );"," }"," } else if ( item.hasOwnProperty( \"group\" ) ) {"," for ( var j = 0, cj, subMenu = []; cj = item.subMenu[j]; j++ ) {"," (function ( subItem ) {"," if ( subItem == '-' ) {"," if ( (last = subMenu[subMenu.length - 1 ] ) && last !== '-' ) {"," subMenu.push( '-' );"," }else{"," subMenu.splice(subMenu.length-1);"," }"," } else {"," if ( (me.commands[subItem.cmdName] || UE.commands[subItem.cmdName] || subItem.query) &&"," (subItem.query ? subItem.query() : me.queryCommandState( subItem.cmdName )) > -1 ) {"," subMenu.push( {"," 'label':subItem.label || me.getLang( \"contextMenu.\" + subItem.cmdName + (subItem.value || '') )||\"\","," 'className':'edui-for-' +subItem.cmdName + ( subItem.className ? ( ' edui-for-' + subItem.cmdName + '-' + subItem.className ) : '' ),"," onclick:subItem.exec ? function () {"," subItem.exec.call( me );"," } : function () {"," me.execCommand( subItem.cmdName, subItem.value );"," }"," } );"," }"," }"," })( cj );"," }"," if ( subMenu.length ) {"," function getLabel(){"," switch (item.icon){"," case \"table\":"," return me.getLang( \"contextMenu.table\" );"," case \"justifyjustify\":"," return me.getLang( \"contextMenu.paragraph\" );"," case \"aligntd\":"," return me.getLang(\"contextMenu.aligntd\");"," case \"aligntable\":"," return me.getLang(\"contextMenu.aligntable\");"," case \"tablesort\":"," return lang.tablesort;"," case \"borderBack\":"," return lang.borderbk;"," default :"," return '';"," }"," }"," contextItems.push( {"," //todo 修正成自动获取方式"," 'label':getLabel(),"," className:'edui-for-' + item.icon,"," 'subMenu':{"," items:subMenu,"," editor:me"," }"," } );"," }",""," } else {"," //有可能commmand没有加载右键不能出来,或者没有command也想能展示出来添加query方法"," if ( (me.commands[item.cmdName] || UE.commands[item.cmdName] || item.query) &&"," (item.query ? item.query.call(me) : me.queryCommandState( item.cmdName )) > -1 ) {"," //highlight todo"," if ( item.cmdName == 'highlightcode' ) {"," if(me.queryCommandState( item.cmdName ) == 1 && item.icon != 'deletehighlightcode'){"," return;"," }"," if(me.queryCommandState( item.cmdName ) != 1 && item.icon == 'deletehighlightcode'){"," return;"," }"," }"," contextItems.push( {"," 'label':item.label || me.getLang( \"contextMenu.\" + item.cmdName ),"," className:'edui-for-' + (item.icon ? item.icon : item.cmdName + (item.value || '')),"," onclick:item.exec ? function () {"," item.exec.call( me );"," } : function () {"," me.execCommand( item.cmdName, item.value );"," }"," } );"," }",""," }",""," })( ti );"," }"," if ( contextItems[contextItems.length - 1] == '-' ) {"," contextItems.pop();"," }",""," menu = new UE.ui.Menu( {"," items:contextItems,"," className:\"edui-contextmenu\","," editor:me"," } );"," menu.render();"," menu.showAt( offset );",""," me.fireEvent(\"aftershowcontextmenu\",menu);",""," domUtils.preventDefault( evt );"," if ( browser.ie ) {"," var ieRange;"," try {"," ieRange = me.selection.getNative().createRange();"," } catch ( e ) {"," return;"," }"," if ( ieRange.item ) {"," var range = new dom.Range( me.document );"," range.selectNode( ieRange.item( 0 ) ).select( true, true );",""," }"," }"," } );","};","",""]; +_$jscoverage['plugins/contextmenu.js'][12]++; +UE.plugins.contextmenu = (function () { + _$jscoverage['plugins/contextmenu.js'][13]++; + var me = this, lang = me.getLang("contextMenu"), menu, items = (me.options.contextMenu || [{label: lang.selectall, cmdName: "selectall"}, {label: lang.deletecode, cmdName: "highlightcode", icon: "deletehighlightcode"}, {label: lang.cleardoc, cmdName: "cleardoc", exec: (function () { + _$jscoverage['plugins/contextmenu.js'][27]++; + if (confirm(lang.confirmclear)) { + _$jscoverage['plugins/contextmenu.js'][28]++; + this.execCommand("cleardoc"); + } +})}, "-", {label: lang.unlink, cmdName: "unlink"}, "-", {group: lang.paragraph, icon: "justifyjustify", subMenu: [{label: lang.justifyleft, cmdName: "justify", value: "left"}, {label: lang.justifyright, cmdName: "justify", value: "right"}, {label: lang.justifycenter, cmdName: "justify", value: "center"}, {label: lang.justifyjustify, cmdName: "justify", value: "justify"}]}, "-", {group: lang.table, icon: "table", subMenu: [{label: lang.inserttable, cmdName: "inserttable"}, {label: lang.deletetable, cmdName: "deletetable"}, "-", {label: lang.deleterow, cmdName: "deleterow"}, {label: lang.deletecol, cmdName: "deletecol"}, {label: lang.insertcol, cmdName: "insertcol"}, {label: lang.insertcolnext, cmdName: "insertcolnext"}, {label: lang.insertrow, cmdName: "insertrow"}, {label: lang.insertrownext, cmdName: "insertrownext"}, "-", {label: lang.insertcaption, cmdName: "insertcaption"}, {label: lang.deletecaption, cmdName: "deletecaption"}, {label: lang.inserttitle, cmdName: "inserttitle"}, {label: lang.deletetitle, cmdName: "deletetitle"}, "-", {label: lang.mergecells, cmdName: "mergecells"}, {label: lang.mergeright, cmdName: "mergeright"}, {label: lang.mergedown, cmdName: "mergedown"}, "-", {label: lang.splittorows, cmdName: "splittorows"}, {label: lang.splittocols, cmdName: "splittocols"}, {label: lang.splittocells, cmdName: "splittocells"}, "-", {label: lang.averageDiseRow, cmdName: "averagedistributerow"}, {label: lang.averageDisCol, cmdName: "averagedistributecol"}, "-", {label: lang.edittd, cmdName: "edittd", exec: (function () { + _$jscoverage['plugins/contextmenu.js'][159]++; + if (UE.ui.edittd) { + _$jscoverage['plugins/contextmenu.js'][160]++; + new (UE.ui.edittd)(this); + } + _$jscoverage['plugins/contextmenu.js'][162]++; + this.getDialog("edittd").open(); +})}, {label: lang.edittable, cmdName: "edittable", exec: (function () { + _$jscoverage['plugins/contextmenu.js'][169]++; + if (UE.ui.edittable) { + _$jscoverage['plugins/contextmenu.js'][170]++; + new (UE.ui.edittable)(this); + } + _$jscoverage['plugins/contextmenu.js'][172]++; + this.getDialog("edittable").open(); +})}]}, {group: lang.tablesort, icon: "tablesort", subMenu: [{label: lang.reversecurrent, cmdName: "sorttable", value: 1}, {label: lang.orderbyasc, cmdName: "sorttable"}, {label: lang.reversebyasc, cmdName: "sorttable", exec: (function () { + _$jscoverage['plugins/contextmenu.js'][194]++; + this.execCommand("sorttable", (function (td1, td2) { + _$jscoverage['plugins/contextmenu.js'][195]++; + var value1 = td1.innerHTML, value2 = td2.innerHTML; + _$jscoverage['plugins/contextmenu.js'][197]++; + return value2.localeCompare(value1); +})); +})}, {label: lang.orderbynum, cmdName: "sorttable", exec: (function () { + _$jscoverage['plugins/contextmenu.js'][205]++; + this.execCommand("sorttable", (function (td1, td2) { + _$jscoverage['plugins/contextmenu.js'][206]++; + var value1 = td1[(browser.ie? "innerText": "textContent")].match(/\d+/), value2 = td2[(browser.ie? "innerText": "textContent")].match(/\d+/); + _$jscoverage['plugins/contextmenu.js'][208]++; + if (value1) { + _$jscoverage['plugins/contextmenu.js'][208]++; + value1 = (+ value1[0]); + } + _$jscoverage['plugins/contextmenu.js'][209]++; + if (value2) { + _$jscoverage['plugins/contextmenu.js'][209]++; + value2 = (+ value2[0]); + } + _$jscoverage['plugins/contextmenu.js'][210]++; + return ((value1 || 0) - (value2 || 0)); +})); +})}, {label: lang.reversebynum, cmdName: "sorttable", exec: (function () { + _$jscoverage['plugins/contextmenu.js'][218]++; + this.execCommand("sorttable", (function (td1, td2) { + _$jscoverage['plugins/contextmenu.js'][219]++; + var value1 = td1[(browser.ie? "innerText": "textContent")].match(/\d+/), value2 = td2[(browser.ie? "innerText": "textContent")].match(/\d+/); + _$jscoverage['plugins/contextmenu.js'][221]++; + if (value1) { + _$jscoverage['plugins/contextmenu.js'][221]++; + value1 = (+ value1[0]); + } + _$jscoverage['plugins/contextmenu.js'][222]++; + if (value2) { + _$jscoverage['plugins/contextmenu.js'][222]++; + value2 = (+ value2[0]); + } + _$jscoverage['plugins/contextmenu.js'][223]++; + return ((value2 || 0) - (value1 || 0)); +})); +})}]}, {group: lang.borderbk, icon: "borderBack", subMenu: [{label: lang.setcolor, cmdName: "interlacetable", exec: (function () { + _$jscoverage['plugins/contextmenu.js'][237]++; + this.execCommand("interlacetable"); +})}, {label: lang.unsetcolor, cmdName: "uninterlacetable", exec: (function () { + _$jscoverage['plugins/contextmenu.js'][244]++; + this.execCommand("uninterlacetable"); +})}, {label: lang.setbackground, cmdName: "settablebackground", exec: (function () { + _$jscoverage['plugins/contextmenu.js'][251]++; + this.execCommand("settablebackground", {repeat: true, colorList: ["#bbb", "#ccc"]}); +})}, {label: lang.unsetbackground, cmdName: "cleartablebackground", exec: (function () { + _$jscoverage['plugins/contextmenu.js'][258]++; + this.execCommand("cleartablebackground"); +})}, {label: lang.redandblue, cmdName: "settablebackground", exec: (function () { + _$jscoverage['plugins/contextmenu.js'][265]++; + this.execCommand("settablebackground", {repeat: true, colorList: ["red", "blue"]}); +})}, {label: lang.threecolorgradient, cmdName: "settablebackground", exec: (function () { + _$jscoverage['plugins/contextmenu.js'][272]++; + this.execCommand("settablebackground", {repeat: true, colorList: ["#aaa", "#bbb", "#ccc"]}); +})}]}, {group: lang.aligntd, icon: "aligntd", subMenu: [{cmdName: "cellalignment", value: {align: "left", vAlign: "top"}}, {cmdName: "cellalignment", value: {align: "center", vAlign: "top"}}, {cmdName: "cellalignment", value: {align: "right", vAlign: "top"}}, {cmdName: "cellalignment", value: {align: "left", vAlign: "middle"}}, {cmdName: "cellalignment", value: {align: "center", vAlign: "middle"}}, {cmdName: "cellalignment", value: {align: "right", vAlign: "middle"}}, {cmdName: "cellalignment", value: {align: "left", vAlign: "bottom"}}, {cmdName: "cellalignment", value: {align: "center", vAlign: "bottom"}}, {cmdName: "cellalignment", value: {align: "right", vAlign: "bottom"}}]}, {group: lang.aligntable, icon: "aligntable", subMenu: [{cmdName: "tablealignment", className: "left", label: lang.tableleft, value: "left"}, {cmdName: "tablealignment", className: "center", label: lang.tablecenter, value: "center"}, {cmdName: "tablealignment", className: "right", label: lang.tableright, value: "right"}]}, "-", {label: lang.insertparagraphbefore, cmdName: "insertparagraph", value: true}, {label: lang.insertparagraphafter, cmdName: "insertparagraph"}, {label: lang.copy, cmdName: "copy", exec: (function () { + _$jscoverage['plugins/contextmenu.js'][357]++; + alert(lang.copymsg); +}), query: (function () { + _$jscoverage['plugins/contextmenu.js'][360]++; + return 0; +})}, {label: lang.paste, cmdName: "paste", exec: (function () { + _$jscoverage['plugins/contextmenu.js'][367]++; + alert(lang.pastemsg); +}), query: (function () { + _$jscoverage['plugins/contextmenu.js'][370]++; + return 0; +})}, {label: lang.highlightcode, cmdName: "highlightcode", exec: (function () { + _$jscoverage['plugins/contextmenu.js'][376]++; + if (UE.ui.highlightcode) { + _$jscoverage['plugins/contextmenu.js'][377]++; + new (UE.ui.highlightcode)(this); + } + _$jscoverage['plugins/contextmenu.js'][379]++; + this.ui._dialogs.highlightcodeDialog.open(); +})}]); + _$jscoverage['plugins/contextmenu.js'][383]++; + if ((! items.length)) { + _$jscoverage['plugins/contextmenu.js'][384]++; + return; + } + _$jscoverage['plugins/contextmenu.js'][386]++; + var uiUtils = UE.ui.uiUtils; + _$jscoverage['plugins/contextmenu.js'][388]++; + me.addListener("contextmenu", (function (type, evt) { + _$jscoverage['plugins/contextmenu.js'][390]++; + var offset = uiUtils.getViewportOffsetByEvent(evt); + _$jscoverage['plugins/contextmenu.js'][391]++; + me.fireEvent("beforeselectionchange"); + _$jscoverage['plugins/contextmenu.js'][392]++; + if (menu) { + _$jscoverage['plugins/contextmenu.js'][393]++; + menu.destroy(); + } + _$jscoverage['plugins/contextmenu.js'][395]++; + for (var i = 0, ti, contextItems = []; (ti = items[i]); (i++)) { + _$jscoverage['plugins/contextmenu.js'][396]++; + var last; + _$jscoverage['plugins/contextmenu.js'][397]++; + (function (item) { + _$jscoverage['plugins/contextmenu.js'][398]++; + if ((item == "-")) { + _$jscoverage['plugins/contextmenu.js'][399]++; + if (((last = contextItems[(contextItems.length - 1)]) && (last !== "-"))) { + _$jscoverage['plugins/contextmenu.js'][400]++; + contextItems.push("-"); + } + } + else { + _$jscoverage['plugins/contextmenu.js'][402]++; + if (item.hasOwnProperty("group")) { + _$jscoverage['plugins/contextmenu.js'][403]++; + for (var j = 0, cj, subMenu = []; (cj = item.subMenu[j]); (j++)) { + _$jscoverage['plugins/contextmenu.js'][404]++; + (function (subItem) { + _$jscoverage['plugins/contextmenu.js'][405]++; + if ((subItem == "-")) { + _$jscoverage['plugins/contextmenu.js'][406]++; + if (((last = subMenu[(subMenu.length - 1)]) && (last !== "-"))) { + _$jscoverage['plugins/contextmenu.js'][407]++; + subMenu.push("-"); + } + else { + _$jscoverage['plugins/contextmenu.js'][409]++; + subMenu.splice((subMenu.length - 1)); + } + } + else { + _$jscoverage['plugins/contextmenu.js'][412]++; + if (((me.commands[subItem.cmdName] || UE.commands[subItem.cmdName] || subItem.query) && ((subItem.query? subItem.query(): me.queryCommandState(subItem.cmdName)) > -1))) { + _$jscoverage['plugins/contextmenu.js'][414]++; + subMenu.push({"label": (subItem.label || me.getLang(("contextMenu." + subItem.cmdName + (subItem.value || ""))) || ""), "className": ("edui-for-" + subItem.cmdName + (subItem.className? (" edui-for-" + subItem.cmdName + "-" + subItem.className): "")), onclick: (subItem.exec? (function () { + _$jscoverage['plugins/contextmenu.js'][418]++; + subItem.exec.call(me); +}): (function () { + _$jscoverage['plugins/contextmenu.js'][420]++; + me.execCommand(subItem.cmdName, subItem.value); +}))}); + } + } +})(cj); +} + _$jscoverage['plugins/contextmenu.js'][427]++; + if (subMenu.length) { + _$jscoverage['plugins/contextmenu.js'][428]++; + function getLabel() { + _$jscoverage['plugins/contextmenu.js'][429]++; + switch (item.icon) { + case "table": + _$jscoverage['plugins/contextmenu.js'][431]++; + return me.getLang("contextMenu.table"); + case "justifyjustify": + _$jscoverage['plugins/contextmenu.js'][433]++; + return me.getLang("contextMenu.paragraph"); + case "aligntd": + _$jscoverage['plugins/contextmenu.js'][435]++; + return me.getLang("contextMenu.aligntd"); + case "aligntable": + _$jscoverage['plugins/contextmenu.js'][437]++; + return me.getLang("contextMenu.aligntable"); + case "tablesort": + _$jscoverage['plugins/contextmenu.js'][439]++; + return lang.tablesort; + case "borderBack": + _$jscoverage['plugins/contextmenu.js'][441]++; + return lang.borderbk; + default: + _$jscoverage['plugins/contextmenu.js'][443]++; + return ""; + } +} + _$jscoverage['plugins/contextmenu.js'][446]++; + contextItems.push({"label": getLabel(), className: ("edui-for-" + item.icon), "subMenu": {items: subMenu, editor: me}}); + } + } + else { + _$jscoverage['plugins/contextmenu.js'][459]++; + if (((me.commands[item.cmdName] || UE.commands[item.cmdName] || item.query) && ((item.query? item.query.call(me): me.queryCommandState(item.cmdName)) > -1))) { + _$jscoverage['plugins/contextmenu.js'][462]++; + if ((item.cmdName == "highlightcode")) { + _$jscoverage['plugins/contextmenu.js'][463]++; + if (((me.queryCommandState(item.cmdName) == 1) && (item.icon != "deletehighlightcode"))) { + _$jscoverage['plugins/contextmenu.js'][464]++; + return; + } + _$jscoverage['plugins/contextmenu.js'][466]++; + if (((me.queryCommandState(item.cmdName) != 1) && (item.icon == "deletehighlightcode"))) { + _$jscoverage['plugins/contextmenu.js'][467]++; + return; + } + } + _$jscoverage['plugins/contextmenu.js'][470]++; + contextItems.push({"label": (item.label || me.getLang(("contextMenu." + item.cmdName))), className: ("edui-for-" + (item.icon? item.icon: (item.cmdName + (item.value || "")))), onclick: (item.exec? (function () { + _$jscoverage['plugins/contextmenu.js'][474]++; + item.exec.call(me); +}): (function () { + _$jscoverage['plugins/contextmenu.js'][476]++; + me.execCommand(item.cmdName, item.value); +}))}); + } + } + } +})(ti); +} + _$jscoverage['plugins/contextmenu.js'][485]++; + if ((contextItems[(contextItems.length - 1)] == "-")) { + _$jscoverage['plugins/contextmenu.js'][486]++; + contextItems.pop(); + } + _$jscoverage['plugins/contextmenu.js'][489]++; + menu = new (UE.ui.Menu)({items: contextItems, className: "edui-contextmenu", editor: me}); + _$jscoverage['plugins/contextmenu.js'][494]++; + menu.render(); + _$jscoverage['plugins/contextmenu.js'][495]++; + menu.showAt(offset); + _$jscoverage['plugins/contextmenu.js'][497]++; + me.fireEvent("aftershowcontextmenu", menu); + _$jscoverage['plugins/contextmenu.js'][499]++; + domUtils.preventDefault(evt); + _$jscoverage['plugins/contextmenu.js'][500]++; + if (browser.ie) { + _$jscoverage['plugins/contextmenu.js'][501]++; + var ieRange; + _$jscoverage['plugins/contextmenu.js'][502]++; + try { + _$jscoverage['plugins/contextmenu.js'][503]++; + ieRange = me.selection.getNative().createRange(); + } + catch (e) { + _$jscoverage['plugins/contextmenu.js'][505]++; + return; + } + _$jscoverage['plugins/contextmenu.js'][507]++; + if (ieRange.item) { + _$jscoverage['plugins/contextmenu.js'][508]++; + var range = new (dom.Range)(me.document); + _$jscoverage['plugins/contextmenu.js'][509]++; + range.selectNode(ieRange.item(0)).select(true, true); + } + } +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/convertcase.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/convertcase.js new file mode 100644 index 000000000..89df8c0c9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/convertcase.js @@ -0,0 +1,91 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/convertcase.js']) { + _$jscoverage['plugins/convertcase.js'] = []; + _$jscoverage['plugins/convertcase.js'][28] = 0; + _$jscoverage['plugins/convertcase.js'][31] = 0; + _$jscoverage['plugins/convertcase.js'][32] = 0; + _$jscoverage['plugins/convertcase.js'][33] = 0; + _$jscoverage['plugins/convertcase.js'][34] = 0; + _$jscoverage['plugins/convertcase.js'][36] = 0; + _$jscoverage['plugins/convertcase.js'][39] = 0; + _$jscoverage['plugins/convertcase.js'][42] = 0; + _$jscoverage['plugins/convertcase.js'][44] = 0; + _$jscoverage['plugins/convertcase.js'][45] = 0; + _$jscoverage['plugins/convertcase.js'][47] = 0; + _$jscoverage['plugins/convertcase.js'][48] = 0; + _$jscoverage['plugins/convertcase.js'][49] = 0; + _$jscoverage['plugins/convertcase.js'][53] = 0; +} +_$jscoverage['plugins/convertcase.js'].source = ["/**"," * 大小写转换"," * @file"," * @since 1.2.6.1"," */","","/**"," * 把选区内文本变大写"," * @command touppercase"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'touppercase' );"," * ```"," */","","/**"," * 把选区内文本变小写"," * @command tolowercase"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'tolowercase' );"," * ```"," */","UE.commands['touppercase'] =","UE.commands['tolowercase'] = {"," execCommand:function (cmd) {"," var me = this;"," var rng = me.selection.getRange();"," if(rng.collapsed){"," return rng;"," }"," var bk = rng.createBookmark(),"," bkEnd = bk.end,"," filterFn = function( node ) {"," return !domUtils.isBr(node) && !domUtils.isWhitespace( node );"," },"," curNode = domUtils.getNextDomNode( bk.start, false, filterFn );"," while ( curNode && (domUtils.getPosition( curNode, bkEnd ) & domUtils.POSITION_PRECEDING) ) {",""," if ( curNode.nodeType == 3 ) {"," curNode.nodeValue = curNode.nodeValue[cmd == 'touppercase' ? 'toUpperCase' : 'toLowerCase']();"," }"," curNode = domUtils.getNextDomNode( curNode, true, filterFn );"," if(curNode === bkEnd){"," break;"," }",""," }"," rng.moveToBookmark(bk).select();"," }","};",""]; +_$jscoverage['plugins/convertcase.js'][28]++; +UE.commands.touppercase = (UE.commands.tolowercase = {execCommand: (function (cmd) { + _$jscoverage['plugins/convertcase.js'][31]++; + var me = this; + _$jscoverage['plugins/convertcase.js'][32]++; + var rng = me.selection.getRange(); + _$jscoverage['plugins/convertcase.js'][33]++; + if (rng.collapsed) { + _$jscoverage['plugins/convertcase.js'][34]++; + return rng; + } + _$jscoverage['plugins/convertcase.js'][36]++; + var bk = rng.createBookmark(), bkEnd = bk.end, filterFn = (function (node) { + _$jscoverage['plugins/convertcase.js'][39]++; + return ((! domUtils.isBr(node)) && (! domUtils.isWhitespace(node))); +}), curNode = domUtils.getNextDomNode(bk.start, false, filterFn); + _$jscoverage['plugins/convertcase.js'][42]++; + while ((curNode && (domUtils.getPosition(curNode, bkEnd) & domUtils.POSITION_PRECEDING))) { + _$jscoverage['plugins/convertcase.js'][44]++; + if ((curNode.nodeType == 3)) { + _$jscoverage['plugins/convertcase.js'][45]++; + curNode.nodeValue = (curNode.nodeValue[((cmd == "touppercase")? "toUpperCase": "toLowerCase")])(); + } + _$jscoverage['plugins/convertcase.js'][47]++; + curNode = domUtils.getNextDomNode(curNode, true, filterFn); + _$jscoverage['plugins/convertcase.js'][48]++; + if ((curNode === bkEnd)) { + _$jscoverage['plugins/convertcase.js'][49]++; + break; + } +} + _$jscoverage['plugins/convertcase.js'][53]++; + rng.moveToBookmark(bk).select(); +})}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/customstyle.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/customstyle.js new file mode 100644 index 000000000..fbf440cbb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/customstyle.js @@ -0,0 +1,293 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/customstyle.js']) { + _$jscoverage['plugins/customstyle.js'] = []; + _$jscoverage['plugins/customstyle.js'][6] = 0; + _$jscoverage['plugins/customstyle.js'][7] = 0; + _$jscoverage['plugins/customstyle.js'][8] = 0; + _$jscoverage['plugins/customstyle.js'][14] = 0; + _$jscoverage['plugins/customstyle.js'][16] = 0; + _$jscoverage['plugins/customstyle.js'][19] = 0; + _$jscoverage['plugins/customstyle.js'][22] = 0; + _$jscoverage['plugins/customstyle.js'][23] = 0; + _$jscoverage['plugins/customstyle.js'][24] = 0; + _$jscoverage['plugins/customstyle.js'][26] = 0; + _$jscoverage['plugins/customstyle.js'][27] = 0; + _$jscoverage['plugins/customstyle.js'][28] = 0; + _$jscoverage['plugins/customstyle.js'][29] = 0; + _$jscoverage['plugins/customstyle.js'][30] = 0; + _$jscoverage['plugins/customstyle.js'][32] = 0; + _$jscoverage['plugins/customstyle.js'][33] = 0; + _$jscoverage['plugins/customstyle.js'][34] = 0; + _$jscoverage['plugins/customstyle.js'][35] = 0; + _$jscoverage['plugins/customstyle.js'][36] = 0; + _$jscoverage['plugins/customstyle.js'][38] = 0; + _$jscoverage['plugins/customstyle.js'][43] = 0; + _$jscoverage['plugins/customstyle.js'][45] = 0; + _$jscoverage['plugins/customstyle.js'][46] = 0; + _$jscoverage['plugins/customstyle.js'][48] = 0; + _$jscoverage['plugins/customstyle.js'][49] = 0; + _$jscoverage['plugins/customstyle.js'][50] = 0; + _$jscoverage['plugins/customstyle.js'][51] = 0; + _$jscoverage['plugins/customstyle.js'][55] = 0; + _$jscoverage['plugins/customstyle.js'][56] = 0; + _$jscoverage['plugins/customstyle.js'][57] = 0; + _$jscoverage['plugins/customstyle.js'][58] = 0; + _$jscoverage['plugins/customstyle.js'][60] = 0; + _$jscoverage['plugins/customstyle.js'][63] = 0; + _$jscoverage['plugins/customstyle.js'][64] = 0; + _$jscoverage['plugins/customstyle.js'][66] = 0; + _$jscoverage['plugins/customstyle.js'][68] = 0; + _$jscoverage['plugins/customstyle.js'][73] = 0; + _$jscoverage['plugins/customstyle.js'][75] = 0; + _$jscoverage['plugins/customstyle.js'][76] = 0; + _$jscoverage['plugins/customstyle.js'][77] = 0; + _$jscoverage['plugins/customstyle.js'][78] = 0; + _$jscoverage['plugins/customstyle.js'][79] = 0; + _$jscoverage['plugins/customstyle.js'][80] = 0; + _$jscoverage['plugins/customstyle.js'][81] = 0; + _$jscoverage['plugins/customstyle.js'][83] = 0; + _$jscoverage['plugins/customstyle.js'][84] = 0; + _$jscoverage['plugins/customstyle.js'][85] = 0; + _$jscoverage['plugins/customstyle.js'][86] = 0; + _$jscoverage['plugins/customstyle.js'][90] = 0; + _$jscoverage['plugins/customstyle.js'][91] = 0; + _$jscoverage['plugins/customstyle.js'][92] = 0; + _$jscoverage['plugins/customstyle.js'][93] = 0; + _$jscoverage['plugins/customstyle.js'][94] = 0; + _$jscoverage['plugins/customstyle.js'][96] = 0; + _$jscoverage['plugins/customstyle.js'][99] = 0; + _$jscoverage['plugins/customstyle.js'][100] = 0; + _$jscoverage['plugins/customstyle.js'][106] = 0; + _$jscoverage['plugins/customstyle.js'][108] = 0; + _$jscoverage['plugins/customstyle.js'][110] = 0; + _$jscoverage['plugins/customstyle.js'][114] = 0; + _$jscoverage['plugins/customstyle.js'][115] = 0; + _$jscoverage['plugins/customstyle.js'][117] = 0; + _$jscoverage['plugins/customstyle.js'][118] = 0; + _$jscoverage['plugins/customstyle.js'][119] = 0; + _$jscoverage['plugins/customstyle.js'][120] = 0; + _$jscoverage['plugins/customstyle.js'][121] = 0; + _$jscoverage['plugins/customstyle.js'][123] = 0; + _$jscoverage['plugins/customstyle.js'][124] = 0; + _$jscoverage['plugins/customstyle.js'][125] = 0; + _$jscoverage['plugins/customstyle.js'][126] = 0; + _$jscoverage['plugins/customstyle.js'][127] = 0; + _$jscoverage['plugins/customstyle.js'][128] = 0; +} +_$jscoverage['plugins/customstyle.js'].source = ["/**"," * 自定义样式命令支持"," * @file"," */","","UE.plugins['customstyle'] = function() {"," var me = this;"," me.setOpt({ 'customstyle':["," {tag:'h1',name:'tc', style:'font-size:32px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;margin:0 0 20px 0;'},"," {tag:'h1',name:'tl', style:'font-size:32px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:left;margin:0 0 10px 0;'},"," {tag:'span',name:'im', style:'font-size:16px;font-style:italic;font-weight:bold;line-height:18px;'},"," {tag:'span',name:'hi', style:'font-size:16px;font-style:italic;font-weight:bold;color:rgb(51, 153, 204);line-height:18px;'}"," ]});"," me.commands['customstyle'] = {"," execCommand : function(cmdName, obj) {"," var me = this,"," tagName = obj.tag,"," node = domUtils.findParent(me.selection.getStart(), function(node) {"," return node.getAttribute('label');"," }, true),"," range,bk,tmpObj = {};"," for (var p in obj) {"," if(obj[p]!==undefined)"," tmpObj[p] = obj[p];"," }"," delete tmpObj.tag;"," if (node && node.getAttribute('label') == obj.label) {"," range = this.selection.getRange();"," bk = range.createBookmark();"," if (range.collapsed) {"," //trace:1732 删掉自定义标签,要有p来回填站位"," if(dtd.$block[node.tagName]){"," var fillNode = me.document.createElement('p');"," domUtils.moveChild(node, fillNode);"," node.parentNode.insertBefore(fillNode, node);"," domUtils.remove(node);"," }else{"," domUtils.remove(node,true);"," }",""," } else {",""," var common = domUtils.getCommonAncestor(bk.start, bk.end),"," nodes = domUtils.getElementsByTagName(common, tagName);"," if(new RegExp(tagName,'i').test(common.tagName)){"," nodes.push(common);"," }"," for (var i = 0,ni; ni = nodes[i++];) {"," if (ni.getAttribute('label') == obj.label) {"," var ps = domUtils.getPosition(ni, bk.start),pe = domUtils.getPosition(ni, bk.end);"," if ((ps & domUtils.POSITION_FOLLOWING || ps & domUtils.POSITION_CONTAINS)"," &&"," (pe & domUtils.POSITION_PRECEDING || pe & domUtils.POSITION_CONTAINS)"," )"," if (dtd.$block[tagName]) {"," var fillNode = me.document.createElement('p');"," domUtils.moveChild(ni, fillNode);"," ni.parentNode.insertBefore(fillNode, ni);"," }"," domUtils.remove(ni, true);"," }"," }"," node = domUtils.findParent(common, function(node) {"," return node.getAttribute('label') == obj.label;"," }, true);"," if (node) {",""," domUtils.remove(node, true);",""," }",""," }"," range.moveToBookmark(bk).select();"," } else {"," if (dtd.$block[tagName]) {"," this.execCommand('paragraph', tagName, tmpObj,'customstyle');"," range = me.selection.getRange();"," if (!range.collapsed) {"," range.collapse();"," node = domUtils.findParent(me.selection.getStart(), function(node) {"," return node.getAttribute('label') == obj.label;"," }, true);"," var pNode = me.document.createElement('p');"," domUtils.insertAfter(node, pNode);"," domUtils.fillNode(me.document, pNode);"," range.setStart(pNode, 0).setCursor();"," }"," } else {",""," range = me.selection.getRange();"," if (range.collapsed) {"," node = me.document.createElement(tagName);"," domUtils.setAttributes(node, tmpObj);"," range.insertNode(node).setStart(node, 0).setCursor();",""," return;"," }",""," bk = range.createBookmark();"," range.applyInlineStyle(tagName, tmpObj).moveToBookmark(bk).select();"," }"," }",""," },"," queryCommandValue : function() {"," var parent = domUtils.filterNodeList("," this.selection.getStartElementPath(),"," function(node){return node.getAttribute('label')}"," );"," return parent ? parent.getAttribute('label') : '';"," }"," };"," //当去掉customstyle是,如果是块元素,用p代替"," me.addListener('keyup', function(type, evt) {"," var keyCode = evt.keyCode || evt.which;",""," if (keyCode == 32 || keyCode == 13) {"," var range = me.selection.getRange();"," if (range.collapsed) {"," var node = domUtils.findParent(me.selection.getStart(), function(node) {"," return node.getAttribute('label');"," }, true);"," if (node && dtd.$block[node.tagName] && domUtils.isEmptyNode(node)) {"," var p = me.document.createElement('p');"," domUtils.insertAfter(node, p);"," domUtils.fillNode(me.document, p);"," domUtils.remove(node);"," range.setStart(p, 0).setCursor();","",""," }"," }"," }"," });","};"]; +_$jscoverage['plugins/customstyle.js'][6]++; +UE.plugins.customstyle = (function () { + _$jscoverage['plugins/customstyle.js'][7]++; + var me = this; + _$jscoverage['plugins/customstyle.js'][8]++; + me.setOpt({"customstyle": [{tag: "h1", name: "tc", style: "font-size:32px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;margin:0 0 20px 0;"}, {tag: "h1", name: "tl", style: "font-size:32px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:left;margin:0 0 10px 0;"}, {tag: "span", name: "im", style: "font-size:16px;font-style:italic;font-weight:bold;line-height:18px;"}, {tag: "span", name: "hi", style: "font-size:16px;font-style:italic;font-weight:bold;color:rgb(51, 153, 204);line-height:18px;"}]}); + _$jscoverage['plugins/customstyle.js'][14]++; + me.commands.customstyle = {execCommand: (function (cmdName, obj) { + _$jscoverage['plugins/customstyle.js'][16]++; + var me = this, tagName = obj.tag, node = domUtils.findParent(me.selection.getStart(), (function (node) { + _$jscoverage['plugins/customstyle.js'][19]++; + return node.getAttribute("label"); +}), true), range, bk, tmpObj = {}; + _$jscoverage['plugins/customstyle.js'][22]++; + for (var p in obj) { + _$jscoverage['plugins/customstyle.js'][23]++; + if ((obj[p] !== undefined)) { + _$jscoverage['plugins/customstyle.js'][24]++; + tmpObj[p] = obj[p]; + } +} + _$jscoverage['plugins/customstyle.js'][26]++; + (delete tmpObj.tag); + _$jscoverage['plugins/customstyle.js'][27]++; + if ((node && (node.getAttribute("label") == obj.label))) { + _$jscoverage['plugins/customstyle.js'][28]++; + range = this.selection.getRange(); + _$jscoverage['plugins/customstyle.js'][29]++; + bk = range.createBookmark(); + _$jscoverage['plugins/customstyle.js'][30]++; + if (range.collapsed) { + _$jscoverage['plugins/customstyle.js'][32]++; + if (dtd.$block[node.tagName]) { + _$jscoverage['plugins/customstyle.js'][33]++; + var fillNode = me.document.createElement("p"); + _$jscoverage['plugins/customstyle.js'][34]++; + domUtils.moveChild(node, fillNode); + _$jscoverage['plugins/customstyle.js'][35]++; + node.parentNode.insertBefore(fillNode, node); + _$jscoverage['plugins/customstyle.js'][36]++; + domUtils.remove(node); + } + else { + _$jscoverage['plugins/customstyle.js'][38]++; + domUtils.remove(node, true); + } + } + else { + _$jscoverage['plugins/customstyle.js'][43]++; + var common = domUtils.getCommonAncestor(bk.start, bk.end), nodes = domUtils.getElementsByTagName(common, tagName); + _$jscoverage['plugins/customstyle.js'][45]++; + if (new RegExp(tagName, "i").test(common.tagName)) { + _$jscoverage['plugins/customstyle.js'][46]++; + nodes.push(common); + } + _$jscoverage['plugins/customstyle.js'][48]++; + for (var i = 0, ni; (ni = nodes[(i++)]);) { + _$jscoverage['plugins/customstyle.js'][49]++; + if ((ni.getAttribute("label") == obj.label)) { + _$jscoverage['plugins/customstyle.js'][50]++; + var ps = domUtils.getPosition(ni, bk.start), pe = domUtils.getPosition(ni, bk.end); + _$jscoverage['plugins/customstyle.js'][51]++; + if ((((ps & domUtils.POSITION_FOLLOWING) || (ps & domUtils.POSITION_CONTAINS)) && ((pe & domUtils.POSITION_PRECEDING) || (pe & domUtils.POSITION_CONTAINS)))) { + _$jscoverage['plugins/customstyle.js'][55]++; + if (dtd.$block[tagName]) { + _$jscoverage['plugins/customstyle.js'][56]++; + var fillNode = me.document.createElement("p"); + _$jscoverage['plugins/customstyle.js'][57]++; + domUtils.moveChild(ni, fillNode); + _$jscoverage['plugins/customstyle.js'][58]++; + ni.parentNode.insertBefore(fillNode, ni); + } + } + _$jscoverage['plugins/customstyle.js'][60]++; + domUtils.remove(ni, true); + } +} + _$jscoverage['plugins/customstyle.js'][63]++; + node = domUtils.findParent(common, (function (node) { + _$jscoverage['plugins/customstyle.js'][64]++; + return (node.getAttribute("label") == obj.label); +}), true); + _$jscoverage['plugins/customstyle.js'][66]++; + if (node) { + _$jscoverage['plugins/customstyle.js'][68]++; + domUtils.remove(node, true); + } + } + _$jscoverage['plugins/customstyle.js'][73]++; + range.moveToBookmark(bk).select(); + } + else { + _$jscoverage['plugins/customstyle.js'][75]++; + if (dtd.$block[tagName]) { + _$jscoverage['plugins/customstyle.js'][76]++; + this.execCommand("paragraph", tagName, tmpObj, "customstyle"); + _$jscoverage['plugins/customstyle.js'][77]++; + range = me.selection.getRange(); + _$jscoverage['plugins/customstyle.js'][78]++; + if ((! range.collapsed)) { + _$jscoverage['plugins/customstyle.js'][79]++; + range.collapse(); + _$jscoverage['plugins/customstyle.js'][80]++; + node = domUtils.findParent(me.selection.getStart(), (function (node) { + _$jscoverage['plugins/customstyle.js'][81]++; + return (node.getAttribute("label") == obj.label); +}), true); + _$jscoverage['plugins/customstyle.js'][83]++; + var pNode = me.document.createElement("p"); + _$jscoverage['plugins/customstyle.js'][84]++; + domUtils.insertAfter(node, pNode); + _$jscoverage['plugins/customstyle.js'][85]++; + domUtils.fillNode(me.document, pNode); + _$jscoverage['plugins/customstyle.js'][86]++; + range.setStart(pNode, 0).setCursor(); + } + } + else { + _$jscoverage['plugins/customstyle.js'][90]++; + range = me.selection.getRange(); + _$jscoverage['plugins/customstyle.js'][91]++; + if (range.collapsed) { + _$jscoverage['plugins/customstyle.js'][92]++; + node = me.document.createElement(tagName); + _$jscoverage['plugins/customstyle.js'][93]++; + domUtils.setAttributes(node, tmpObj); + _$jscoverage['plugins/customstyle.js'][94]++; + range.insertNode(node).setStart(node, 0).setCursor(); + _$jscoverage['plugins/customstyle.js'][96]++; + return; + } + _$jscoverage['plugins/customstyle.js'][99]++; + bk = range.createBookmark(); + _$jscoverage['plugins/customstyle.js'][100]++; + range.applyInlineStyle(tagName, tmpObj).moveToBookmark(bk).select(); + } + } +}), queryCommandValue: (function () { + _$jscoverage['plugins/customstyle.js'][106]++; + var parent = domUtils.filterNodeList(this.selection.getStartElementPath(), (function (node) { + _$jscoverage['plugins/customstyle.js'][108]++; + return node.getAttribute("label"); +})); + _$jscoverage['plugins/customstyle.js'][110]++; + return (parent? parent.getAttribute("label"): ""); +})}; + _$jscoverage['plugins/customstyle.js'][114]++; + me.addListener("keyup", (function (type, evt) { + _$jscoverage['plugins/customstyle.js'][115]++; + var keyCode = (evt.keyCode || evt.which); + _$jscoverage['plugins/customstyle.js'][117]++; + if (((keyCode == 32) || (keyCode == 13))) { + _$jscoverage['plugins/customstyle.js'][118]++; + var range = me.selection.getRange(); + _$jscoverage['plugins/customstyle.js'][119]++; + if (range.collapsed) { + _$jscoverage['plugins/customstyle.js'][120]++; + var node = domUtils.findParent(me.selection.getStart(), (function (node) { + _$jscoverage['plugins/customstyle.js'][121]++; + return node.getAttribute("label"); +}), true); + _$jscoverage['plugins/customstyle.js'][123]++; + if ((node && dtd.$block[node.tagName] && domUtils.isEmptyNode(node))) { + _$jscoverage['plugins/customstyle.js'][124]++; + var p = me.document.createElement("p"); + _$jscoverage['plugins/customstyle.js'][125]++; + domUtils.insertAfter(node, p); + _$jscoverage['plugins/customstyle.js'][126]++; + domUtils.fillNode(me.document, p); + _$jscoverage['plugins/customstyle.js'][127]++; + domUtils.remove(node); + _$jscoverage['plugins/customstyle.js'][128]++; + range.setStart(p, 0).setCursor(); + } + } + } +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/defaultfilter.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/defaultfilter.js new file mode 100644 index 000000000..7cb7f3dad --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/defaultfilter.js @@ -0,0 +1,388 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/defaultfilter.js']) { + _$jscoverage['plugins/defaultfilter.js'] = []; + _$jscoverage['plugins/defaultfilter.js'][4] = 0; + _$jscoverage['plugins/defaultfilter.js'][5] = 0; + _$jscoverage['plugins/defaultfilter.js'][6] = 0; + _$jscoverage['plugins/defaultfilter.js'][9] = 0; + _$jscoverage['plugins/defaultfilter.js'][10] = 0; + _$jscoverage['plugins/defaultfilter.js'][11] = 0; + _$jscoverage['plugins/defaultfilter.js'][13] = 0; + _$jscoverage['plugins/defaultfilter.js'][14] = 0; + _$jscoverage['plugins/defaultfilter.js'][15] = 0; + _$jscoverage['plugins/defaultfilter.js'][16] = 0; + _$jscoverage['plugins/defaultfilter.js'][17] = 0; + _$jscoverage['plugins/defaultfilter.js'][18] = 0; + _$jscoverage['plugins/defaultfilter.js'][20] = 0; + _$jscoverage['plugins/defaultfilter.js'][22] = 0; + _$jscoverage['plugins/defaultfilter.js'][25] = 0; + _$jscoverage['plugins/defaultfilter.js'][29] = 0; + _$jscoverage['plugins/defaultfilter.js'][30] = 0; + _$jscoverage['plugins/defaultfilter.js'][31] = 0; + _$jscoverage['plugins/defaultfilter.js'][33] = 0; + _$jscoverage['plugins/defaultfilter.js'][34] = 0; + _$jscoverage['plugins/defaultfilter.js'][36] = 0; + _$jscoverage['plugins/defaultfilter.js'][39] = 0; + _$jscoverage['plugins/defaultfilter.js'][40] = 0; + _$jscoverage['plugins/defaultfilter.js'][41] = 0; + _$jscoverage['plugins/defaultfilter.js'][42] = 0; + _$jscoverage['plugins/defaultfilter.js'][45] = 0; + _$jscoverage['plugins/defaultfilter.js'][46] = 0; + _$jscoverage['plugins/defaultfilter.js'][48] = 0; + _$jscoverage['plugins/defaultfilter.js'][49] = 0; + _$jscoverage['plugins/defaultfilter.js'][50] = 0; + _$jscoverage['plugins/defaultfilter.js'][51] = 0; + _$jscoverage['plugins/defaultfilter.js'][52] = 0; + _$jscoverage['plugins/defaultfilter.js'][56] = 0; + _$jscoverage['plugins/defaultfilter.js'][58] = 0; + _$jscoverage['plugins/defaultfilter.js'][59] = 0; + _$jscoverage['plugins/defaultfilter.js'][60] = 0; + _$jscoverage['plugins/defaultfilter.js'][69] = 0; + _$jscoverage['plugins/defaultfilter.js'][70] = 0; + _$jscoverage['plugins/defaultfilter.js'][72] = 0; + _$jscoverage['plugins/defaultfilter.js'][74] = 0; + _$jscoverage['plugins/defaultfilter.js'][75] = 0; + _$jscoverage['plugins/defaultfilter.js'][78] = 0; + _$jscoverage['plugins/defaultfilter.js'][79] = 0; + _$jscoverage['plugins/defaultfilter.js'][80] = 0; + _$jscoverage['plugins/defaultfilter.js'][82] = 0; + _$jscoverage['plugins/defaultfilter.js'][83] = 0; + _$jscoverage['plugins/defaultfilter.js'][85] = 0; + _$jscoverage['plugins/defaultfilter.js'][86] = 0; + _$jscoverage['plugins/defaultfilter.js'][87] = 0; + _$jscoverage['plugins/defaultfilter.js'][88] = 0; + _$jscoverage['plugins/defaultfilter.js'][90] = 0; + _$jscoverage['plugins/defaultfilter.js'][91] = 0; + _$jscoverage['plugins/defaultfilter.js'][92] = 0; + _$jscoverage['plugins/defaultfilter.js'][94] = 0; + _$jscoverage['plugins/defaultfilter.js'][98] = 0; + _$jscoverage['plugins/defaultfilter.js'][99] = 0; + _$jscoverage['plugins/defaultfilter.js'][101] = 0; + _$jscoverage['plugins/defaultfilter.js'][102] = 0; + _$jscoverage['plugins/defaultfilter.js'][104] = 0; + _$jscoverage['plugins/defaultfilter.js'][105] = 0; + _$jscoverage['plugins/defaultfilter.js'][108] = 0; + _$jscoverage['plugins/defaultfilter.js'][109] = 0; + _$jscoverage['plugins/defaultfilter.js'][111] = 0; + _$jscoverage['plugins/defaultfilter.js'][112] = 0; + _$jscoverage['plugins/defaultfilter.js'][113] = 0; + _$jscoverage['plugins/defaultfilter.js'][115] = 0; + _$jscoverage['plugins/defaultfilter.js'][116] = 0; + _$jscoverage['plugins/defaultfilter.js'][117] = 0; + _$jscoverage['plugins/defaultfilter.js'][119] = 0; + _$jscoverage['plugins/defaultfilter.js'][123] = 0; + _$jscoverage['plugins/defaultfilter.js'][125] = 0; + _$jscoverage['plugins/defaultfilter.js'][130] = 0; + _$jscoverage['plugins/defaultfilter.js'][131] = 0; + _$jscoverage['plugins/defaultfilter.js'][138] = 0; + _$jscoverage['plugins/defaultfilter.js'][140] = 0; + _$jscoverage['plugins/defaultfilter.js'][141] = 0; + _$jscoverage['plugins/defaultfilter.js'][142] = 0; + _$jscoverage['plugins/defaultfilter.js'][144] = 0; + _$jscoverage['plugins/defaultfilter.js'][146] = 0; + _$jscoverage['plugins/defaultfilter.js'][147] = 0; + _$jscoverage['plugins/defaultfilter.js'][148] = 0; + _$jscoverage['plugins/defaultfilter.js'][150] = 0; + _$jscoverage['plugins/defaultfilter.js'][152] = 0; + _$jscoverage['plugins/defaultfilter.js'][154] = 0; + _$jscoverage['plugins/defaultfilter.js'][155] = 0; + _$jscoverage['plugins/defaultfilter.js'][156] = 0; + _$jscoverage['plugins/defaultfilter.js'][157] = 0; + _$jscoverage['plugins/defaultfilter.js'][159] = 0; + _$jscoverage['plugins/defaultfilter.js'][161] = 0; + _$jscoverage['plugins/defaultfilter.js'][162] = 0; + _$jscoverage['plugins/defaultfilter.js'][167] = 0; + _$jscoverage['plugins/defaultfilter.js'][169] = 0; + _$jscoverage['plugins/defaultfilter.js'][170] = 0; +} +_$jscoverage['plugins/defaultfilter.js'].source = ["///import core","///plugin 编辑器默认的过滤转换机制","","UE.plugins['defaultfilter'] = function () {"," var me = this;"," me.setOpt('allowDivTransToP',true);"," //默认的过滤处理"," //进入编辑器的内容处理"," me.addInputRule(function (root) {"," var allowDivTransToP = this.options.allowDivTransToP;"," var val;"," //进行默认的处理"," root.traversal(function (node) {"," if (node.type == 'element') {"," if (!dtd.$cdata[node.tagName] && me.options.autoClearEmptyNode && dtd.$inline[node.tagName] && !dtd.$empty[node.tagName] && (!node.attrs || utils.isEmptyObject(node.attrs))) {"," if (!node.firstChild()) node.parentNode.removeChild(node);"," else if (node.tagName == 'span' && (!node.attrs || utils.isEmptyObject(node.attrs))) {"," node.parentNode.removeChild(node, true)"," }"," return;"," }"," switch (node.tagName) {"," case 'style':"," case 'script':"," node.setAttr({"," cdata_tag: node.tagName,"," cdata_data: encodeURIComponent(node.innerText() || '')"," });"," node.tagName = 'div';"," node.removeChild(node.firstChild());"," break;"," case 'a':"," if (val = node.getAttr('href')) {"," node.setAttr('_href', val)"," }"," break;"," case 'img':"," //todo base64暂时去掉,后边做远程图片上传后,干掉这个"," if (val = node.getAttr('src')) {"," if (/^data:/.test(val)) {"," node.parentNode.removeChild(node);"," break;"," }"," }"," node.setAttr('_src', node.getAttr('src'));"," break;"," case 'span':"," if (browser.webkit && (val = node.getStyle('white-space'))) {"," if (/nowrap|normal/.test(val)) {"," node.setStyle('white-space', '');"," if (me.options.autoClearEmptyNode && utils.isEmptyObject(node.attrs)) {"," node.parentNode.removeChild(node, true)"," }"," }"," }"," break;"," case 'p':"," if (val = node.getAttr('align')) {"," node.setAttr('align');"," node.setStyle('text-align', val)"," }"," //trace:3431","// var cssStyle = node.getAttr('style');","// if (cssStyle) {","// cssStyle = cssStyle.replace(/(margin|padding)[^;]+/g, '');","// node.setAttr('style', cssStyle)","//","// }"," if (!node.firstChild()) {"," node.innerHTML(browser.ie ? '&nbsp;' : '<br/>')"," }"," break;"," case 'div':"," if(node.getAttr('cdata_tag')){"," break;"," }"," //针对代码这里不处理插入代码的div"," val = node.getAttr('class');"," if(val && /^line number\\d+/.test(val)){"," break;"," }"," if(!allowDivTransToP){"," break;"," }"," var tmpNode, p = UE.uNode.createElement('p');"," while (tmpNode = node.firstChild()) {"," if (tmpNode.type == 'text' || !UE.dom.dtd.$block[tmpNode.tagName]) {"," p.appendChild(tmpNode);"," } else {"," if (p.firstChild()) {"," node.parentNode.insertBefore(p, node);"," p = UE.uNode.createElement('p');"," } else {"," node.parentNode.insertBefore(tmpNode, node);"," }"," }"," }"," if (p.firstChild()) {"," node.parentNode.insertBefore(p, node);"," }"," node.parentNode.removeChild(node);"," break;"," case 'dl':"," node.tagName = 'ul';"," break;"," case 'dt':"," case 'dd':"," node.tagName = 'li';"," break;"," case 'li':"," var className = node.getAttr('class');"," if (!className || !/list\\-/.test(className)) {"," node.setAttr()"," }"," var tmpNodes = node.getNodesByTagName('ol ul');"," UE.utils.each(tmpNodes, function (n) {"," node.parentNode.insertAfter(n, node);"," });"," break;"," case 'td':"," case 'th':"," case 'caption':"," if(!node.children || !node.children.length){",""," node.appendChild(browser.ie ? UE.uNode.createText(' ') : UE.uNode.createElement('br'))"," }"," }",""," }"," if(node.type == 'comment'){"," node.parentNode.removeChild(node);"," }"," })",""," });",""," //从编辑器出去的内容处理"," me.addOutputRule(function (root) {",""," var val;"," root.traversal(function (node) {"," if (node.type == 'element') {",""," if (me.options.autoClearEmptyNode && dtd.$inline[node.tagName] && !dtd.$empty[node.tagName] && (!node.attrs || utils.isEmptyObject(node.attrs))) {",""," if (!node.firstChild()) node.parentNode.removeChild(node);"," else if (node.tagName == 'span' && (!node.attrs || utils.isEmptyObject(node.attrs))) {"," node.parentNode.removeChild(node, true)"," }"," return;"," }"," switch (node.tagName) {"," case 'div':"," if (val = node.getAttr('cdata_tag')) {"," node.tagName = val;"," node.appendChild(UE.uNode.createText(node.getAttr('cdata_data')));"," node.setAttr({cdata_tag: '', cdata_data: ''});"," }"," break;"," case 'a':"," if (val = node.getAttr('_href')) {"," node.setAttr({"," 'href': val,"," '_href': ''"," })"," }"," break;"," case 'img':"," if (val = node.getAttr('_src')) {"," node.setAttr({"," 'src': node.getAttr('_src'),"," '_src': ''"," })"," }","",""," }"," }",""," })","",""," });","};"]; +_$jscoverage['plugins/defaultfilter.js'][4]++; +UE.plugins.defaultfilter = (function () { + _$jscoverage['plugins/defaultfilter.js'][5]++; + var me = this; + _$jscoverage['plugins/defaultfilter.js'][6]++; + me.setOpt("allowDivTransToP", true); + _$jscoverage['plugins/defaultfilter.js'][9]++; + me.addInputRule((function (root) { + _$jscoverage['plugins/defaultfilter.js'][10]++; + var allowDivTransToP = this.options.allowDivTransToP; + _$jscoverage['plugins/defaultfilter.js'][11]++; + var val; + _$jscoverage['plugins/defaultfilter.js'][13]++; + root.traversal((function (node) { + _$jscoverage['plugins/defaultfilter.js'][14]++; + if ((node.type == "element")) { + _$jscoverage['plugins/defaultfilter.js'][15]++; + if (((! dtd.$cdata[node.tagName]) && me.options.autoClearEmptyNode && dtd.$inline[node.tagName] && (! dtd.$empty[node.tagName]) && ((! node.attrs) || utils.isEmptyObject(node.attrs)))) { + _$jscoverage['plugins/defaultfilter.js'][16]++; + if ((! node.firstChild())) { + _$jscoverage['plugins/defaultfilter.js'][16]++; + node.parentNode.removeChild(node); + } + else { + _$jscoverage['plugins/defaultfilter.js'][17]++; + if (((node.tagName == "span") && ((! node.attrs) || utils.isEmptyObject(node.attrs)))) { + _$jscoverage['plugins/defaultfilter.js'][18]++; + node.parentNode.removeChild(node, true); + } + } + _$jscoverage['plugins/defaultfilter.js'][20]++; + return; + } + _$jscoverage['plugins/defaultfilter.js'][22]++; + switch (node.tagName) { + case "style": + case "script": + _$jscoverage['plugins/defaultfilter.js'][25]++; + node.setAttr({cdata_tag: node.tagName, cdata_data: encodeURIComponent((node.innerText() || ""))}); + _$jscoverage['plugins/defaultfilter.js'][29]++; + node.tagName = "div"; + _$jscoverage['plugins/defaultfilter.js'][30]++; + node.removeChild(node.firstChild()); + _$jscoverage['plugins/defaultfilter.js'][31]++; + break; + case "a": + _$jscoverage['plugins/defaultfilter.js'][33]++; + if ((val = node.getAttr("href"))) { + _$jscoverage['plugins/defaultfilter.js'][34]++; + node.setAttr("_href", val); + } + _$jscoverage['plugins/defaultfilter.js'][36]++; + break; + case "img": + _$jscoverage['plugins/defaultfilter.js'][39]++; + if ((val = node.getAttr("src"))) { + _$jscoverage['plugins/defaultfilter.js'][40]++; + if (/^data:/.test(val)) { + _$jscoverage['plugins/defaultfilter.js'][41]++; + node.parentNode.removeChild(node); + _$jscoverage['plugins/defaultfilter.js'][42]++; + break; + } + } + _$jscoverage['plugins/defaultfilter.js'][45]++; + node.setAttr("_src", node.getAttr("src")); + _$jscoverage['plugins/defaultfilter.js'][46]++; + break; + case "span": + _$jscoverage['plugins/defaultfilter.js'][48]++; + if ((browser.webkit && (val = node.getStyle("white-space")))) { + _$jscoverage['plugins/defaultfilter.js'][49]++; + if (/nowrap|normal/.test(val)) { + _$jscoverage['plugins/defaultfilter.js'][50]++; + node.setStyle("white-space", ""); + _$jscoverage['plugins/defaultfilter.js'][51]++; + if ((me.options.autoClearEmptyNode && utils.isEmptyObject(node.attrs))) { + _$jscoverage['plugins/defaultfilter.js'][52]++; + node.parentNode.removeChild(node, true); + } + } + } + _$jscoverage['plugins/defaultfilter.js'][56]++; + break; + case "p": + _$jscoverage['plugins/defaultfilter.js'][58]++; + if ((val = node.getAttr("align"))) { + _$jscoverage['plugins/defaultfilter.js'][59]++; + node.setAttr("align"); + _$jscoverage['plugins/defaultfilter.js'][60]++; + node.setStyle("text-align", val); + } + _$jscoverage['plugins/defaultfilter.js'][69]++; + if ((! node.firstChild())) { + _$jscoverage['plugins/defaultfilter.js'][70]++; + node.innerHTML((browser.ie? " ": "
    ")); + } + _$jscoverage['plugins/defaultfilter.js'][72]++; + break; + case "div": + _$jscoverage['plugins/defaultfilter.js'][74]++; + if (node.getAttr("cdata_tag")) { + _$jscoverage['plugins/defaultfilter.js'][75]++; + break; + } + _$jscoverage['plugins/defaultfilter.js'][78]++; + val = node.getAttr("class"); + _$jscoverage['plugins/defaultfilter.js'][79]++; + if ((val && /^line number\d+/.test(val))) { + _$jscoverage['plugins/defaultfilter.js'][80]++; + break; + } + _$jscoverage['plugins/defaultfilter.js'][82]++; + if ((! allowDivTransToP)) { + _$jscoverage['plugins/defaultfilter.js'][83]++; + break; + } + _$jscoverage['plugins/defaultfilter.js'][85]++; + var tmpNode, p = UE.uNode.createElement("p"); + _$jscoverage['plugins/defaultfilter.js'][86]++; + while ((tmpNode = node.firstChild())) { + _$jscoverage['plugins/defaultfilter.js'][87]++; + if (((tmpNode.type == "text") || (! UE.dom.dtd.$block[tmpNode.tagName]))) { + _$jscoverage['plugins/defaultfilter.js'][88]++; + p.appendChild(tmpNode); + } + else { + _$jscoverage['plugins/defaultfilter.js'][90]++; + if (p.firstChild()) { + _$jscoverage['plugins/defaultfilter.js'][91]++; + node.parentNode.insertBefore(p, node); + _$jscoverage['plugins/defaultfilter.js'][92]++; + p = UE.uNode.createElement("p"); + } + else { + _$jscoverage['plugins/defaultfilter.js'][94]++; + node.parentNode.insertBefore(tmpNode, node); + } + } +} + _$jscoverage['plugins/defaultfilter.js'][98]++; + if (p.firstChild()) { + _$jscoverage['plugins/defaultfilter.js'][99]++; + node.parentNode.insertBefore(p, node); + } + _$jscoverage['plugins/defaultfilter.js'][101]++; + node.parentNode.removeChild(node); + _$jscoverage['plugins/defaultfilter.js'][102]++; + break; + case "dl": + _$jscoverage['plugins/defaultfilter.js'][104]++; + node.tagName = "ul"; + _$jscoverage['plugins/defaultfilter.js'][105]++; + break; + case "dt": + case "dd": + _$jscoverage['plugins/defaultfilter.js'][108]++; + node.tagName = "li"; + _$jscoverage['plugins/defaultfilter.js'][109]++; + break; + case "li": + _$jscoverage['plugins/defaultfilter.js'][111]++; + var className = node.getAttr("class"); + _$jscoverage['plugins/defaultfilter.js'][112]++; + if (((! className) || (! /list\-/.test(className)))) { + _$jscoverage['plugins/defaultfilter.js'][113]++; + node.setAttr(); + } + _$jscoverage['plugins/defaultfilter.js'][115]++; + var tmpNodes = node.getNodesByTagName("ol ul"); + _$jscoverage['plugins/defaultfilter.js'][116]++; + UE.utils.each(tmpNodes, (function (n) { + _$jscoverage['plugins/defaultfilter.js'][117]++; + node.parentNode.insertAfter(n, node); +})); + _$jscoverage['plugins/defaultfilter.js'][119]++; + break; + case "td": + case "th": + case "caption": + _$jscoverage['plugins/defaultfilter.js'][123]++; + if (((! node.children) || (! node.children.length))) { + _$jscoverage['plugins/defaultfilter.js'][125]++; + node.appendChild((browser.ie? UE.uNode.createText(" "): UE.uNode.createElement("br"))); + } + } + } + _$jscoverage['plugins/defaultfilter.js'][130]++; + if ((node.type == "comment")) { + _$jscoverage['plugins/defaultfilter.js'][131]++; + node.parentNode.removeChild(node); + } +})); +})); + _$jscoverage['plugins/defaultfilter.js'][138]++; + me.addOutputRule((function (root) { + _$jscoverage['plugins/defaultfilter.js'][140]++; + var val; + _$jscoverage['plugins/defaultfilter.js'][141]++; + root.traversal((function (node) { + _$jscoverage['plugins/defaultfilter.js'][142]++; + if ((node.type == "element")) { + _$jscoverage['plugins/defaultfilter.js'][144]++; + if ((me.options.autoClearEmptyNode && dtd.$inline[node.tagName] && (! dtd.$empty[node.tagName]) && ((! node.attrs) || utils.isEmptyObject(node.attrs)))) { + _$jscoverage['plugins/defaultfilter.js'][146]++; + if ((! node.firstChild())) { + _$jscoverage['plugins/defaultfilter.js'][146]++; + node.parentNode.removeChild(node); + } + else { + _$jscoverage['plugins/defaultfilter.js'][147]++; + if (((node.tagName == "span") && ((! node.attrs) || utils.isEmptyObject(node.attrs)))) { + _$jscoverage['plugins/defaultfilter.js'][148]++; + node.parentNode.removeChild(node, true); + } + } + _$jscoverage['plugins/defaultfilter.js'][150]++; + return; + } + _$jscoverage['plugins/defaultfilter.js'][152]++; + switch (node.tagName) { + case "div": + _$jscoverage['plugins/defaultfilter.js'][154]++; + if ((val = node.getAttr("cdata_tag"))) { + _$jscoverage['plugins/defaultfilter.js'][155]++; + node.tagName = val; + _$jscoverage['plugins/defaultfilter.js'][156]++; + node.appendChild(UE.uNode.createText(node.getAttr("cdata_data"))); + _$jscoverage['plugins/defaultfilter.js'][157]++; + node.setAttr({cdata_tag: "", cdata_data: ""}); + } + _$jscoverage['plugins/defaultfilter.js'][159]++; + break; + case "a": + _$jscoverage['plugins/defaultfilter.js'][161]++; + if ((val = node.getAttr("_href"))) { + _$jscoverage['plugins/defaultfilter.js'][162]++; + node.setAttr({"href": val, "_href": ""}); + } + _$jscoverage['plugins/defaultfilter.js'][167]++; + break; + case "img": + _$jscoverage['plugins/defaultfilter.js'][169]++; + if ((val = node.getAttr("_src"))) { + _$jscoverage['plugins/defaultfilter.js'][170]++; + node.setAttr({"src": node.getAttr("_src"), "_src": ""}); + } + } + } +})); +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/directionality.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/directionality.js new file mode 100644 index 000000000..8accd52cb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/directionality.js @@ -0,0 +1,199 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/directionality.js']) { + _$jscoverage['plugins/directionality.js'] = []; + _$jscoverage['plugins/directionality.js'][7] = 0; + _$jscoverage['plugins/directionality.js'][8] = 0; + _$jscoverage['plugins/directionality.js'][21] = 0; + _$jscoverage['plugins/directionality.js'][26] = 0; + _$jscoverage['plugins/directionality.js'][28] = 0; + _$jscoverage['plugins/directionality.js'][33] = 0; + _$jscoverage['plugins/directionality.js'][34] = 0; + _$jscoverage['plugins/directionality.js'][35] = 0; + _$jscoverage['plugins/directionality.js'][37] = 0; + _$jscoverage['plugins/directionality.js'][38] = 0; + _$jscoverage['plugins/directionality.js'][39] = 0; + _$jscoverage['plugins/directionality.js'][43] = 0; + _$jscoverage['plugins/directionality.js'][44] = 0; + _$jscoverage['plugins/directionality.js'][45] = 0; + _$jscoverage['plugins/directionality.js'][46] = 0; + _$jscoverage['plugins/directionality.js'][47] = 0; + _$jscoverage['plugins/directionality.js'][48] = 0; + _$jscoverage['plugins/directionality.js'][49] = 0; + _$jscoverage['plugins/directionality.js'][52] = 0; + _$jscoverage['plugins/directionality.js'][53] = 0; + _$jscoverage['plugins/directionality.js'][54] = 0; + _$jscoverage['plugins/directionality.js'][56] = 0; + _$jscoverage['plugins/directionality.js'][57] = 0; + _$jscoverage['plugins/directionality.js'][60] = 0; + _$jscoverage['plugins/directionality.js'][61] = 0; + _$jscoverage['plugins/directionality.js'][62] = 0; + _$jscoverage['plugins/directionality.js'][63] = 0; + _$jscoverage['plugins/directionality.js'][64] = 0; + _$jscoverage['plugins/directionality.js'][65] = 0; + _$jscoverage['plugins/directionality.js'][68] = 0; + _$jscoverage['plugins/directionality.js'][70] = 0; + _$jscoverage['plugins/directionality.js'][73] = 0; + _$jscoverage['plugins/directionality.js'][99] = 0; + _$jscoverage['plugins/directionality.js'][101] = 0; + _$jscoverage['plugins/directionality.js'][103] = 0; + _$jscoverage['plugins/directionality.js'][104] = 0; + _$jscoverage['plugins/directionality.js'][105] = 0; + _$jscoverage['plugins/directionality.js'][107] = 0; + _$jscoverage['plugins/directionality.js'][108] = 0; + _$jscoverage['plugins/directionality.js'][109] = 0; + _$jscoverage['plugins/directionality.js'][110] = 0; + _$jscoverage['plugins/directionality.js'][113] = 0; + _$jscoverage['plugins/directionality.js'][114] = 0; + _$jscoverage['plugins/directionality.js'][117] = 0; + _$jscoverage['plugins/directionality.js'][118] = 0; +} +_$jscoverage['plugins/directionality.js'].source = ["/**"," * 设置文字输入的方向的插件"," * @file"," * @since 1.2.6.1"," */","","(function() {"," var block = domUtils.isBlockElm ,"," getObj = function(editor){","// var startNode = editor.selection.getStart(),","// parents;","// if ( startNode ) {","// //查找所有的是block的父亲节点","// parents = domUtils.findParents( startNode, true, block, true );","// for ( var i = 0,ci; ci = parents[i++]; ) {","// if ( ci.getAttribute( 'dir' ) ) {","// return ci;","// }","// }","// }"," return domUtils.filterNodeList(editor.selection.getStartElementPath(),function(n){return n.getAttribute('dir')});",""," },"," doDirectionality = function(range,editor,forward){"," "," var bookmark,"," filterFn = function( node ) {"," return node.nodeType == 1 ? !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace(node);"," },",""," obj = getObj( editor );",""," if ( obj && range.collapsed ) {"," obj.setAttribute( 'dir', forward );"," return range;"," }"," bookmark = range.createBookmark();"," range.enlarge( true );"," var bookmark2 = range.createBookmark(),"," current = domUtils.getNextDomNode( bookmark2.start, false, filterFn ),"," tmpRange = range.cloneRange(),"," tmpNode;"," while ( current && !(domUtils.getPosition( current, bookmark2.end ) & domUtils.POSITION_FOLLOWING) ) {"," if ( current.nodeType == 3 || !block( current ) ) {"," tmpRange.setStartBefore( current );"," while ( current && current !== bookmark2.end && !block( current ) ) {"," tmpNode = current;"," current = domUtils.getNextDomNode( current, false, null, function( node ) {"," return !block( node );"," } );"," }"," tmpRange.setEndAfter( tmpNode );"," var common = tmpRange.getCommonAncestor();"," if ( !domUtils.isBody( common ) && block( common ) ) {"," //遍历到了block节点"," common.setAttribute( 'dir', forward );"," current = common;"," } else {"," //没有遍历到,添加一个block节点"," var p = range.document.createElement( 'p' );"," p.setAttribute( 'dir', forward );"," var frag = tmpRange.extractContents();"," p.appendChild( frag );"," tmpRange.insertNode( p );"," current = p;"," }",""," current = domUtils.getNextDomNode( current, false, filterFn );"," } else {"," current = domUtils.getNextDomNode( current, true, filterFn );"," }"," }"," return range.moveToBookmark( bookmark2 ).moveToBookmark( bookmark );"," };",""," /**"," * 设置文字的方向,可设置从左向右输入,或者从右向左输入,操作对当前段作用"," * @command directionality"," * @method execCommand"," * @param { String } cmdName 命令字符串"," * @param { String } forward 传入'ltr'表示从左向右输入,传入'rtl'表示从右向左输入"," * @example"," * ```javascript"," * editor.execCommand( 'directionality', 'ltr');"," * ```"," */",""," /**"," * 查询当前段落的文字输入方向"," * @command directionality"," * @method queryCommandValue"," * @param { String } cmdName 命令字符串"," * @return { String } 返回'ltr'表示从左向右输入,返回'rtl'表示从右向左输入"," * @example"," * ```javascript"," * editor.queryCommandValue( 'directionality');"," * ```"," */"," UE.commands['directionality'] = {"," execCommand : function( cmdName,forward ) {"," var range = this.selection.getRange();"," //闭合时单独处理"," if(range.collapsed){"," var txt = this.document.createTextNode('d');"," range.insertNode(txt);"," }"," doDirectionality(range,this,forward);"," if(txt){"," range.setStartBefore(txt).collapse(true);"," domUtils.remove(txt);"," }",""," range.select();"," return true;"," },"," queryCommandValue : function() {"," var node = getObj(this);"," return node ? node.getAttribute('dir') : 'ltr';"," }"," };","})();",""]; +_$jscoverage['plugins/directionality.js'][7]++; +(function () { + _$jscoverage['plugins/directionality.js'][8]++; + var block = domUtils.isBlockElm, getObj = (function (editor) { + _$jscoverage['plugins/directionality.js'][21]++; + return domUtils.filterNodeList(editor.selection.getStartElementPath(), (function (n) { + _$jscoverage['plugins/directionality.js'][21]++; + return n.getAttribute("dir"); +})); +}), doDirectionality = (function (range, editor, forward) { + _$jscoverage['plugins/directionality.js'][26]++; + var bookmark, filterFn = (function (node) { + _$jscoverage['plugins/directionality.js'][28]++; + return ((node.nodeType == 1)? (! domUtils.isBookmarkNode(node)): (! domUtils.isWhitespace(node))); +}), obj = getObj(editor); + _$jscoverage['plugins/directionality.js'][33]++; + if ((obj && range.collapsed)) { + _$jscoverage['plugins/directionality.js'][34]++; + obj.setAttribute("dir", forward); + _$jscoverage['plugins/directionality.js'][35]++; + return range; + } + _$jscoverage['plugins/directionality.js'][37]++; + bookmark = range.createBookmark(); + _$jscoverage['plugins/directionality.js'][38]++; + range.enlarge(true); + _$jscoverage['plugins/directionality.js'][39]++; + var bookmark2 = range.createBookmark(), current = domUtils.getNextDomNode(bookmark2.start, false, filterFn), tmpRange = range.cloneRange(), tmpNode; + _$jscoverage['plugins/directionality.js'][43]++; + while ((current && (! (domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)))) { + _$jscoverage['plugins/directionality.js'][44]++; + if (((current.nodeType == 3) || (! block(current)))) { + _$jscoverage['plugins/directionality.js'][45]++; + tmpRange.setStartBefore(current); + _$jscoverage['plugins/directionality.js'][46]++; + while ((current && (current !== bookmark2.end) && (! block(current)))) { + _$jscoverage['plugins/directionality.js'][47]++; + tmpNode = current; + _$jscoverage['plugins/directionality.js'][48]++; + current = domUtils.getNextDomNode(current, false, null, (function (node) { + _$jscoverage['plugins/directionality.js'][49]++; + return (! block(node)); +})); +} + _$jscoverage['plugins/directionality.js'][52]++; + tmpRange.setEndAfter(tmpNode); + _$jscoverage['plugins/directionality.js'][53]++; + var common = tmpRange.getCommonAncestor(); + _$jscoverage['plugins/directionality.js'][54]++; + if (((! domUtils.isBody(common)) && block(common))) { + _$jscoverage['plugins/directionality.js'][56]++; + common.setAttribute("dir", forward); + _$jscoverage['plugins/directionality.js'][57]++; + current = common; + } + else { + _$jscoverage['plugins/directionality.js'][60]++; + var p = range.document.createElement("p"); + _$jscoverage['plugins/directionality.js'][61]++; + p.setAttribute("dir", forward); + _$jscoverage['plugins/directionality.js'][62]++; + var frag = tmpRange.extractContents(); + _$jscoverage['plugins/directionality.js'][63]++; + p.appendChild(frag); + _$jscoverage['plugins/directionality.js'][64]++; + tmpRange.insertNode(p); + _$jscoverage['plugins/directionality.js'][65]++; + current = p; + } + _$jscoverage['plugins/directionality.js'][68]++; + current = domUtils.getNextDomNode(current, false, filterFn); + } + else { + _$jscoverage['plugins/directionality.js'][70]++; + current = domUtils.getNextDomNode(current, true, filterFn); + } +} + _$jscoverage['plugins/directionality.js'][73]++; + return range.moveToBookmark(bookmark2).moveToBookmark(bookmark); +}); + _$jscoverage['plugins/directionality.js'][99]++; + UE.commands.directionality = {execCommand: (function (cmdName, forward) { + _$jscoverage['plugins/directionality.js'][101]++; + var range = this.selection.getRange(); + _$jscoverage['plugins/directionality.js'][103]++; + if (range.collapsed) { + _$jscoverage['plugins/directionality.js'][104]++; + var txt = this.document.createTextNode("d"); + _$jscoverage['plugins/directionality.js'][105]++; + range.insertNode(txt); + } + _$jscoverage['plugins/directionality.js'][107]++; + doDirectionality(range, this, forward); + _$jscoverage['plugins/directionality.js'][108]++; + if (txt) { + _$jscoverage['plugins/directionality.js'][109]++; + range.setStartBefore(txt).collapse(true); + _$jscoverage['plugins/directionality.js'][110]++; + domUtils.remove(txt); + } + _$jscoverage['plugins/directionality.js'][113]++; + range.select(); + _$jscoverage['plugins/directionality.js'][114]++; + return true; +}), queryCommandValue: (function () { + _$jscoverage['plugins/directionality.js'][117]++; + var node = getObj(this); + _$jscoverage['plugins/directionality.js'][118]++; + return (node? node.getAttribute("dir"): "ltr"); +})}; +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/dragdrop.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/dragdrop.js new file mode 100644 index 000000000..12afaabad --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/dragdrop.js @@ -0,0 +1,158 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/dragdrop.js']) { + _$jscoverage['plugins/dragdrop.js'] = []; + _$jscoverage['plugins/dragdrop.js'][1] = 0; + _$jscoverage['plugins/dragdrop.js'][3] = 0; + _$jscoverage['plugins/dragdrop.js'][4] = 0; + _$jscoverage['plugins/dragdrop.js'][5] = 0; + _$jscoverage['plugins/dragdrop.js'][6] = 0; + _$jscoverage['plugins/dragdrop.js'][7] = 0; + _$jscoverage['plugins/dragdrop.js'][9] = 0; + _$jscoverage['plugins/dragdrop.js'][11] = 0; + _$jscoverage['plugins/dragdrop.js'][12] = 0; + _$jscoverage['plugins/dragdrop.js'][13] = 0; + _$jscoverage['plugins/dragdrop.js'][14] = 0; + _$jscoverage['plugins/dragdrop.js'][16] = 0; + _$jscoverage['plugins/dragdrop.js'][21] = 0; + _$jscoverage['plugins/dragdrop.js'][22] = 0; + _$jscoverage['plugins/dragdrop.js'][23] = 0; + _$jscoverage['plugins/dragdrop.js'][24] = 0; + _$jscoverage['plugins/dragdrop.js'][25] = 0; + _$jscoverage['plugins/dragdrop.js'][26] = 0; + _$jscoverage['plugins/dragdrop.js'][27] = 0; + _$jscoverage['plugins/dragdrop.js'][30] = 0; + _$jscoverage['plugins/dragdrop.js'][31] = 0; + _$jscoverage['plugins/dragdrop.js'][33] = 0; + _$jscoverage['plugins/dragdrop.js'][34] = 0; + _$jscoverage['plugins/dragdrop.js'][36] = 0; + _$jscoverage['plugins/dragdrop.js'][37] = 0; + _$jscoverage['plugins/dragdrop.js'][45] = 0; + _$jscoverage['plugins/dragdrop.js'][46] = 0; + _$jscoverage['plugins/dragdrop.js'][47] = 0; + _$jscoverage['plugins/dragdrop.js'][48] = 0; + _$jscoverage['plugins/dragdrop.js'][49] = 0; + _$jscoverage['plugins/dragdrop.js'][50] = 0; + _$jscoverage['plugins/dragdrop.js'][51] = 0; +} +_$jscoverage['plugins/dragdrop.js'].source = ["UE.plugins['dragdrop'] = function (){",""," var me = this;"," me.ready(function(){"," domUtils.on(this.body,'dragend',function(){"," var rng = me.selection.getRange();"," var node = rng.getClosedNode()||me.selection.getStart();",""," if(node && node.tagName == 'IMG'){",""," var pre = node.previousSibling,next;"," while(next = node.nextSibling){"," if(next.nodeType == 1 && next.tagName == 'SPAN' && !next.firstChild){"," domUtils.remove(next)"," }else{"," break;"," }"," }","",""," if((pre && pre.nodeType == 1 && !domUtils.isEmptyBlock(pre) || !pre) && (!next || next && !domUtils.isEmptyBlock(next))){"," if(pre && pre.tagName == 'P' && !domUtils.isEmptyBlock(pre)){"," pre.appendChild(node);"," domUtils.moveChild(next,pre);"," domUtils.remove(next);"," }else if(next && next.tagName == 'P' && !domUtils.isEmptyBlock(next)){"," next.insertBefore(node,next.firstChild);"," }",""," if(pre && pre.tagName == 'P' && domUtils.isEmptyBlock(pre)){"," domUtils.remove(pre)"," }"," if(next && next.tagName == 'P' && domUtils.isEmptyBlock(next)){"," domUtils.remove(next)"," }"," rng.selectNode(node).select();"," me.fireEvent('saveScene');",""," }",""," }",""," })"," });"," me.addListener('keyup', function(type, evt) {"," var keyCode = evt.keyCode || evt.which;"," if (keyCode == 13) {"," var rng = me.selection.getRange(),node;"," if(node = domUtils.findParentByTagName(rng.startContainer,'p',true)){"," if(domUtils.getComputedStyle(node,'text-align') == 'center'){"," domUtils.removeStyle(node,'text-align')"," }"," }"," }"," })","};"]; +_$jscoverage['plugins/dragdrop.js'][1]++; +UE.plugins.dragdrop = (function () { + _$jscoverage['plugins/dragdrop.js'][3]++; + var me = this; + _$jscoverage['plugins/dragdrop.js'][4]++; + me.ready((function () { + _$jscoverage['plugins/dragdrop.js'][5]++; + domUtils.on(this.body, "dragend", (function () { + _$jscoverage['plugins/dragdrop.js'][6]++; + var rng = me.selection.getRange(); + _$jscoverage['plugins/dragdrop.js'][7]++; + var node = (rng.getClosedNode() || me.selection.getStart()); + _$jscoverage['plugins/dragdrop.js'][9]++; + if ((node && (node.tagName == "IMG"))) { + _$jscoverage['plugins/dragdrop.js'][11]++; + var pre = node.previousSibling, next; + _$jscoverage['plugins/dragdrop.js'][12]++; + while ((next = node.nextSibling)) { + _$jscoverage['plugins/dragdrop.js'][13]++; + if (((next.nodeType == 1) && (next.tagName == "SPAN") && (! next.firstChild))) { + _$jscoverage['plugins/dragdrop.js'][14]++; + domUtils.remove(next); + } + else { + _$jscoverage['plugins/dragdrop.js'][16]++; + break; + } +} + _$jscoverage['plugins/dragdrop.js'][21]++; + if ((((pre && (pre.nodeType == 1) && (! domUtils.isEmptyBlock(pre))) || (! pre)) && ((! next) || (next && (! domUtils.isEmptyBlock(next)))))) { + _$jscoverage['plugins/dragdrop.js'][22]++; + if ((pre && (pre.tagName == "P") && (! domUtils.isEmptyBlock(pre)))) { + _$jscoverage['plugins/dragdrop.js'][23]++; + pre.appendChild(node); + _$jscoverage['plugins/dragdrop.js'][24]++; + domUtils.moveChild(next, pre); + _$jscoverage['plugins/dragdrop.js'][25]++; + domUtils.remove(next); + } + else { + _$jscoverage['plugins/dragdrop.js'][26]++; + if ((next && (next.tagName == "P") && (! domUtils.isEmptyBlock(next)))) { + _$jscoverage['plugins/dragdrop.js'][27]++; + next.insertBefore(node, next.firstChild); + } + } + _$jscoverage['plugins/dragdrop.js'][30]++; + if ((pre && (pre.tagName == "P") && domUtils.isEmptyBlock(pre))) { + _$jscoverage['plugins/dragdrop.js'][31]++; + domUtils.remove(pre); + } + _$jscoverage['plugins/dragdrop.js'][33]++; + if ((next && (next.tagName == "P") && domUtils.isEmptyBlock(next))) { + _$jscoverage['plugins/dragdrop.js'][34]++; + domUtils.remove(next); + } + _$jscoverage['plugins/dragdrop.js'][36]++; + rng.selectNode(node).select(); + _$jscoverage['plugins/dragdrop.js'][37]++; + me.fireEvent("saveScene"); + } + } +})); +})); + _$jscoverage['plugins/dragdrop.js'][45]++; + me.addListener("keyup", (function (type, evt) { + _$jscoverage['plugins/dragdrop.js'][46]++; + var keyCode = (evt.keyCode || evt.which); + _$jscoverage['plugins/dragdrop.js'][47]++; + if ((keyCode == 13)) { + _$jscoverage['plugins/dragdrop.js'][48]++; + var rng = me.selection.getRange(), node; + _$jscoverage['plugins/dragdrop.js'][49]++; + if ((node = domUtils.findParentByTagName(rng.startContainer, "p", true))) { + _$jscoverage['plugins/dragdrop.js'][50]++; + if ((domUtils.getComputedStyle(node, "text-align") == "center")) { + _$jscoverage['plugins/dragdrop.js'][51]++; + domUtils.removeStyle(node, "text-align"); + } + } + } +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/elementpath.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/elementpath.js new file mode 100644 index 000000000..4491ea35a --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/elementpath.js @@ -0,0 +1,120 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/elementpath.js']) { + _$jscoverage['plugins/elementpath.js'] = []; + _$jscoverage['plugins/elementpath.js'][6] = 0; + _$jscoverage['plugins/elementpath.js'][7] = 0; + _$jscoverage['plugins/elementpath.js'][10] = 0; + _$jscoverage['plugins/elementpath.js'][11] = 0; + _$jscoverage['plugins/elementpath.js'][12] = 0; + _$jscoverage['plugins/elementpath.js'][14] = 0; + _$jscoverage['plugins/elementpath.js'][16] = 0; + _$jscoverage['plugins/elementpath.js'][17] = 0; + _$jscoverage['plugins/elementpath.js'][19] = 0; + _$jscoverage['plugins/elementpath.js'][20] = 0; + _$jscoverage['plugins/elementpath.js'][24] = 0; + _$jscoverage['plugins/elementpath.js'][26] = 0; + _$jscoverage['plugins/elementpath.js'][27] = 0; + _$jscoverage['plugins/elementpath.js'][28] = 0; + _$jscoverage['plugins/elementpath.js'][29] = 0; + _$jscoverage['plugins/elementpath.js'][31] = 0; + _$jscoverage['plugins/elementpath.js'][32] = 0; + _$jscoverage['plugins/elementpath.js'][33] = 0; + _$jscoverage['plugins/elementpath.js'][35] = 0; + _$jscoverage['plugins/elementpath.js'][36] = 0; + _$jscoverage['plugins/elementpath.js'][37] = 0; + _$jscoverage['plugins/elementpath.js'][38] = 0; + _$jscoverage['plugins/elementpath.js'][41] = 0; +} +_$jscoverage['plugins/elementpath.js'].source = ["/**"," * 选取路径命令"," * @file"," */","","UE.plugins['elementpath'] = function(){"," var currentLevel,"," tagNames,"," me = this;"," me.setOpt('elementPathEnabled',true);"," if(!me.options.elementPathEnabled){"," return;"," }"," me.commands['elementpath'] = {"," execCommand : function( cmdName, level ) {"," debugger;"," var start = tagNames[level],"," range = me.selection.getRange();"," currentLevel = level*1;"," range.selectNode(start).select();"," },"," queryCommandValue : function() {"," //产生一个副本,不能修改原来的startElementPath;"," var parents = [].concat(this.selection.getStartElementPath()).reverse(),"," names = [];"," tagNames = parents;"," for(var i=0,ci;ci=parents[i];i++){"," if(ci.nodeType == 3) {"," continue;"," }"," var name = ci.tagName.toLowerCase();"," if(name == 'img' && ci.getAttribute('anchorname')){"," name = 'anchor';"," }"," names[i] = name;"," if(currentLevel == i){"," currentLevel = -1;"," break;"," }"," }"," return names;"," }"," };","};",""]; +_$jscoverage['plugins/elementpath.js'][6]++; +UE.plugins.elementpath = (function () { + _$jscoverage['plugins/elementpath.js'][7]++; + var currentLevel, tagNames, me = this; + _$jscoverage['plugins/elementpath.js'][10]++; + me.setOpt("elementPathEnabled", true); + _$jscoverage['plugins/elementpath.js'][11]++; + if ((! me.options.elementPathEnabled)) { + _$jscoverage['plugins/elementpath.js'][12]++; + return; + } + _$jscoverage['plugins/elementpath.js'][14]++; + me.commands.elementpath = {execCommand: (function (cmdName, level) { + _$jscoverage['plugins/elementpath.js'][16]++; + debugger; + _$jscoverage['plugins/elementpath.js'][17]++; + var start = tagNames[level], range = me.selection.getRange(); + _$jscoverage['plugins/elementpath.js'][19]++; + currentLevel = (level * 1); + _$jscoverage['plugins/elementpath.js'][20]++; + range.selectNode(start).select(); +}), queryCommandValue: (function () { + _$jscoverage['plugins/elementpath.js'][24]++; + var parents = [].concat(this.selection.getStartElementPath()).reverse(), names = []; + _$jscoverage['plugins/elementpath.js'][26]++; + tagNames = parents; + _$jscoverage['plugins/elementpath.js'][27]++; + for (var i = 0, ci; (ci = parents[i]); (i++)) { + _$jscoverage['plugins/elementpath.js'][28]++; + if ((ci.nodeType == 3)) { + _$jscoverage['plugins/elementpath.js'][29]++; + continue; + } + _$jscoverage['plugins/elementpath.js'][31]++; + var name = ci.tagName.toLowerCase(); + _$jscoverage['plugins/elementpath.js'][32]++; + if (((name == "img") && ci.getAttribute("anchorname"))) { + _$jscoverage['plugins/elementpath.js'][33]++; + name = "anchor"; + } + _$jscoverage['plugins/elementpath.js'][35]++; + names[i] = name; + _$jscoverage['plugins/elementpath.js'][36]++; + if ((currentLevel == i)) { + _$jscoverage['plugins/elementpath.js'][37]++; + currentLevel = -1; + _$jscoverage['plugins/elementpath.js'][38]++; + break; + } +} + _$jscoverage['plugins/elementpath.js'][41]++; + return names; +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/enterkey.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/enterkey.js new file mode 100644 index 000000000..b016991c7 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/enterkey.js @@ -0,0 +1,352 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/enterkey.js']) { + _$jscoverage['plugins/enterkey.js'] = []; + _$jscoverage['plugins/enterkey.js'][10] = 0; + _$jscoverage['plugins/enterkey.js'][11] = 0; + _$jscoverage['plugins/enterkey.js'][14] = 0; + _$jscoverage['plugins/enterkey.js'][16] = 0; + _$jscoverage['plugins/enterkey.js'][17] = 0; + _$jscoverage['plugins/enterkey.js'][18] = 0; + _$jscoverage['plugins/enterkey.js'][23] = 0; + _$jscoverage['plugins/enterkey.js'][25] = 0; + _$jscoverage['plugins/enterkey.js'][26] = 0; + _$jscoverage['plugins/enterkey.js'][27] = 0; + _$jscoverage['plugins/enterkey.js'][28] = 0; + _$jscoverage['plugins/enterkey.js'][29] = 0; + _$jscoverage['plugins/enterkey.js'][30] = 0; + _$jscoverage['plugins/enterkey.js'][34] = 0; + _$jscoverage['plugins/enterkey.js'][35] = 0; + _$jscoverage['plugins/enterkey.js'][36] = 0; + _$jscoverage['plugins/enterkey.js'][37] = 0; + _$jscoverage['plugins/enterkey.js'][38] = 0; + _$jscoverage['plugins/enterkey.js'][39] = 0; + _$jscoverage['plugins/enterkey.js'][40] = 0; + _$jscoverage['plugins/enterkey.js'][41] = 0; + _$jscoverage['plugins/enterkey.js'][43] = 0; + _$jscoverage['plugins/enterkey.js'][44] = 0; + _$jscoverage['plugins/enterkey.js'][45] = 0; + _$jscoverage['plugins/enterkey.js'][46] = 0; + _$jscoverage['plugins/enterkey.js'][48] = 0; + _$jscoverage['plugins/enterkey.js'][53] = 0; + _$jscoverage['plugins/enterkey.js'][54] = 0; + _$jscoverage['plugins/enterkey.js'][58] = 0; + _$jscoverage['plugins/enterkey.js'][60] = 0; + _$jscoverage['plugins/enterkey.js'][65] = 0; + _$jscoverage['plugins/enterkey.js'][66] = 0; + _$jscoverage['plugins/enterkey.js'][67] = 0; + _$jscoverage['plugins/enterkey.js'][68] = 0; + _$jscoverage['plugins/enterkey.js'][69] = 0; + _$jscoverage['plugins/enterkey.js'][70] = 0; + _$jscoverage['plugins/enterkey.js'][72] = 0; + _$jscoverage['plugins/enterkey.js'][73] = 0; + _$jscoverage['plugins/enterkey.js'][76] = 0; + _$jscoverage['plugins/enterkey.js'][78] = 0; + _$jscoverage['plugins/enterkey.js'][80] = 0; + _$jscoverage['plugins/enterkey.js'][84] = 0; + _$jscoverage['plugins/enterkey.js'][85] = 0; + _$jscoverage['plugins/enterkey.js'][86] = 0; + _$jscoverage['plugins/enterkey.js'][89] = 0; + _$jscoverage['plugins/enterkey.js'][92] = 0; + _$jscoverage['plugins/enterkey.js'][94] = 0; + _$jscoverage['plugins/enterkey.js'][98] = 0; + _$jscoverage['plugins/enterkey.js'][100] = 0; + _$jscoverage['plugins/enterkey.js'][102] = 0; + _$jscoverage['plugins/enterkey.js'][103] = 0; + _$jscoverage['plugins/enterkey.js'][104] = 0; + _$jscoverage['plugins/enterkey.js'][105] = 0; + _$jscoverage['plugins/enterkey.js'][110] = 0; + _$jscoverage['plugins/enterkey.js'][111] = 0; + _$jscoverage['plugins/enterkey.js'][117] = 0; + _$jscoverage['plugins/enterkey.js'][119] = 0; + _$jscoverage['plugins/enterkey.js'][120] = 0; + _$jscoverage['plugins/enterkey.js'][121] = 0; + _$jscoverage['plugins/enterkey.js'][122] = 0; + _$jscoverage['plugins/enterkey.js'][123] = 0; + _$jscoverage['plugins/enterkey.js'][124] = 0; + _$jscoverage['plugins/enterkey.js'][125] = 0; + _$jscoverage['plugins/enterkey.js'][126] = 0; + _$jscoverage['plugins/enterkey.js'][127] = 0; + _$jscoverage['plugins/enterkey.js'][129] = 0; + _$jscoverage['plugins/enterkey.js'][131] = 0; + _$jscoverage['plugins/enterkey.js'][132] = 0; + _$jscoverage['plugins/enterkey.js'][133] = 0; + _$jscoverage['plugins/enterkey.js'][134] = 0; + _$jscoverage['plugins/enterkey.js'][135] = 0; + _$jscoverage['plugins/enterkey.js'][136] = 0; + _$jscoverage['plugins/enterkey.js'][138] = 0; + _$jscoverage['plugins/enterkey.js'][140] = 0; + _$jscoverage['plugins/enterkey.js'][142] = 0; + _$jscoverage['plugins/enterkey.js'][143] = 0; + _$jscoverage['plugins/enterkey.js'][144] = 0; + _$jscoverage['plugins/enterkey.js'][147] = 0; + _$jscoverage['plugins/enterkey.js'][152] = 0; + _$jscoverage['plugins/enterkey.js'][153] = 0; + _$jscoverage['plugins/enterkey.js'][158] = 0; + _$jscoverage['plugins/enterkey.js'][159] = 0; + _$jscoverage['plugins/enterkey.js'][160] = 0; + _$jscoverage['plugins/enterkey.js'][161] = 0; + _$jscoverage['plugins/enterkey.js'][162] = 0; + _$jscoverage['plugins/enterkey.js'][163] = 0; + _$jscoverage['plugins/enterkey.js'][165] = 0; + _$jscoverage['plugins/enterkey.js'][167] = 0; +} +_$jscoverage['plugins/enterkey.js'].source = ["///import core","///import plugins/undo.js","///commands 设置回车标签p或br","///commandsName EnterKey","///commandsTitle 设置回车标签p或br","/*"," * @description 处理回车"," * @author zhanyi"," */","UE.plugins['enterkey'] = function() {"," var hTag,"," me = this,"," tag = me.options.enterTag;"," me.addListener('keyup', function(type, evt) {",""," var keyCode = evt.keyCode || evt.which;"," if (keyCode == 13) {"," var range = me.selection.getRange(),"," start = range.startContainer,"," doSave;",""," //修正在h1-h6里边回车后不能嵌套p的问题"," if (!browser.ie) {",""," if (/h\\d/i.test(hTag)) {"," if (browser.gecko) {"," var h = domUtils.findParentByTagName(start, [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6','blockquote','caption','table'], true);"," if (!h) {"," me.document.execCommand('formatBlock', false, '<p>');"," doSave = 1;"," }"," } else {"," //chrome remove div"," if (start.nodeType == 1) {"," var tmp = me.document.createTextNode(''),div;"," range.insertNode(tmp);"," div = domUtils.findParentByTagName(tmp, 'div', true);"," if (div) {"," var p = me.document.createElement('p');"," while (div.firstChild) {"," p.appendChild(div.firstChild);"," }"," div.parentNode.insertBefore(p, div);"," domUtils.remove(div);"," range.setStartBefore(tmp).setCursor();"," doSave = 1;"," }"," domUtils.remove(tmp);",""," }"," }",""," if (me.undoManger && doSave) {"," me.undoManger.save();"," }"," }"," //没有站位符,会出现多行的问题"," browser.opera && range.select();"," }else{"," me.fireEvent('saveScene',true,true)"," }"," }"," });",""," me.addListener('keydown', function(type, evt) {"," var keyCode = evt.keyCode || evt.which;"," if (keyCode == 13) {//回车"," if(me.fireEvent('beforeenterkeydown')){"," domUtils.preventDefault(evt);"," return;"," }"," me.fireEvent('saveScene',true,true);"," hTag = '';","",""," var range = me.selection.getRange();",""," if (!range.collapsed) {"," //跨td不能删"," var start = range.startContainer,"," end = range.endContainer,"," startTd = domUtils.findParentByTagName(start, 'td', true),"," endTd = domUtils.findParentByTagName(end, 'td', true);"," if (startTd && endTd && startTd !== endTd || !startTd && endTd || startTd && !endTd) {"," evt.preventDefault ? evt.preventDefault() : ( evt.returnValue = false);"," return;"," }"," }"," if (tag == 'p') {","",""," if (!browser.ie) {",""," start = domUtils.findParentByTagName(range.startContainer, ['ol','ul','p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6','blockquote','caption'], true);",""," //opera下执行formatblock会在table的场景下有问题,回车在opera原生支持很好,所以暂时在opera去掉调用这个原生的command"," //trace:2431"," if (!start && !browser.opera) {",""," me.document.execCommand('formatBlock', false, '<p>');",""," if (browser.gecko) {"," range = me.selection.getRange();"," start = domUtils.findParentByTagName(range.startContainer, 'p', true);"," start && domUtils.removeDirtyAttr(start);"," }","",""," } else {"," hTag = start.tagName;"," start.tagName.toLowerCase() == 'p' && browser.gecko && domUtils.removeDirtyAttr(start);"," }",""," }",""," } else {"," evt.preventDefault ? evt.preventDefault() : ( evt.returnValue = false);",""," if (!range.collapsed) {"," range.deleteContents();"," start = range.startContainer;"," if (start.nodeType == 1 && (start = start.childNodes[range.startOffset])) {"," while (start.nodeType == 1) {"," if (dtd.$empty[start.tagName]) {"," range.setStartBefore(start).setCursor();"," if (me.undoManger) {"," me.undoManger.save();"," }"," return false;"," }"," if (!start.firstChild) {"," var br = range.document.createElement('br');"," start.appendChild(br);"," range.setStart(start, 0).setCursor();"," if (me.undoManger) {"," me.undoManger.save();"," }"," return false;"," }"," start = start.firstChild;"," }"," if (start === range.startContainer.childNodes[range.startOffset]) {"," br = range.document.createElement('br');"," range.insertNode(br).setCursor();",""," } else {"," range.setStart(start, 0).setCursor();"," }","",""," } else {"," br = range.document.createElement('br');"," range.insertNode(br).setStartAfter(br).setCursor();"," }","",""," } else {"," br = range.document.createElement('br');"," range.insertNode(br);"," var parent = br.parentNode;"," if (parent.lastChild === br) {"," br.parentNode.insertBefore(br.cloneNode(true), br);"," range.setStartBefore(br);"," } else {"," range.setStartAfter(br);"," }"," range.setCursor();",""," }",""," }",""," }"," });","};"]; +_$jscoverage['plugins/enterkey.js'][10]++; +UE.plugins.enterkey = (function () { + _$jscoverage['plugins/enterkey.js'][11]++; + var hTag, me = this, tag = me.options.enterTag; + _$jscoverage['plugins/enterkey.js'][14]++; + me.addListener("keyup", (function (type, evt) { + _$jscoverage['plugins/enterkey.js'][16]++; + var keyCode = (evt.keyCode || evt.which); + _$jscoverage['plugins/enterkey.js'][17]++; + if ((keyCode == 13)) { + _$jscoverage['plugins/enterkey.js'][18]++; + var range = me.selection.getRange(), start = range.startContainer, doSave; + _$jscoverage['plugins/enterkey.js'][23]++; + if ((! browser.ie)) { + _$jscoverage['plugins/enterkey.js'][25]++; + if (/h\d/i.test(hTag)) { + _$jscoverage['plugins/enterkey.js'][26]++; + if (browser.gecko) { + _$jscoverage['plugins/enterkey.js'][27]++; + var h = domUtils.findParentByTagName(start, ["h1", "h2", "h3", "h4", "h5", "h6", "blockquote", "caption", "table"], true); + _$jscoverage['plugins/enterkey.js'][28]++; + if ((! h)) { + _$jscoverage['plugins/enterkey.js'][29]++; + me.document.execCommand("formatBlock", false, "

    "); + _$jscoverage['plugins/enterkey.js'][30]++; + doSave = 1; + } + } + else { + _$jscoverage['plugins/enterkey.js'][34]++; + if ((start.nodeType == 1)) { + _$jscoverage['plugins/enterkey.js'][35]++; + var tmp = me.document.createTextNode(""), div; + _$jscoverage['plugins/enterkey.js'][36]++; + range.insertNode(tmp); + _$jscoverage['plugins/enterkey.js'][37]++; + div = domUtils.findParentByTagName(tmp, "div", true); + _$jscoverage['plugins/enterkey.js'][38]++; + if (div) { + _$jscoverage['plugins/enterkey.js'][39]++; + var p = me.document.createElement("p"); + _$jscoverage['plugins/enterkey.js'][40]++; + while (div.firstChild) { + _$jscoverage['plugins/enterkey.js'][41]++; + p.appendChild(div.firstChild); +} + _$jscoverage['plugins/enterkey.js'][43]++; + div.parentNode.insertBefore(p, div); + _$jscoverage['plugins/enterkey.js'][44]++; + domUtils.remove(div); + _$jscoverage['plugins/enterkey.js'][45]++; + range.setStartBefore(tmp).setCursor(); + _$jscoverage['plugins/enterkey.js'][46]++; + doSave = 1; + } + _$jscoverage['plugins/enterkey.js'][48]++; + domUtils.remove(tmp); + } + } + _$jscoverage['plugins/enterkey.js'][53]++; + if ((me.undoManger && doSave)) { + _$jscoverage['plugins/enterkey.js'][54]++; + me.undoManger.save(); + } + } + _$jscoverage['plugins/enterkey.js'][58]++; + (browser.opera && range.select()); + } + else { + _$jscoverage['plugins/enterkey.js'][60]++; + me.fireEvent("saveScene", true, true); + } + } +})); + _$jscoverage['plugins/enterkey.js'][65]++; + me.addListener("keydown", (function (type, evt) { + _$jscoverage['plugins/enterkey.js'][66]++; + var keyCode = (evt.keyCode || evt.which); + _$jscoverage['plugins/enterkey.js'][67]++; + if ((keyCode == 13)) { + _$jscoverage['plugins/enterkey.js'][68]++; + if (me.fireEvent("beforeenterkeydown")) { + _$jscoverage['plugins/enterkey.js'][69]++; + domUtils.preventDefault(evt); + _$jscoverage['plugins/enterkey.js'][70]++; + return; + } + _$jscoverage['plugins/enterkey.js'][72]++; + me.fireEvent("saveScene", true, true); + _$jscoverage['plugins/enterkey.js'][73]++; + hTag = ""; + _$jscoverage['plugins/enterkey.js'][76]++; + var range = me.selection.getRange(); + _$jscoverage['plugins/enterkey.js'][78]++; + if ((! range.collapsed)) { + _$jscoverage['plugins/enterkey.js'][80]++; + var start = range.startContainer, end = range.endContainer, startTd = domUtils.findParentByTagName(start, "td", true), endTd = domUtils.findParentByTagName(end, "td", true); + _$jscoverage['plugins/enterkey.js'][84]++; + if (((startTd && endTd && (startTd !== endTd)) || ((! startTd) && endTd) || (startTd && (! endTd)))) { + _$jscoverage['plugins/enterkey.js'][85]++; + (evt.preventDefault? evt.preventDefault(): (evt.returnValue = false)); + _$jscoverage['plugins/enterkey.js'][86]++; + return; + } + } + _$jscoverage['plugins/enterkey.js'][89]++; + if ((tag == "p")) { + _$jscoverage['plugins/enterkey.js'][92]++; + if ((! browser.ie)) { + _$jscoverage['plugins/enterkey.js'][94]++; + start = domUtils.findParentByTagName(range.startContainer, ["ol", "ul", "p", "h1", "h2", "h3", "h4", "h5", "h6", "blockquote", "caption"], true); + _$jscoverage['plugins/enterkey.js'][98]++; + if (((! start) && (! browser.opera))) { + _$jscoverage['plugins/enterkey.js'][100]++; + me.document.execCommand("formatBlock", false, "

    "); + _$jscoverage['plugins/enterkey.js'][102]++; + if (browser.gecko) { + _$jscoverage['plugins/enterkey.js'][103]++; + range = me.selection.getRange(); + _$jscoverage['plugins/enterkey.js'][104]++; + start = domUtils.findParentByTagName(range.startContainer, "p", true); + _$jscoverage['plugins/enterkey.js'][105]++; + (start && domUtils.removeDirtyAttr(start)); + } + } + else { + _$jscoverage['plugins/enterkey.js'][110]++; + hTag = start.tagName; + _$jscoverage['plugins/enterkey.js'][111]++; + ((start.tagName.toLowerCase() == "p") && browser.gecko && domUtils.removeDirtyAttr(start)); + } + } + } + else { + _$jscoverage['plugins/enterkey.js'][117]++; + (evt.preventDefault? evt.preventDefault(): (evt.returnValue = false)); + _$jscoverage['plugins/enterkey.js'][119]++; + if ((! range.collapsed)) { + _$jscoverage['plugins/enterkey.js'][120]++; + range.deleteContents(); + _$jscoverage['plugins/enterkey.js'][121]++; + start = range.startContainer; + _$jscoverage['plugins/enterkey.js'][122]++; + if (((start.nodeType == 1) && (start = start.childNodes[range.startOffset]))) { + _$jscoverage['plugins/enterkey.js'][123]++; + while ((start.nodeType == 1)) { + _$jscoverage['plugins/enterkey.js'][124]++; + if (dtd.$empty[start.tagName]) { + _$jscoverage['plugins/enterkey.js'][125]++; + range.setStartBefore(start).setCursor(); + _$jscoverage['plugins/enterkey.js'][126]++; + if (me.undoManger) { + _$jscoverage['plugins/enterkey.js'][127]++; + me.undoManger.save(); + } + _$jscoverage['plugins/enterkey.js'][129]++; + return false; + } + _$jscoverage['plugins/enterkey.js'][131]++; + if ((! start.firstChild)) { + _$jscoverage['plugins/enterkey.js'][132]++; + var br = range.document.createElement("br"); + _$jscoverage['plugins/enterkey.js'][133]++; + start.appendChild(br); + _$jscoverage['plugins/enterkey.js'][134]++; + range.setStart(start, 0).setCursor(); + _$jscoverage['plugins/enterkey.js'][135]++; + if (me.undoManger) { + _$jscoverage['plugins/enterkey.js'][136]++; + me.undoManger.save(); + } + _$jscoverage['plugins/enterkey.js'][138]++; + return false; + } + _$jscoverage['plugins/enterkey.js'][140]++; + start = start.firstChild; +} + _$jscoverage['plugins/enterkey.js'][142]++; + if ((start === range.startContainer.childNodes[range.startOffset])) { + _$jscoverage['plugins/enterkey.js'][143]++; + br = range.document.createElement("br"); + _$jscoverage['plugins/enterkey.js'][144]++; + range.insertNode(br).setCursor(); + } + else { + _$jscoverage['plugins/enterkey.js'][147]++; + range.setStart(start, 0).setCursor(); + } + } + else { + _$jscoverage['plugins/enterkey.js'][152]++; + br = range.document.createElement("br"); + _$jscoverage['plugins/enterkey.js'][153]++; + range.insertNode(br).setStartAfter(br).setCursor(); + } + } + else { + _$jscoverage['plugins/enterkey.js'][158]++; + br = range.document.createElement("br"); + _$jscoverage['plugins/enterkey.js'][159]++; + range.insertNode(br); + _$jscoverage['plugins/enterkey.js'][160]++; + var parent = br.parentNode; + _$jscoverage['plugins/enterkey.js'][161]++; + if ((parent.lastChild === br)) { + _$jscoverage['plugins/enterkey.js'][162]++; + br.parentNode.insertBefore(br.cloneNode(true), br); + _$jscoverage['plugins/enterkey.js'][163]++; + range.setStartBefore(br); + } + else { + _$jscoverage['plugins/enterkey.js'][165]++; + range.setStartAfter(br); + } + _$jscoverage['plugins/enterkey.js'][167]++; + range.setCursor(); + } + } + } +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/fiximgclick.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/fiximgclick.js new file mode 100644 index 000000000..b32a5f225 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/fiximgclick.js @@ -0,0 +1,68 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/fiximgclick.js']) { + _$jscoverage['plugins/fiximgclick.js'] = []; + _$jscoverage['plugins/fiximgclick.js'][7] = 0; + _$jscoverage['plugins/fiximgclick.js'][8] = 0; + _$jscoverage['plugins/fiximgclick.js'][9] = 0; + _$jscoverage['plugins/fiximgclick.js'][10] = 0; + _$jscoverage['plugins/fiximgclick.js'][11] = 0; + _$jscoverage['plugins/fiximgclick.js'][12] = 0; + _$jscoverage['plugins/fiximgclick.js'][13] = 0; +} +_$jscoverage['plugins/fiximgclick.js'].source = ["///import core","///commands 修复chrome下图片不能点击的问题","///commandsName FixImgClick","///commandsTitle 修复chrome下图片不能点击的问题","//修复chrome下图片不能点击的问题","//todo 可以改大小","UE.plugins['fiximgclick'] = function() {"," var me = this;"," if ( browser.webkit ) {"," me.addListener( 'click', function( type, e ) {"," if ( e.target.tagName == 'IMG' ) {"," var range = new dom.Range( me.document );"," range.selectNode( e.target ).select();",""," }"," } );"," }","};"]; +_$jscoverage['plugins/fiximgclick.js'][7]++; +UE.plugins.fiximgclick = (function () { + _$jscoverage['plugins/fiximgclick.js'][8]++; + var me = this; + _$jscoverage['plugins/fiximgclick.js'][9]++; + if (browser.webkit) { + _$jscoverage['plugins/fiximgclick.js'][10]++; + me.addListener("click", (function (type, e) { + _$jscoverage['plugins/fiximgclick.js'][11]++; + if ((e.target.tagName == "IMG")) { + _$jscoverage['plugins/fiximgclick.js'][12]++; + var range = new (dom.Range)(me.document); + _$jscoverage['plugins/fiximgclick.js'][13]++; + range.selectNode(e.target).select(); + } +})); + } +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/font.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/font.js new file mode 100644 index 000000000..7cfdc6709 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/font.js @@ -0,0 +1,646 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/font.js']) { + _$jscoverage['plugins/font.js'] = []; + _$jscoverage['plugins/font.js'][197] = 0; + _$jscoverage['plugins/font.js'][198] = 0; + _$jscoverage['plugins/font.js'][216] = 0; + _$jscoverage['plugins/font.js'][233] = 0; + _$jscoverage['plugins/font.js'][234] = 0; + _$jscoverage['plugins/font.js'][235] = 0; + _$jscoverage['plugins/font.js'][236] = 0; + _$jscoverage['plugins/font.js'][237] = 0; + _$jscoverage['plugins/font.js'][239] = 0; + _$jscoverage['plugins/font.js'][240] = 0; + _$jscoverage['plugins/font.js'][241] = 0; + _$jscoverage['plugins/font.js'][244] = 0; + _$jscoverage['plugins/font.js'][249] = 0; + _$jscoverage['plugins/font.js'][250] = 0; + _$jscoverage['plugins/font.js'][251] = 0; + _$jscoverage['plugins/font.js'][252] = 0; + _$jscoverage['plugins/font.js'][253] = 0; + _$jscoverage['plugins/font.js'][254] = 0; + _$jscoverage['plugins/font.js'][255] = 0; + _$jscoverage['plugins/font.js'][256] = 0; + _$jscoverage['plugins/font.js'][257] = 0; + _$jscoverage['plugins/font.js'][258] = 0; + _$jscoverage['plugins/font.js'][259] = 0; + _$jscoverage['plugins/font.js'][261] = 0; + _$jscoverage['plugins/font.js'][262] = 0; + _$jscoverage['plugins/font.js'][263] = 0; + _$jscoverage['plugins/font.js'][266] = 0; + _$jscoverage['plugins/font.js'][272] = 0; + _$jscoverage['plugins/font.js'][273] = 0; + _$jscoverage['plugins/font.js'][275] = 0; + _$jscoverage['plugins/font.js'][276] = 0; + _$jscoverage['plugins/font.js'][277] = 0; + _$jscoverage['plugins/font.js'][278] = 0; + _$jscoverage['plugins/font.js'][281] = 0; + _$jscoverage['plugins/font.js'][283] = 0; + _$jscoverage['plugins/font.js'][284] = 0; + _$jscoverage['plugins/font.js'][285] = 0; + _$jscoverage['plugins/font.js'][286] = 0; + _$jscoverage['plugins/font.js'][287] = 0; + _$jscoverage['plugins/font.js'][289] = 0; + _$jscoverage['plugins/font.js'][291] = 0; + _$jscoverage['plugins/font.js'][293] = 0; + _$jscoverage['plugins/font.js'][294] = 0; + _$jscoverage['plugins/font.js'][296] = 0; + _$jscoverage['plugins/font.js'][297] = 0; + _$jscoverage['plugins/font.js'][298] = 0; + _$jscoverage['plugins/font.js'][299] = 0; + _$jscoverage['plugins/font.js'][300] = 0; + _$jscoverage['plugins/font.js'][301] = 0; + _$jscoverage['plugins/font.js'][302] = 0; + _$jscoverage['plugins/font.js'][304] = 0; + _$jscoverage['plugins/font.js'][305] = 0; + _$jscoverage['plugins/font.js'][306] = 0; + _$jscoverage['plugins/font.js'][308] = 0; + _$jscoverage['plugins/font.js'][309] = 0; + _$jscoverage['plugins/font.js'][310] = 0; + _$jscoverage['plugins/font.js'][315] = 0; + _$jscoverage['plugins/font.js'][316] = 0; + _$jscoverage['plugins/font.js'][318] = 0; + _$jscoverage['plugins/font.js'][319] = 0; + _$jscoverage['plugins/font.js'][320] = 0; + _$jscoverage['plugins/font.js'][325] = 0; + _$jscoverage['plugins/font.js'][326] = 0; + _$jscoverage['plugins/font.js'][329] = 0; + _$jscoverage['plugins/font.js'][330] = 0; + _$jscoverage['plugins/font.js'][331] = 0; + _$jscoverage['plugins/font.js'][332] = 0; + _$jscoverage['plugins/font.js'][333] = 0; + _$jscoverage['plugins/font.js'][334] = 0; + _$jscoverage['plugins/font.js'][336] = 0; + _$jscoverage['plugins/font.js'][337] = 0; + _$jscoverage['plugins/font.js'][339] = 0; + _$jscoverage['plugins/font.js'][340] = 0; + _$jscoverage['plugins/font.js'][342] = 0; + _$jscoverage['plugins/font.js'][343] = 0; + _$jscoverage['plugins/font.js'][345] = 0; + _$jscoverage['plugins/font.js'][348] = 0; + _$jscoverage['plugins/font.js'][352] = 0; + _$jscoverage['plugins/font.js'][353] = 0; + _$jscoverage['plugins/font.js'][357] = 0; + _$jscoverage['plugins/font.js'][409] = 0; + _$jscoverage['plugins/font.js'][410] = 0; + _$jscoverage['plugins/font.js'][411] = 0; + _$jscoverage['plugins/font.js'][413] = 0; + _$jscoverage['plugins/font.js'][416] = 0; + _$jscoverage['plugins/font.js'][420] = 0; + _$jscoverage['plugins/font.js'][422] = 0; + _$jscoverage['plugins/font.js'][423] = 0; + _$jscoverage['plugins/font.js'][424] = 0; + _$jscoverage['plugins/font.js'][427] = 0; + _$jscoverage['plugins/font.js'][428] = 0; + _$jscoverage['plugins/font.js'][429] = 0; + _$jscoverage['plugins/font.js'][430] = 0; + _$jscoverage['plugins/font.js'][432] = 0; + _$jscoverage['plugins/font.js'][433] = 0; + _$jscoverage['plugins/font.js'][435] = 0; + _$jscoverage['plugins/font.js'][436] = 0; + _$jscoverage['plugins/font.js'][437] = 0; + _$jscoverage['plugins/font.js'][439] = 0; + _$jscoverage['plugins/font.js'][441] = 0; + _$jscoverage['plugins/font.js'][442] = 0; + _$jscoverage['plugins/font.js'][443] = 0; + _$jscoverage['plugins/font.js'][446] = 0; + _$jscoverage['plugins/font.js'][447] = 0; + _$jscoverage['plugins/font.js'][448] = 0; + _$jscoverage['plugins/font.js'][450] = 0; + _$jscoverage['plugins/font.js'][451] = 0; + _$jscoverage['plugins/font.js'][452] = 0; + _$jscoverage['plugins/font.js'][453] = 0; + _$jscoverage['plugins/font.js'][455] = 0; + _$jscoverage['plugins/font.js'][456] = 0; + _$jscoverage['plugins/font.js'][459] = 0; + _$jscoverage['plugins/font.js'][460] = 0; + _$jscoverage['plugins/font.js'][464] = 0; + _$jscoverage['plugins/font.js'][465] = 0; + _$jscoverage['plugins/font.js'][466] = 0; + _$jscoverage['plugins/font.js'][468] = 0; + _$jscoverage['plugins/font.js'][470] = 0; + _$jscoverage['plugins/font.js'][471] = 0; + _$jscoverage['plugins/font.js'][472] = 0; + _$jscoverage['plugins/font.js'][473] = 0; + _$jscoverage['plugins/font.js'][475] = 0; + _$jscoverage['plugins/font.js'][478] = 0; + _$jscoverage['plugins/font.js'][481] = 0; + _$jscoverage['plugins/font.js'][483] = 0; + _$jscoverage['plugins/font.js'][484] = 0; + _$jscoverage['plugins/font.js'][485] = 0; + _$jscoverage['plugins/font.js'][486] = 0; + _$jscoverage['plugins/font.js'][488] = 0; + _$jscoverage['plugins/font.js'][490] = 0; + _$jscoverage['plugins/font.js'][495] = 0; + _$jscoverage['plugins/font.js'][496] = 0; + _$jscoverage['plugins/font.js'][497] = 0; + _$jscoverage['plugins/font.js'][498] = 0; + _$jscoverage['plugins/font.js'][499] = 0; + _$jscoverage['plugins/font.js'][502] = 0; + _$jscoverage['plugins/font.js'][503] = 0; + _$jscoverage['plugins/font.js'][504] = 0; + _$jscoverage['plugins/font.js'][510] = 0; + _$jscoverage['plugins/font.js'][515] = 0; + _$jscoverage['plugins/font.js'][518] = 0; + _$jscoverage['plugins/font.js'][521] = 0; + _$jscoverage['plugins/font.js'][522] = 0; + _$jscoverage['plugins/font.js'][523] = 0; + _$jscoverage['plugins/font.js'][524] = 0; + _$jscoverage['plugins/font.js'][525] = 0; + _$jscoverage['plugins/font.js'][527] = 0; + _$jscoverage['plugins/font.js'][528] = 0; + _$jscoverage['plugins/font.js'][532] = 0; + _$jscoverage['plugins/font.js'][534] = 0; + _$jscoverage['plugins/font.js'][536] = 0; + _$jscoverage['plugins/font.js'][537] = 0; + _$jscoverage['plugins/font.js'][538] = 0; + _$jscoverage['plugins/font.js'][539] = 0; + _$jscoverage['plugins/font.js'][540] = 0; + _$jscoverage['plugins/font.js'][541] = 0; + _$jscoverage['plugins/font.js'][544] = 0; + _$jscoverage['plugins/font.js'][546] = 0; + _$jscoverage['plugins/font.js'][549] = 0; + _$jscoverage['plugins/font.js'][550] = 0; + _$jscoverage['plugins/font.js'][553] = 0; + _$jscoverage['plugins/font.js'][555] = 0; + _$jscoverage['plugins/font.js'][559] = 0; + _$jscoverage['plugins/font.js'][563] = 0; + _$jscoverage['plugins/font.js'][566] = 0; + _$jscoverage['plugins/font.js'][567] = 0; + _$jscoverage['plugins/font.js'][568] = 0; + _$jscoverage['plugins/font.js'][569] = 0; + _$jscoverage['plugins/font.js'][570] = 0; + _$jscoverage['plugins/font.js'][572] = 0; +} +_$jscoverage['plugins/font.js'].source = ["/**"," * 字体颜色,背景色,字号,字体,下划线,删除线"," * @file"," * @since 1.2.6.1"," */","","/**"," * 设置字体颜色"," * @command forecolor"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param { String } value 色值"," * @example"," * ```javascript"," * editor.execCommand( 'forecolor', '#000' );"," * ```"," */","/**"," * 返回选区字体颜色"," * @command forecolor"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { String } 返回字体颜色"," * @example"," * ```javascript"," * editor.queryCommandValue( 'forecolor' );"," * ```"," */","","/**"," * 设置字体背景颜色"," * @command backcolor"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param { String } value 色值"," * @example"," * ```javascript"," * editor.execCommand( 'backcolor', '#000' );"," * ```"," */","/**"," * 返回选区字体颜色"," * @command backcolor"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { String } 返回字体背景颜色"," * @example"," * ```javascript"," * editor.queryCommandValue( 'backcolor' );"," * ```"," */","","/**"," * 设置字体大小"," * @command fontsize"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param { String } value 字体大小"," * @example"," * ```javascript"," * editor.execCommand( 'fontsize', '14px' );"," * ```"," */","/**"," * 返回选区字体大小"," * @command fontsize"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { String } 返回字体大小"," * @example"," * ```javascript"," * editor.queryCommandValue( 'fontsize' );"," * ```"," */","","/**"," * 设置字体样式"," * @command fontfamily"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param { String } value 字体大小"," * @example"," * ```javascript"," * editor.execCommand( 'fontfamily', '微软雅黑' );"," * ```"," */","/**"," * 返回选区字体样式"," * @command fontfamily"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { String } 返回字体样式"," * @example"," * ```javascript"," * editor.queryCommandValue( 'fontfamily' );"," * ```"," */","","/**"," * 根据选区内文本有无下划线设置字体下划线"," * @command underline"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'underline' );"," * ```"," */","/**"," * 返回选区下划线样式"," * @command underline"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { String } underline|default"," * @example"," * ```javascript"," * editor.queryCommandValue( 'underline' );"," * ```"," */","/**"," * 返回选区有无下划线"," * @command underline"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { Bool }true为有下划线,反之则无"," * @example"," * ```javascript"," * editor.queryCommandValue( 'underline' );"," * ```"," */","","/**"," * 根据选区内文本有无删除线设置字体删除线"," * @command strikethrough"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'strikethrough' );"," * ```"," */","/**"," * 返回选区删除线样式"," * @command strikethrough"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { String } line-through|default"," * @example"," * ```javascript"," * editor.queryCommandValue( 'strikethrough' );"," * ```"," */","/**"," * 返回选区有无删除线"," * @command strikethrough"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { Bool }true为有删除线,反之则无"," * @example"," * ```javascript"," * editor.queryCommandValue( 'strikethrough' );"," * ```"," */","","/**"," * 根据选区内文本有无字体边框设置字体边框"," * @command fontborder"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'fontborder' );"," * ```"," */","/**"," * 返回选区字体边框样式"," * @command fontborder"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { String } 字体边框样式"," * @example"," * ```javascript"," * editor.queryCommandValue( 'fontborder' );"," * ```"," */","/**"," * 返回选区有无字体边框"," * @command fontborder"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { Bool }true为有字体边框,反之则无"," * @example"," * ```javascript"," * editor.queryCommandValue( 'fontborder' );"," * ```"," */","UE.plugins['font'] = function () {"," var me = this,"," fonts = {"," 'forecolor': 'color',"," 'backcolor': 'background-color',"," 'fontsize': 'font-size',"," 'fontfamily': 'font-family',"," 'underline': 'text-decoration',"," 'strikethrough': 'text-decoration',"," 'fontborder': 'border'"," },"," needCmd = {'underline': 1, 'strikethrough': 1, 'fontborder': 1},"," needSetChild = {"," 'forecolor': 'color',"," 'backcolor': 'background-color',"," 'fontsize': 'font-size',"," 'fontfamily': 'font-family'",""," };"," me.setOpt({"," 'fontfamily': ["," { name: 'songti', val: '宋体,SimSun'},"," { name: 'yahei', val: '微软雅黑,Microsoft YaHei'},"," { name: 'kaiti', val: '楷体,楷体_GB2312, SimKai'},"," { name: 'heiti', val: '黑体, SimHei'},"," { name: 'lishu', val: '隶书, SimLi'},"," { name: 'andaleMono', val: 'andale mono'},"," { name: 'arial', val: 'arial, helvetica,sans-serif'},"," { name: 'arialBlack', val: 'arial black,avant garde'},"," { name: 'comicSansMs', val: 'comic sans ms'},"," { name: 'impact', val: 'impact,chicago'},"," { name: 'timesNewRoman', val: 'times new roman'}"," ],"," 'fontsize': [10, 11, 12, 14, 16, 18, 20, 24, 36]"," });",""," function mergeWithParent(node){"," var parent;"," while(parent = node.parentNode){"," if(parent.tagName == 'SPAN' && domUtils.getChildCount(parent,function(child){"," return !domUtils.isBookmarkNode(child) && !domUtils.isBr(child)"," }) == 1) {"," parent.style.cssText += node.style.cssText;"," domUtils.remove(node,true);"," node = parent;",""," }else{"," break;"," }"," }",""," }"," function mergeChild(rng,cmdName,value){"," if(needSetChild[cmdName]){"," rng.adjustmentBoundary();"," if(!rng.collapsed && rng.startContainer.nodeType == 1){"," var start = rng.startContainer.childNodes[rng.startOffset];"," if(start && domUtils.isTagNode(start,'span')){"," var bk = rng.createBookmark();"," utils.each(domUtils.getElementsByTagName(start, 'span'), function (span) {"," if (!span.parentNode || domUtils.isBookmarkNode(span))return;"," if(cmdName == 'backcolor' && domUtils.getComputedStyle(span,'background-color').toLowerCase() === value){"," return;"," }"," domUtils.removeStyle(span,needSetChild[cmdName]);"," if(span.style.cssText.replace(/^\\s+$/,'').length == 0){"," domUtils.remove(span,true)"," }"," });"," rng.moveToBookmark(bk)"," }"," }"," }",""," }"," function mergesibling(rng,cmdName,value) {"," var collapsed = rng.collapsed,"," bk = rng.createBookmark(), common;"," if (collapsed) {"," common = bk.start.parentNode;"," while (dtd.$inline[common.tagName]) {"," common = common.parentNode;"," }"," } else {"," common = domUtils.getCommonAncestor(bk.start, bk.end);"," }"," utils.each(domUtils.getElementsByTagName(common, 'span'), function (span) {"," if (!span.parentNode || domUtils.isBookmarkNode(span))return;"," if (/\\s*border\\s*:\\s*none;?\\s*/i.test(span.style.cssText)) {"," if(/^\\s*border\\s*:\\s*none;?\\s*$/.test(span.style.cssText)){"," domUtils.remove(span, true);"," }else{"," domUtils.removeStyle(span,'border');"," }"," return"," }"," if (/border/i.test(span.style.cssText) && span.parentNode.tagName == 'SPAN' && /border/i.test(span.parentNode.style.cssText)) {"," span.style.cssText = span.style.cssText.replace(/border[^:]*:[^;]+;?/gi, '');"," }"," if(!(cmdName=='fontborder' && value=='none')){"," var next = span.nextSibling;"," while (next && next.nodeType == 1 && next.tagName == 'SPAN' ) {"," if(domUtils.isBookmarkNode(next) && cmdName == 'fontborder') {"," span.appendChild(next);"," next = span.nextSibling;"," continue;"," }"," if (next.style.cssText == span.style.cssText) {"," domUtils.moveChild(next, span);"," domUtils.remove(next);"," }"," if (span.nextSibling === next)"," break;"," next = span.nextSibling;"," }"," }","",""," mergeWithParent(span);"," if(browser.ie && browser.version > 8 ){"," //拷贝父亲们的特别的属性,这里只做背景颜色的处理"," var parent = domUtils.findParent(span,function(n){return n.tagName == 'SPAN' && /background-color/.test(n.style.cssText)});"," if(parent && !/background-color/.test(span.style.cssText)){"," span.style.backgroundColor = parent.style.backgroundColor;"," }"," }",""," });"," rng.moveToBookmark(bk);"," mergeChild(rng,cmdName,value)"," }",""," me.addInputRule(function (root) {"," utils.each(root.getNodesByTagName('u s del font strike'), function (node) {"," if (node.tagName == 'font') {"," var cssStyle = [];"," for (var p in node.attrs) {"," switch (p) {"," case 'size':"," cssStyle.push('font-size:' + node.attrs[p] + 'px');"," break;"," case 'color':"," cssStyle.push('color:' + node.attrs[p]);"," break;"," case 'face':"," cssStyle.push('font-family:' + node.attrs[p]);"," break;"," case 'style':"," cssStyle.push(node.attrs[p]);"," }"," }"," node.attrs = {"," 'style': cssStyle.join(';')"," };"," } else {"," var val = node.tagName == 'u' ? 'underline' : 'line-through';"," node.attrs = {"," 'style': (node.getAttr('style') || '') + 'text-decoration:' + val + ';'"," }"," }"," node.tagName = 'span';"," });","// utils.each(root.getNodesByTagName('span'), function (node) {","// var val;","// if(val = node.getAttr('class')){","// if(/fontstrikethrough/.test(val)){","// node.setStyle('text-decoration','line-through');","// if(node.attrs['class']){","// node.attrs['class'] = node.attrs['class'].replace(/fontstrikethrough/,'');","// }else{","// node.setAttr('class')","// }","// }","// if(/fontborder/.test(val)){","// node.setStyle('border','1px solid #000');","// if(node.attrs['class']){","// node.attrs['class'] = node.attrs['class'].replace(/fontborder/,'');","// }else{","// node.setAttr('class')","// }","// }","// }","// });"," });","// me.addOutputRule(function(root){","// utils.each(root.getNodesByTagName('span'), function (node) {","// var val;","// if(val = node.getStyle('text-decoration')){","// if(/line-through/.test(val)){","// if(node.attrs['class']){","// node.attrs['class'] += ' fontstrikethrough';","// }else{","// node.setAttr('class','fontstrikethrough')","// }","// }","//","// node.setStyle('text-decoration')","// }","// if(val = node.getStyle('border')){","// if(/1px/.test(val) && /solid/.test(val)){","// if(node.attrs['class']){","// node.attrs['class'] += ' fontborder';","//","// }else{","// node.setAttr('class','fontborder')","// }","// }","// node.setStyle('border')","//","// }","// });","// });"," for (var p in fonts) {"," (function (cmd, style) {"," UE.commands[cmd] = {"," execCommand: function (cmdName, value) {"," value = value || (this.queryCommandState(cmdName) ? 'none' : cmdName == 'underline' ? 'underline' :"," cmdName == 'fontborder' ? '1px solid #000' :"," 'line-through');"," var me = this,"," range = this.selection.getRange(),"," text;",""," if (value == 'default') {",""," if (range.collapsed) {"," text = me.document.createTextNode('font');"," range.insertNode(text).select();",""," }"," me.execCommand('removeFormat', 'span,a', style);"," if (text) {"," range.setStartBefore(text).collapse(true);"," domUtils.remove(text);"," }"," mergesibling(range,cmdName,value);"," range.select()"," } else {"," if (!range.collapsed) {"," if (needCmd[cmd] && me.queryCommandValue(cmd)) {"," me.execCommand('removeFormat', 'span,a', style);"," }"," range = me.selection.getRange();",""," range.applyInlineStyle('span', {'style': style + ':' + value});"," mergesibling(range, cmdName,value);"," range.select();"," } else {",""," var span = domUtils.findParentByTagName(range.startContainer, 'span', true);"," text = me.document.createTextNode('font');"," if (span && !span.children.length && !span[browser.ie ? 'innerText' : 'textContent'].replace(fillCharReg, '').length) {"," //for ie hack when enter"," range.insertNode(text);"," if (needCmd[cmd]) {"," range.selectNode(text).select();"," me.execCommand('removeFormat', 'span,a', style, null);",""," span = domUtils.findParentByTagName(text, 'span', true);"," range.setStartBefore(text);",""," }"," span && (span.style.cssText += ';' + style + ':' + value);"," range.collapse(true).select();","",""," } else {"," range.insertNode(text);"," range.selectNode(text).select();"," span = range.document.createElement('span');",""," if (needCmd[cmd]) {"," //a标签内的不处理跳过"," if (domUtils.findParentByTagName(text, 'a', true)) {"," range.setStartBefore(text).setCursor();"," domUtils.remove(text);"," return;"," }"," me.execCommand('removeFormat', 'span,a', style);"," }",""," span.style.cssText = style + ':' + value;","",""," text.parentNode.insertBefore(span, text);"," //修复,span套span 但样式不继承的问题"," if (!browser.ie || browser.ie && browser.version == 9) {"," var spanParent = span.parentNode;"," while (!domUtils.isBlockElm(spanParent)) {"," if (spanParent.tagName == 'SPAN') {"," //opera合并style不会加入\";\""," span.style.cssText = spanParent.style.cssText + \";\" + span.style.cssText;"," }"," spanParent = spanParent.parentNode;"," }"," }","",""," if (opera) {"," setTimeout(function () {"," range.setStart(span, 0).collapse(true);"," mergesibling(range, cmdName,value);"," range.select();"," });"," } else {"," range.setStart(span, 0).collapse(true);"," mergesibling(range,cmdName,value);"," range.select();"," }",""," //trace:981"," //domUtils.mergeToParent(span)"," }"," domUtils.remove(text);"," }","",""," }"," return true;"," },"," queryCommandValue: function (cmdName) {"," var startNode = this.selection.getStart();",""," //trace:946"," if (cmdName == 'underline' || cmdName == 'strikethrough') {"," var tmpNode = startNode, value;"," while (tmpNode && !domUtils.isBlockElm(tmpNode) && !domUtils.isBody(tmpNode)) {"," if (tmpNode.nodeType == 1) {"," value = domUtils.getComputedStyle(tmpNode, style);",""," if (value != 'none') {"," return value;"," }"," }",""," tmpNode = tmpNode.parentNode;"," }"," return 'none';"," }"," if (cmdName == 'fontborder') {"," var tmp = startNode, val;"," while (tmp && dtd.$inline[tmp.tagName]) {"," if (val = domUtils.getComputedStyle(tmp, 'border')) {"," if (/1px/.test(val) && /solid/.test(val)) {"," return val;"," }"," }"," tmp = tmp.parentNode;"," }"," return ''"," }",""," if( cmdName == 'FontSize' ) {"," var styleVal = domUtils.getComputedStyle(startNode, style),"," tmp = /^([\\d\\.]+)(\\w+)$/.exec( styleVal );",""," if( tmp ) {",""," return Math.floor( tmp[1] ) + tmp[2];",""," }",""," return styleVal;",""," }",""," return domUtils.getComputedStyle(startNode, style);"," },"," queryCommandState: function (cmdName) {"," if (!needCmd[cmdName])"," return 0;"," var val = this.queryCommandValue(cmdName);"," if (cmdName == 'fontborder') {"," return /1px/.test(val) && /solid/.test(val)"," } else {"," return val == (cmdName == 'underline' ?"," 'underline' : 'line-through');"," }",""," }"," };"," })(p, fonts[p]);"," }","};"]; +_$jscoverage['plugins/font.js'][197]++; +UE.plugins.font = (function () { + _$jscoverage['plugins/font.js'][198]++; + var me = this, fonts = {"forecolor": "color", "backcolor": "background-color", "fontsize": "font-size", "fontfamily": "font-family", "underline": "text-decoration", "strikethrough": "text-decoration", "fontborder": "border"}, needCmd = {"underline": 1, "strikethrough": 1, "fontborder": 1}, needSetChild = {"forecolor": "color", "backcolor": "background-color", "fontsize": "font-size", "fontfamily": "font-family"}; + _$jscoverage['plugins/font.js'][216]++; + me.setOpt({"fontfamily": [{name: "songti", val: "\u5b8b\u4f53,SimSun"}, {name: "yahei", val: "\u5fae\u8f6f\u96c5\u9ed1,Microsoft YaHei"}, {name: "kaiti", val: "\u6977\u4f53,\u6977\u4f53_GB2312, SimKai"}, {name: "heiti", val: "\u9ed1\u4f53, SimHei"}, {name: "lishu", val: "\u96b6\u4e66, SimLi"}, {name: "andaleMono", val: "andale mono"}, {name: "arial", val: "arial, helvetica,sans-serif"}, {name: "arialBlack", val: "arial black,avant garde"}, {name: "comicSansMs", val: "comic sans ms"}, {name: "impact", val: "impact,chicago"}, {name: "timesNewRoman", val: "times new roman"}], "fontsize": [10, 11, 12, 14, 16, 18, 20, 24, 36]}); + _$jscoverage['plugins/font.js'][233]++; + function mergeWithParent(node) { + _$jscoverage['plugins/font.js'][234]++; + var parent; + _$jscoverage['plugins/font.js'][235]++; + while ((parent = node.parentNode)) { + _$jscoverage['plugins/font.js'][236]++; + if (((parent.tagName == "SPAN") && (domUtils.getChildCount(parent, (function (child) { + _$jscoverage['plugins/font.js'][237]++; + return ((! domUtils.isBookmarkNode(child)) && (! domUtils.isBr(child))); +})) == 1))) { + _$jscoverage['plugins/font.js'][239]++; + parent.style.cssText += node.style.cssText; + _$jscoverage['plugins/font.js'][240]++; + domUtils.remove(node, true); + _$jscoverage['plugins/font.js'][241]++; + node = parent; + } + else { + _$jscoverage['plugins/font.js'][244]++; + break; + } +} +} + _$jscoverage['plugins/font.js'][249]++; + function mergeChild(rng, cmdName, value) { + _$jscoverage['plugins/font.js'][250]++; + if (needSetChild[cmdName]) { + _$jscoverage['plugins/font.js'][251]++; + rng.adjustmentBoundary(); + _$jscoverage['plugins/font.js'][252]++; + if (((! rng.collapsed) && (rng.startContainer.nodeType == 1))) { + _$jscoverage['plugins/font.js'][253]++; + var start = rng.startContainer.childNodes[rng.startOffset]; + _$jscoverage['plugins/font.js'][254]++; + if ((start && domUtils.isTagNode(start, "span"))) { + _$jscoverage['plugins/font.js'][255]++; + var bk = rng.createBookmark(); + _$jscoverage['plugins/font.js'][256]++; + utils.each(domUtils.getElementsByTagName(start, "span"), (function (span) { + _$jscoverage['plugins/font.js'][257]++; + if (((! span.parentNode) || domUtils.isBookmarkNode(span))) { + _$jscoverage['plugins/font.js'][257]++; + return; + } + _$jscoverage['plugins/font.js'][258]++; + if (((cmdName == "backcolor") && (domUtils.getComputedStyle(span, "background-color").toLowerCase() === value))) { + _$jscoverage['plugins/font.js'][259]++; + return; + } + _$jscoverage['plugins/font.js'][261]++; + domUtils.removeStyle(span, needSetChild[cmdName]); + _$jscoverage['plugins/font.js'][262]++; + if ((span.style.cssText.replace(/^\s+$/, "").length == 0)) { + _$jscoverage['plugins/font.js'][263]++; + domUtils.remove(span, true); + } +})); + _$jscoverage['plugins/font.js'][266]++; + rng.moveToBookmark(bk); + } + } + } +} + _$jscoverage['plugins/font.js'][272]++; + function mergesibling(rng, cmdName, value) { + _$jscoverage['plugins/font.js'][273]++; + var collapsed = rng.collapsed, bk = rng.createBookmark(), common; + _$jscoverage['plugins/font.js'][275]++; + if (collapsed) { + _$jscoverage['plugins/font.js'][276]++; + common = bk.start.parentNode; + _$jscoverage['plugins/font.js'][277]++; + while (dtd.$inline[common.tagName]) { + _$jscoverage['plugins/font.js'][278]++; + common = common.parentNode; +} + } + else { + _$jscoverage['plugins/font.js'][281]++; + common = domUtils.getCommonAncestor(bk.start, bk.end); + } + _$jscoverage['plugins/font.js'][283]++; + utils.each(domUtils.getElementsByTagName(common, "span"), (function (span) { + _$jscoverage['plugins/font.js'][284]++; + if (((! span.parentNode) || domUtils.isBookmarkNode(span))) { + _$jscoverage['plugins/font.js'][284]++; + return; + } + _$jscoverage['plugins/font.js'][285]++; + if (/\s*border\s*:\s*none;?\s*/i.test(span.style.cssText)) { + _$jscoverage['plugins/font.js'][286]++; + if (/^\s*border\s*:\s*none;?\s*$/.test(span.style.cssText)) { + _$jscoverage['plugins/font.js'][287]++; + domUtils.remove(span, true); + } + else { + _$jscoverage['plugins/font.js'][289]++; + domUtils.removeStyle(span, "border"); + } + _$jscoverage['plugins/font.js'][291]++; + return; + } + _$jscoverage['plugins/font.js'][293]++; + if ((/border/i.test(span.style.cssText) && (span.parentNode.tagName == "SPAN") && /border/i.test(span.parentNode.style.cssText))) { + _$jscoverage['plugins/font.js'][294]++; + span.style.cssText = span.style.cssText.replace(/border[^:]*:[^;]+;?/gi, ""); + } + _$jscoverage['plugins/font.js'][296]++; + if ((! ((cmdName == "fontborder") && (value == "none")))) { + _$jscoverage['plugins/font.js'][297]++; + var next = span.nextSibling; + _$jscoverage['plugins/font.js'][298]++; + while ((next && (next.nodeType == 1) && (next.tagName == "SPAN"))) { + _$jscoverage['plugins/font.js'][299]++; + if ((domUtils.isBookmarkNode(next) && (cmdName == "fontborder"))) { + _$jscoverage['plugins/font.js'][300]++; + span.appendChild(next); + _$jscoverage['plugins/font.js'][301]++; + next = span.nextSibling; + _$jscoverage['plugins/font.js'][302]++; + continue; + } + _$jscoverage['plugins/font.js'][304]++; + if ((next.style.cssText == span.style.cssText)) { + _$jscoverage['plugins/font.js'][305]++; + domUtils.moveChild(next, span); + _$jscoverage['plugins/font.js'][306]++; + domUtils.remove(next); + } + _$jscoverage['plugins/font.js'][308]++; + if ((span.nextSibling === next)) { + _$jscoverage['plugins/font.js'][309]++; + break; + } + _$jscoverage['plugins/font.js'][310]++; + next = span.nextSibling; +} + } + _$jscoverage['plugins/font.js'][315]++; + mergeWithParent(span); + _$jscoverage['plugins/font.js'][316]++; + if ((browser.ie && (browser.version > 8))) { + _$jscoverage['plugins/font.js'][318]++; + var parent = domUtils.findParent(span, (function (n) { + _$jscoverage['plugins/font.js'][318]++; + return ((n.tagName == "SPAN") && /background-color/.test(n.style.cssText)); +})); + _$jscoverage['plugins/font.js'][319]++; + if ((parent && (! /background-color/.test(span.style.cssText)))) { + _$jscoverage['plugins/font.js'][320]++; + span.style.backgroundColor = parent.style.backgroundColor; + } + } +})); + _$jscoverage['plugins/font.js'][325]++; + rng.moveToBookmark(bk); + _$jscoverage['plugins/font.js'][326]++; + mergeChild(rng, cmdName, value); +} + _$jscoverage['plugins/font.js'][329]++; + me.addInputRule((function (root) { + _$jscoverage['plugins/font.js'][330]++; + utils.each(root.getNodesByTagName("u s del font strike"), (function (node) { + _$jscoverage['plugins/font.js'][331]++; + if ((node.tagName == "font")) { + _$jscoverage['plugins/font.js'][332]++; + var cssStyle = []; + _$jscoverage['plugins/font.js'][333]++; + for (var p in node.attrs) { + _$jscoverage['plugins/font.js'][334]++; + switch (p) { + case "size": + _$jscoverage['plugins/font.js'][336]++; + cssStyle.push(("font-size:" + node.attrs[p] + "px")); + _$jscoverage['plugins/font.js'][337]++; + break; + case "color": + _$jscoverage['plugins/font.js'][339]++; + cssStyle.push(("color:" + node.attrs[p])); + _$jscoverage['plugins/font.js'][340]++; + break; + case "face": + _$jscoverage['plugins/font.js'][342]++; + cssStyle.push(("font-family:" + node.attrs[p])); + _$jscoverage['plugins/font.js'][343]++; + break; + case "style": + _$jscoverage['plugins/font.js'][345]++; + cssStyle.push(node.attrs[p]); + } +} + _$jscoverage['plugins/font.js'][348]++; + node.attrs = {"style": cssStyle.join(";")}; + } + else { + _$jscoverage['plugins/font.js'][352]++; + var val = ((node.tagName == "u")? "underline": "line-through"); + _$jscoverage['plugins/font.js'][353]++; + node.attrs = {"style": ((node.getAttr("style") || "") + "text-decoration:" + val + ";")}; + } + _$jscoverage['plugins/font.js'][357]++; + node.tagName = "span"; +})); +})); + _$jscoverage['plugins/font.js'][409]++; + for (var p in fonts) { + _$jscoverage['plugins/font.js'][410]++; + (function (cmd, style) { + _$jscoverage['plugins/font.js'][411]++; + UE.commands[cmd] = {execCommand: (function (cmdName, value) { + _$jscoverage['plugins/font.js'][413]++; + value = (value || (this.queryCommandState(cmdName)? "none": ((cmdName == "underline")? "underline": ((cmdName == "fontborder")? "1px solid #000": "line-through")))); + _$jscoverage['plugins/font.js'][416]++; + var me = this, range = this.selection.getRange(), text; + _$jscoverage['plugins/font.js'][420]++; + if ((value == "default")) { + _$jscoverage['plugins/font.js'][422]++; + if (range.collapsed) { + _$jscoverage['plugins/font.js'][423]++; + text = me.document.createTextNode("font"); + _$jscoverage['plugins/font.js'][424]++; + range.insertNode(text).select(); + } + _$jscoverage['plugins/font.js'][427]++; + me.execCommand("removeFormat", "span,a", style); + _$jscoverage['plugins/font.js'][428]++; + if (text) { + _$jscoverage['plugins/font.js'][429]++; + range.setStartBefore(text).collapse(true); + _$jscoverage['plugins/font.js'][430]++; + domUtils.remove(text); + } + _$jscoverage['plugins/font.js'][432]++; + mergesibling(range, cmdName, value); + _$jscoverage['plugins/font.js'][433]++; + range.select(); + } + else { + _$jscoverage['plugins/font.js'][435]++; + if ((! range.collapsed)) { + _$jscoverage['plugins/font.js'][436]++; + if ((needCmd[cmd] && me.queryCommandValue(cmd))) { + _$jscoverage['plugins/font.js'][437]++; + me.execCommand("removeFormat", "span,a", style); + } + _$jscoverage['plugins/font.js'][439]++; + range = me.selection.getRange(); + _$jscoverage['plugins/font.js'][441]++; + range.applyInlineStyle("span", {"style": (style + ":" + value)}); + _$jscoverage['plugins/font.js'][442]++; + mergesibling(range, cmdName, value); + _$jscoverage['plugins/font.js'][443]++; + range.select(); + } + else { + _$jscoverage['plugins/font.js'][446]++; + var span = domUtils.findParentByTagName(range.startContainer, "span", true); + _$jscoverage['plugins/font.js'][447]++; + text = me.document.createTextNode("font"); + _$jscoverage['plugins/font.js'][448]++; + if ((span && (! span.children.length) && (! span[(browser.ie? "innerText": "textContent")].replace(fillCharReg, "").length))) { + _$jscoverage['plugins/font.js'][450]++; + range.insertNode(text); + _$jscoverage['plugins/font.js'][451]++; + if (needCmd[cmd]) { + _$jscoverage['plugins/font.js'][452]++; + range.selectNode(text).select(); + _$jscoverage['plugins/font.js'][453]++; + me.execCommand("removeFormat", "span,a", style, null); + _$jscoverage['plugins/font.js'][455]++; + span = domUtils.findParentByTagName(text, "span", true); + _$jscoverage['plugins/font.js'][456]++; + range.setStartBefore(text); + } + _$jscoverage['plugins/font.js'][459]++; + (span && (span.style.cssText += (";" + style + ":" + value))); + _$jscoverage['plugins/font.js'][460]++; + range.collapse(true).select(); + } + else { + _$jscoverage['plugins/font.js'][464]++; + range.insertNode(text); + _$jscoverage['plugins/font.js'][465]++; + range.selectNode(text).select(); + _$jscoverage['plugins/font.js'][466]++; + span = range.document.createElement("span"); + _$jscoverage['plugins/font.js'][468]++; + if (needCmd[cmd]) { + _$jscoverage['plugins/font.js'][470]++; + if (domUtils.findParentByTagName(text, "a", true)) { + _$jscoverage['plugins/font.js'][471]++; + range.setStartBefore(text).setCursor(); + _$jscoverage['plugins/font.js'][472]++; + domUtils.remove(text); + _$jscoverage['plugins/font.js'][473]++; + return; + } + _$jscoverage['plugins/font.js'][475]++; + me.execCommand("removeFormat", "span,a", style); + } + _$jscoverage['plugins/font.js'][478]++; + span.style.cssText = (style + ":" + value); + _$jscoverage['plugins/font.js'][481]++; + text.parentNode.insertBefore(span, text); + _$jscoverage['plugins/font.js'][483]++; + if (((! browser.ie) || (browser.ie && (browser.version == 9)))) { + _$jscoverage['plugins/font.js'][484]++; + var spanParent = span.parentNode; + _$jscoverage['plugins/font.js'][485]++; + while ((! domUtils.isBlockElm(spanParent))) { + _$jscoverage['plugins/font.js'][486]++; + if ((spanParent.tagName == "SPAN")) { + _$jscoverage['plugins/font.js'][488]++; + span.style.cssText = (spanParent.style.cssText + ";" + span.style.cssText); + } + _$jscoverage['plugins/font.js'][490]++; + spanParent = spanParent.parentNode; +} + } + _$jscoverage['plugins/font.js'][495]++; + if (opera) { + _$jscoverage['plugins/font.js'][496]++; + setTimeout((function () { + _$jscoverage['plugins/font.js'][497]++; + range.setStart(span, 0).collapse(true); + _$jscoverage['plugins/font.js'][498]++; + mergesibling(range, cmdName, value); + _$jscoverage['plugins/font.js'][499]++; + range.select(); +})); + } + else { + _$jscoverage['plugins/font.js'][502]++; + range.setStart(span, 0).collapse(true); + _$jscoverage['plugins/font.js'][503]++; + mergesibling(range, cmdName, value); + _$jscoverage['plugins/font.js'][504]++; + range.select(); + } + } + _$jscoverage['plugins/font.js'][510]++; + domUtils.remove(text); + } + } + _$jscoverage['plugins/font.js'][515]++; + return true; +}), queryCommandValue: (function (cmdName) { + _$jscoverage['plugins/font.js'][518]++; + var startNode = this.selection.getStart(); + _$jscoverage['plugins/font.js'][521]++; + if (((cmdName == "underline") || (cmdName == "strikethrough"))) { + _$jscoverage['plugins/font.js'][522]++; + var tmpNode = startNode, value; + _$jscoverage['plugins/font.js'][523]++; + while ((tmpNode && (! domUtils.isBlockElm(tmpNode)) && (! domUtils.isBody(tmpNode)))) { + _$jscoverage['plugins/font.js'][524]++; + if ((tmpNode.nodeType == 1)) { + _$jscoverage['plugins/font.js'][525]++; + value = domUtils.getComputedStyle(tmpNode, style); + _$jscoverage['plugins/font.js'][527]++; + if ((value != "none")) { + _$jscoverage['plugins/font.js'][528]++; + return value; + } + } + _$jscoverage['plugins/font.js'][532]++; + tmpNode = tmpNode.parentNode; +} + _$jscoverage['plugins/font.js'][534]++; + return "none"; + } + _$jscoverage['plugins/font.js'][536]++; + if ((cmdName == "fontborder")) { + _$jscoverage['plugins/font.js'][537]++; + var tmp = startNode, val; + _$jscoverage['plugins/font.js'][538]++; + while ((tmp && dtd.$inline[tmp.tagName])) { + _$jscoverage['plugins/font.js'][539]++; + if ((val = domUtils.getComputedStyle(tmp, "border"))) { + _$jscoverage['plugins/font.js'][540]++; + if ((/1px/.test(val) && /solid/.test(val))) { + _$jscoverage['plugins/font.js'][541]++; + return val; + } + } + _$jscoverage['plugins/font.js'][544]++; + tmp = tmp.parentNode; +} + _$jscoverage['plugins/font.js'][546]++; + return ""; + } + _$jscoverage['plugins/font.js'][549]++; + if ((cmdName == "FontSize")) { + _$jscoverage['plugins/font.js'][550]++; + var styleVal = domUtils.getComputedStyle(startNode, style), tmp = /^([\d\.]+)(\w+)$/.exec(styleVal); + _$jscoverage['plugins/font.js'][553]++; + if (tmp) { + _$jscoverage['plugins/font.js'][555]++; + return (Math.floor(tmp[1]) + tmp[2]); + } + _$jscoverage['plugins/font.js'][559]++; + return styleVal; + } + _$jscoverage['plugins/font.js'][563]++; + return domUtils.getComputedStyle(startNode, style); +}), queryCommandState: (function (cmdName) { + _$jscoverage['plugins/font.js'][566]++; + if ((! needCmd[cmdName])) { + _$jscoverage['plugins/font.js'][567]++; + return 0; + } + _$jscoverage['plugins/font.js'][568]++; + var val = this.queryCommandValue(cmdName); + _$jscoverage['plugins/font.js'][569]++; + if ((cmdName == "fontborder")) { + _$jscoverage['plugins/font.js'][570]++; + return (/1px/.test(val) && /solid/.test(val)); + } + else { + _$jscoverage['plugins/font.js'][572]++; + return (val == ((cmdName == "underline")? "underline": "line-through")); + } +})}; +})(p, fonts[p]); +} +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/formatmatch.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/formatmatch.js new file mode 100644 index 000000000..0dbe004f9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/formatmatch.js @@ -0,0 +1,237 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/formatmatch.js']) { + _$jscoverage['plugins/formatmatch.js'] = []; + _$jscoverage['plugins/formatmatch.js'][39] = 0; + _$jscoverage['plugins/formatmatch.js'][41] = 0; + _$jscoverage['plugins/formatmatch.js'][45] = 0; + _$jscoverage['plugins/formatmatch.js'][46] = 0; + _$jscoverage['plugins/formatmatch.js'][47] = 0; + _$jscoverage['plugins/formatmatch.js'][50] = 0; + _$jscoverage['plugins/formatmatch.js'][52] = 0; + _$jscoverage['plugins/formatmatch.js'][53] = 0; + _$jscoverage['plugins/formatmatch.js'][56] = 0; + _$jscoverage['plugins/formatmatch.js'][58] = 0; + _$jscoverage['plugins/formatmatch.js'][59] = 0; + _$jscoverage['plugins/formatmatch.js'][61] = 0; + _$jscoverage['plugins/formatmatch.js'][65] = 0; + _$jscoverage['plugins/formatmatch.js'][67] = 0; + _$jscoverage['plugins/formatmatch.js'][69] = 0; + _$jscoverage['plugins/formatmatch.js'][72] = 0; + _$jscoverage['plugins/formatmatch.js'][74] = 0; + _$jscoverage['plugins/formatmatch.js'][76] = 0; + _$jscoverage['plugins/formatmatch.js'][77] = 0; + _$jscoverage['plugins/formatmatch.js'][78] = 0; + _$jscoverage['plugins/formatmatch.js'][79] = 0; + _$jscoverage['plugins/formatmatch.js'][80] = 0; + _$jscoverage['plugins/formatmatch.js'][84] = 0; + _$jscoverage['plugins/formatmatch.js'][87] = 0; + _$jscoverage['plugins/formatmatch.js'][88] = 0; + _$jscoverage['plugins/formatmatch.js'][89] = 0; + _$jscoverage['plugins/formatmatch.js'][90] = 0; + _$jscoverage['plugins/formatmatch.js'][91] = 0; + _$jscoverage['plugins/formatmatch.js'][93] = 0; + _$jscoverage['plugins/formatmatch.js'][94] = 0; + _$jscoverage['plugins/formatmatch.js'][95] = 0; + _$jscoverage['plugins/formatmatch.js'][97] = 0; + _$jscoverage['plugins/formatmatch.js'][98] = 0; + _$jscoverage['plugins/formatmatch.js'][101] = 0; + _$jscoverage['plugins/formatmatch.js'][102] = 0; + _$jscoverage['plugins/formatmatch.js'][110] = 0; + _$jscoverage['plugins/formatmatch.js'][111] = 0; + _$jscoverage['plugins/formatmatch.js'][112] = 0; + _$jscoverage['plugins/formatmatch.js'][115] = 0; + _$jscoverage['plugins/formatmatch.js'][118] = 0; + _$jscoverage['plugins/formatmatch.js'][119] = 0; + _$jscoverage['plugins/formatmatch.js'][120] = 0; + _$jscoverage['plugins/formatmatch.js'][121] = 0; + _$jscoverage['plugins/formatmatch.js'][122] = 0; + _$jscoverage['plugins/formatmatch.js'][127] = 0; + _$jscoverage['plugins/formatmatch.js'][128] = 0; + _$jscoverage['plugins/formatmatch.js'][129] = 0; + _$jscoverage['plugins/formatmatch.js'][130] = 0; + _$jscoverage['plugins/formatmatch.js'][131] = 0; + _$jscoverage['plugins/formatmatch.js'][132] = 0; + _$jscoverage['plugins/formatmatch.js'][133] = 0; + _$jscoverage['plugins/formatmatch.js'][136] = 0; + _$jscoverage['plugins/formatmatch.js'][137] = 0; + _$jscoverage['plugins/formatmatch.js'][138] = 0; + _$jscoverage['plugins/formatmatch.js'][139] = 0; + _$jscoverage['plugins/formatmatch.js'][145] = 0; + _$jscoverage['plugins/formatmatch.js'][146] = 0; + _$jscoverage['plugins/formatmatch.js'][151] = 0; +} +_$jscoverage['plugins/formatmatch.js'].source = ["///import core","///import plugins\\removeformat.js","///commands 格式刷","///commandsName FormatMatch","///commandsTitle 格式刷","/**"," * 格式刷,只格式inline的"," * @file"," * @since 1.2.6.1"," */","","/**"," * 格式刷,对inline类型的文本内容执行格式刷操作"," * @command formatmatch"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * //editor是编辑器实例"," * //获取格式刷"," * editor.execCommand( 'formatmatch' );"," * ```"," */","","/**"," * 获取当前的格式状态"," * @command formatmatch"," * @method queryCommandState"," * @param { String } cmd 命令字符串"," * @return { int } 如果当前的格式刷处于可用状态, 则返回1, 否则返回0"," * @example"," * ```javascript"," * //editor是编辑器实例"," * //获取当前选中的文本内容的上标状态"," * //output: 1 或者 0"," * console.log( editor.queryCommandState( 'formatmatch' ) );"," * ```"," */","UE.plugins['formatmatch'] = function(){",""," var me = this,"," list = [],img,"," flag = 0;",""," me.addListener('reset',function(){"," list = [];"," flag = 0;"," });",""," function addList(type,evt){"," "," if(browser.webkit){"," var target = evt.target.tagName == 'IMG' ? evt.target : null;"," }",""," function addFormat(range){",""," if(text){"," range.selectNode(text);"," }"," return range.applyInlineStyle(list[list.length-1].tagName,null,list);",""," }",""," me.undoManger && me.undoManger.save();",""," var range = me.selection.getRange(),"," imgT = target || range.getClosedNode();"," if(img && imgT && imgT.tagName == 'IMG'){"," //trace:964",""," imgT.style.cssText += ';float:' + (img.style.cssFloat || img.style.styleFloat ||'none') + ';display:' + (img.style.display||'inline');",""," img = null;"," }else{"," if(!img){"," var collapsed = range.collapsed;"," if(collapsed){"," var text = me.document.createTextNode('match');"," range.insertNode(text).select();","",""," }"," me.__hasEnterExecCommand = true;"," //不能把block上的属性干掉"," //trace:1553"," var removeFormatAttributes = me.options.removeFormatAttributes;"," me.options.removeFormatAttributes = '';"," me.execCommand('removeformat');"," me.options.removeFormatAttributes = removeFormatAttributes;"," me.__hasEnterExecCommand = false;"," //trace:969"," range = me.selection.getRange();"," if(list.length){"," addFormat(range);"," }"," if(text){"," range.setStartBefore(text).collapse(true);",""," }"," range.select();"," text && domUtils.remove(text);"," }",""," }","","","",""," me.undoManger && me.undoManger.save();"," me.removeListener('mouseup',addList);"," flag = 0;"," }",""," me.commands['formatmatch'] = {"," execCommand : function( cmdName ) {"," "," if(flag){"," flag = 0;"," list = [];"," me.removeListener('mouseup',addList);"," return;"," }","",""," "," var range = me.selection.getRange();"," img = range.getClosedNode();"," if(!img || img.tagName != 'IMG'){"," range.collapse(true).shrinkBoundary();"," var start = range.startContainer;"," list = domUtils.findParents(start,true,function(node){"," return !domUtils.isBlockElm(node) && node.nodeType == 1;"," });"," //a不能加入格式刷, 并且克隆节点"," for(var i=0,ci;ci=list[i];i++){"," if(ci.tagName == 'A'){"," list.splice(i,1);"," break;"," }"," }",""," }",""," me.addListener('mouseup',addList);"," flag = 1;","",""," },"," queryCommandState : function() {"," return flag;"," },"," notNeedUndo : 1"," };","};",""]; +_$jscoverage['plugins/formatmatch.js'][39]++; +UE.plugins.formatmatch = (function () { + _$jscoverage['plugins/formatmatch.js'][41]++; + var me = this, list = [], img, flag = 0; + _$jscoverage['plugins/formatmatch.js'][45]++; + me.addListener("reset", (function () { + _$jscoverage['plugins/formatmatch.js'][46]++; + list = []; + _$jscoverage['plugins/formatmatch.js'][47]++; + flag = 0; +})); + _$jscoverage['plugins/formatmatch.js'][50]++; + function addList(type, evt) { + _$jscoverage['plugins/formatmatch.js'][52]++; + if (browser.webkit) { + _$jscoverage['plugins/formatmatch.js'][53]++; + var target = ((evt.target.tagName == "IMG")? evt.target: null); + } + _$jscoverage['plugins/formatmatch.js'][56]++; + function addFormat(range) { + _$jscoverage['plugins/formatmatch.js'][58]++; + if (text) { + _$jscoverage['plugins/formatmatch.js'][59]++; + range.selectNode(text); + } + _$jscoverage['plugins/formatmatch.js'][61]++; + return range.applyInlineStyle(list[(list.length - 1)].tagName, null, list); +} + _$jscoverage['plugins/formatmatch.js'][65]++; + (me.undoManger && me.undoManger.save()); + _$jscoverage['plugins/formatmatch.js'][67]++; + var range = me.selection.getRange(), imgT = (target || range.getClosedNode()); + _$jscoverage['plugins/formatmatch.js'][69]++; + if ((img && imgT && (imgT.tagName == "IMG"))) { + _$jscoverage['plugins/formatmatch.js'][72]++; + imgT.style.cssText += (";float:" + (img.style.cssFloat || img.style.styleFloat || "none") + ";display:" + (img.style.display || "inline")); + _$jscoverage['plugins/formatmatch.js'][74]++; + img = null; + } + else { + _$jscoverage['plugins/formatmatch.js'][76]++; + if ((! img)) { + _$jscoverage['plugins/formatmatch.js'][77]++; + var collapsed = range.collapsed; + _$jscoverage['plugins/formatmatch.js'][78]++; + if (collapsed) { + _$jscoverage['plugins/formatmatch.js'][79]++; + var text = me.document.createTextNode("match"); + _$jscoverage['plugins/formatmatch.js'][80]++; + range.insertNode(text).select(); + } + _$jscoverage['plugins/formatmatch.js'][84]++; + me.__hasEnterExecCommand = true; + _$jscoverage['plugins/formatmatch.js'][87]++; + var removeFormatAttributes = me.options.removeFormatAttributes; + _$jscoverage['plugins/formatmatch.js'][88]++; + me.options.removeFormatAttributes = ""; + _$jscoverage['plugins/formatmatch.js'][89]++; + me.execCommand("removeformat"); + _$jscoverage['plugins/formatmatch.js'][90]++; + me.options.removeFormatAttributes = removeFormatAttributes; + _$jscoverage['plugins/formatmatch.js'][91]++; + me.__hasEnterExecCommand = false; + _$jscoverage['plugins/formatmatch.js'][93]++; + range = me.selection.getRange(); + _$jscoverage['plugins/formatmatch.js'][94]++; + if (list.length) { + _$jscoverage['plugins/formatmatch.js'][95]++; + addFormat(range); + } + _$jscoverage['plugins/formatmatch.js'][97]++; + if (text) { + _$jscoverage['plugins/formatmatch.js'][98]++; + range.setStartBefore(text).collapse(true); + } + _$jscoverage['plugins/formatmatch.js'][101]++; + range.select(); + _$jscoverage['plugins/formatmatch.js'][102]++; + (text && domUtils.remove(text)); + } + } + _$jscoverage['plugins/formatmatch.js'][110]++; + (me.undoManger && me.undoManger.save()); + _$jscoverage['plugins/formatmatch.js'][111]++; + me.removeListener("mouseup", addList); + _$jscoverage['plugins/formatmatch.js'][112]++; + flag = 0; +} + _$jscoverage['plugins/formatmatch.js'][115]++; + me.commands.formatmatch = {execCommand: (function (cmdName) { + _$jscoverage['plugins/formatmatch.js'][118]++; + if (flag) { + _$jscoverage['plugins/formatmatch.js'][119]++; + flag = 0; + _$jscoverage['plugins/formatmatch.js'][120]++; + list = []; + _$jscoverage['plugins/formatmatch.js'][121]++; + me.removeListener("mouseup", addList); + _$jscoverage['plugins/formatmatch.js'][122]++; + return; + } + _$jscoverage['plugins/formatmatch.js'][127]++; + var range = me.selection.getRange(); + _$jscoverage['plugins/formatmatch.js'][128]++; + img = range.getClosedNode(); + _$jscoverage['plugins/formatmatch.js'][129]++; + if (((! img) || (img.tagName != "IMG"))) { + _$jscoverage['plugins/formatmatch.js'][130]++; + range.collapse(true).shrinkBoundary(); + _$jscoverage['plugins/formatmatch.js'][131]++; + var start = range.startContainer; + _$jscoverage['plugins/formatmatch.js'][132]++; + list = domUtils.findParents(start, true, (function (node) { + _$jscoverage['plugins/formatmatch.js'][133]++; + return ((! domUtils.isBlockElm(node)) && (node.nodeType == 1)); +})); + _$jscoverage['plugins/formatmatch.js'][136]++; + for (var i = 0, ci; (ci = list[i]); (i++)) { + _$jscoverage['plugins/formatmatch.js'][137]++; + if ((ci.tagName == "A")) { + _$jscoverage['plugins/formatmatch.js'][138]++; + list.splice(i, 1); + _$jscoverage['plugins/formatmatch.js'][139]++; + break; + } +} + } + _$jscoverage['plugins/formatmatch.js'][145]++; + me.addListener("mouseup", addList); + _$jscoverage['plugins/formatmatch.js'][146]++; + flag = 1; +}), queryCommandState: (function () { + _$jscoverage['plugins/formatmatch.js'][151]++; + return flag; +}), notNeedUndo: 1}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/horizontal.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/horizontal.js new file mode 100644 index 000000000..f619da64d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/horizontal.js @@ -0,0 +1,149 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/horizontal.js']) { + _$jscoverage['plugins/horizontal.js'] = []; + _$jscoverage['plugins/horizontal.js'][28] = 0; + _$jscoverage['plugins/horizontal.js'][29] = 0; + _$jscoverage['plugins/horizontal.js'][30] = 0; + _$jscoverage['plugins/horizontal.js'][32] = 0; + _$jscoverage['plugins/horizontal.js'][33] = 0; + _$jscoverage['plugins/horizontal.js'][34] = 0; + _$jscoverage['plugins/horizontal.js'][35] = 0; + _$jscoverage['plugins/horizontal.js'][37] = 0; + _$jscoverage['plugins/horizontal.js'][39] = 0; + _$jscoverage['plugins/horizontal.js'][40] = 0; + _$jscoverage['plugins/horizontal.js'][41] = 0; + _$jscoverage['plugins/horizontal.js'][42] = 0; + _$jscoverage['plugins/horizontal.js'][43] = 0; + _$jscoverage['plugins/horizontal.js'][44] = 0; + _$jscoverage['plugins/horizontal.js'][45] = 0; + _$jscoverage['plugins/horizontal.js'][48] = 0; + _$jscoverage['plugins/horizontal.js'][49] = 0; + _$jscoverage['plugins/horizontal.js'][50] = 0; + _$jscoverage['plugins/horizontal.js'][56] = 0; + _$jscoverage['plugins/horizontal.js'][62] = 0; + _$jscoverage['plugins/horizontal.js'][98] = 0; + _$jscoverage['plugins/horizontal.js'][99] = 0; + _$jscoverage['plugins/horizontal.js'][100] = 0; + _$jscoverage['plugins/horizontal.js'][101] = 0; + _$jscoverage['plugins/horizontal.js'][102] = 0; + _$jscoverage['plugins/horizontal.js'][103] = 0; + _$jscoverage['plugins/horizontal.js'][104] = 0; + _$jscoverage['plugins/horizontal.js'][105] = 0; + _$jscoverage['plugins/horizontal.js'][106] = 0; + _$jscoverage['plugins/horizontal.js'][107] = 0; + _$jscoverage['plugins/horizontal.js'][108] = 0; +} +_$jscoverage['plugins/horizontal.js'].source = ["/**"," * 插入分割线插件"," * @file"," * @since 1.2.6.1"," */","","/**"," * 插入分割线,分割线是hr标签"," * @command horizontal"," * @method execCommand"," * @param { String } cmdName 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'horizontal' );"," * ```"," */","","/**"," * 查询当前是否允许插入分割线"," * @command horizontal"," * @method queryCommandState"," * @return { Int } 如果选区在表格里面,返回0,否则返回1"," * @example"," * ```javascript"," * editor.queryCommandState( 'horizontal' );"," * ```"," */","UE.plugins['horizontal'] = function(){"," var me = this;"," me.commands['horizontal'] = {"," execCommand : function( cmdName ) {"," var me = this;"," if(me.queryCommandState(cmdName)!==-1){"," me.execCommand('insertHtml','<hr>');"," var range = me.selection.getRange(),"," start = range.startContainer;"," if(start.nodeType == 1 && !start.childNodes[range.startOffset] ){",""," var tmp;"," if(tmp = start.childNodes[range.startOffset - 1]){"," if(tmp.nodeType == 1 && tmp.tagName == 'HR'){"," if(me.options.enterTag == 'p'){"," tmp = me.document.createElement('p');"," range.insertNode(tmp);"," range.setStart(tmp,0).setCursor();",""," }else{"," tmp = me.document.createElement('br');"," range.insertNode(tmp);"," range.setStartBefore(tmp).setCursor();"," }"," }"," }",""," }"," return true;"," }",""," },"," //边界在table里不能加分隔线"," queryCommandState : function() {"," return domUtils.filterNodeList(this.selection.getStartElementPath(),'table') ? -1 : 0;"," }"," };","// me.addListener('delkeyup',function(){","// var rng = this.selection.getRange();","// if(browser.ie && browser.version > 8){","// rng.txtToElmBoundary(true);","// if(domUtils.isStartInblock(rng)){","// var tmpNode = rng.startContainer;","// var pre = tmpNode.previousSibling;","// if(pre && domUtils.isTagNode(pre,'hr')){","// domUtils.remove(pre);","// rng.select();","// return;","// }","// }","// }","// if(domUtils.isBody(rng.startContainer)){","// var hr = rng.startContainer.childNodes[rng.startOffset -1];","// if(hr && hr.nodeName == 'HR'){","// var next = hr.nextSibling;","// if(next){","// rng.setStart(next,0)","// }else if(hr.previousSibling){","// rng.setStartAtLast(hr.previousSibling)","// }else{","// var p = this.document.createElement('p');","// hr.parentNode.insertBefore(p,hr);","// domUtils.fillNode(this.document,p);","// rng.setStart(p,0);","// }","// domUtils.remove(hr);","// rng.setCursor(false,true);","// }","// }","// })"," me.addListener('delkeydown',function(name,evt){"," var rng = this.selection.getRange();"," rng.txtToElmBoundary(true);"," if(domUtils.isStartInblock(rng)){"," var tmpNode = rng.startContainer;"," var pre = tmpNode.previousSibling;"," if(pre && domUtils.isTagNode(pre,'hr')){"," domUtils.remove(pre);"," rng.select();"," domUtils.preventDefault(evt);"," return true;",""," }"," }",""," })","};",""]; +_$jscoverage['plugins/horizontal.js'][28]++; +UE.plugins.horizontal = (function () { + _$jscoverage['plugins/horizontal.js'][29]++; + var me = this; + _$jscoverage['plugins/horizontal.js'][30]++; + me.commands.horizontal = {execCommand: (function (cmdName) { + _$jscoverage['plugins/horizontal.js'][32]++; + var me = this; + _$jscoverage['plugins/horizontal.js'][33]++; + if ((me.queryCommandState(cmdName) !== -1)) { + _$jscoverage['plugins/horizontal.js'][34]++; + me.execCommand("insertHtml", "


    "); + _$jscoverage['plugins/horizontal.js'][35]++; + var range = me.selection.getRange(), start = range.startContainer; + _$jscoverage['plugins/horizontal.js'][37]++; + if (((start.nodeType == 1) && (! start.childNodes[range.startOffset]))) { + _$jscoverage['plugins/horizontal.js'][39]++; + var tmp; + _$jscoverage['plugins/horizontal.js'][40]++; + if ((tmp = start.childNodes[(range.startOffset - 1)])) { + _$jscoverage['plugins/horizontal.js'][41]++; + if (((tmp.nodeType == 1) && (tmp.tagName == "HR"))) { + _$jscoverage['plugins/horizontal.js'][42]++; + if ((me.options.enterTag == "p")) { + _$jscoverage['plugins/horizontal.js'][43]++; + tmp = me.document.createElement("p"); + _$jscoverage['plugins/horizontal.js'][44]++; + range.insertNode(tmp); + _$jscoverage['plugins/horizontal.js'][45]++; + range.setStart(tmp, 0).setCursor(); + } + else { + _$jscoverage['plugins/horizontal.js'][48]++; + tmp = me.document.createElement("br"); + _$jscoverage['plugins/horizontal.js'][49]++; + range.insertNode(tmp); + _$jscoverage['plugins/horizontal.js'][50]++; + range.setStartBefore(tmp).setCursor(); + } + } + } + } + _$jscoverage['plugins/horizontal.js'][56]++; + return true; + } +}), queryCommandState: (function () { + _$jscoverage['plugins/horizontal.js'][62]++; + return (domUtils.filterNodeList(this.selection.getStartElementPath(), "table")? -1: 0); +})}; + _$jscoverage['plugins/horizontal.js'][98]++; + me.addListener("delkeydown", (function (name, evt) { + _$jscoverage['plugins/horizontal.js'][99]++; + var rng = this.selection.getRange(); + _$jscoverage['plugins/horizontal.js'][100]++; + rng.txtToElmBoundary(true); + _$jscoverage['plugins/horizontal.js'][101]++; + if (domUtils.isStartInblock(rng)) { + _$jscoverage['plugins/horizontal.js'][102]++; + var tmpNode = rng.startContainer; + _$jscoverage['plugins/horizontal.js'][103]++; + var pre = tmpNode.previousSibling; + _$jscoverage['plugins/horizontal.js'][104]++; + if ((pre && domUtils.isTagNode(pre, "hr"))) { + _$jscoverage['plugins/horizontal.js'][105]++; + domUtils.remove(pre); + _$jscoverage['plugins/horizontal.js'][106]++; + rng.select(); + _$jscoverage['plugins/horizontal.js'][107]++; + domUtils.preventDefault(evt); + _$jscoverage['plugins/horizontal.js'][108]++; + return true; + } + } +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/iframe.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/iframe.js new file mode 100644 index 000000000..33406b245 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/iframe.js @@ -0,0 +1,64 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/iframe.js']) { + _$jscoverage['plugins/iframe.js'] = []; + _$jscoverage['plugins/iframe.js'][8] = 0; + _$jscoverage['plugins/iframe.js'][9] = 0; + _$jscoverage['plugins/iframe.js'][10] = 0; + _$jscoverage['plugins/iframe.js'][11] = 0; + _$jscoverage['plugins/iframe.js'][14] = 0; + _$jscoverage['plugins/iframe.js'][15] = 0; +} +_$jscoverage['plugins/iframe.js'].source = ["///import core","///import plugins\\inserthtml.js","///commands 插入框架","///commandsName InsertFrame","///commandsTitle 插入Iframe","///commandsDialog dialogs\\insertframe","","UE.plugins['insertframe'] = function() {"," var me =this;"," function deleteIframe(){"," me._iframe && delete me._iframe;"," }",""," me.addListener(\"selectionchange\",function(){"," deleteIframe();"," });","","};",""]; +_$jscoverage['plugins/iframe.js'][8]++; +UE.plugins.insertframe = (function () { + _$jscoverage['plugins/iframe.js'][9]++; + var me = this; + _$jscoverage['plugins/iframe.js'][10]++; + function deleteIframe() { + _$jscoverage['plugins/iframe.js'][11]++; + (me._iframe && (delete me._iframe)); +} + _$jscoverage['plugins/iframe.js'][14]++; + me.addListener("selectionchange", (function () { + _$jscoverage['plugins/iframe.js'][15]++; + deleteIframe(); +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/image.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/image.js new file mode 100644 index 000000000..5c6b26110 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/image.js @@ -0,0 +1,354 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/image.js']) { + _$jscoverage['plugins/image.js'] = []; + _$jscoverage['plugins/image.js'][41] = 0; + _$jscoverage['plugins/image.js'][43] = 0; + _$jscoverage['plugins/image.js'][45] = 0; + _$jscoverage['plugins/image.js'][46] = 0; + _$jscoverage['plugins/image.js'][47] = 0; + _$jscoverage['plugins/image.js'][48] = 0; + _$jscoverage['plugins/image.js'][52] = 0; + _$jscoverage['plugins/image.js'][53] = 0; + _$jscoverage['plugins/image.js'][54] = 0; + _$jscoverage['plugins/image.js'][56] = 0; + _$jscoverage['plugins/image.js'][57] = 0; + _$jscoverage['plugins/image.js'][58] = 0; + _$jscoverage['plugins/image.js'][59] = 0; + _$jscoverage['plugins/image.js'][61] = 0; + _$jscoverage['plugins/image.js'][62] = 0; + _$jscoverage['plugins/image.js'][63] = 0; + _$jscoverage['plugins/image.js'][64] = 0; + _$jscoverage['plugins/image.js'][65] = 0; + _$jscoverage['plugins/image.js'][66] = 0; + _$jscoverage['plugins/image.js'][68] = 0; + _$jscoverage['plugins/image.js'][69] = 0; + _$jscoverage['plugins/image.js'][71] = 0; + _$jscoverage['plugins/image.js'][77] = 0; + _$jscoverage['plugins/image.js'][79] = 0; + _$jscoverage['plugins/image.js'][80] = 0; + _$jscoverage['plugins/image.js'][81] = 0; + _$jscoverage['plugins/image.js'][84] = 0; + _$jscoverage['plugins/image.js'][86] = 0; + _$jscoverage['plugins/image.js'][87] = 0; + _$jscoverage['plugins/image.js'][88] = 0; + _$jscoverage['plugins/image.js'][89] = 0; + _$jscoverage['plugins/image.js'][90] = 0; + _$jscoverage['plugins/image.js'][91] = 0; + _$jscoverage['plugins/image.js'][92] = 0; + _$jscoverage['plugins/image.js'][95] = 0; + _$jscoverage['plugins/image.js'][96] = 0; + _$jscoverage['plugins/image.js'][98] = 0; + _$jscoverage['plugins/image.js'][99] = 0; + _$jscoverage['plugins/image.js'][100] = 0; + _$jscoverage['plugins/image.js'][101] = 0; + _$jscoverage['plugins/image.js'][103] = 0; + _$jscoverage['plugins/image.js'][105] = 0; + _$jscoverage['plugins/image.js'][106] = 0; + _$jscoverage['plugins/image.js'][107] = 0; + _$jscoverage['plugins/image.js'][108] = 0; + _$jscoverage['plugins/image.js'][110] = 0; + _$jscoverage['plugins/image.js'][111] = 0; + _$jscoverage['plugins/image.js'][112] = 0; + _$jscoverage['plugins/image.js'][117] = 0; + _$jscoverage['plugins/image.js'][124] = 0; + _$jscoverage['plugins/image.js'][126] = 0; + _$jscoverage['plugins/image.js'][127] = 0; + _$jscoverage['plugins/image.js'][129] = 0; + _$jscoverage['plugins/image.js'][130] = 0; + _$jscoverage['plugins/image.js'][131] = 0; + _$jscoverage['plugins/image.js'][132] = 0; + _$jscoverage['plugins/image.js'][133] = 0; + _$jscoverage['plugins/image.js'][135] = 0; + _$jscoverage['plugins/image.js'][141] = 0; + _$jscoverage['plugins/image.js'][146] = 0; + _$jscoverage['plugins/image.js'][149] = 0; + _$jscoverage['plugins/image.js'][151] = 0; + _$jscoverage['plugins/image.js'][152] = 0; + _$jscoverage['plugins/image.js'][153] = 0; + _$jscoverage['plugins/image.js'][155] = 0; + _$jscoverage['plugins/image.js'][173] = 0; + _$jscoverage['plugins/image.js'][176] = 0; + _$jscoverage['plugins/image.js'][177] = 0; + _$jscoverage['plugins/image.js'][178] = 0; + _$jscoverage['plugins/image.js'][180] = 0; + _$jscoverage['plugins/image.js'][183] = 0; + _$jscoverage['plugins/image.js'][184] = 0; + _$jscoverage['plugins/image.js'][185] = 0; + _$jscoverage['plugins/image.js'][186] = 0; + _$jscoverage['plugins/image.js'][190] = 0; + _$jscoverage['plugins/image.js'][191] = 0; + _$jscoverage['plugins/image.js'][192] = 0; + _$jscoverage['plugins/image.js'][193] = 0; + _$jscoverage['plugins/image.js'][194] = 0; + _$jscoverage['plugins/image.js'][198] = 0; + _$jscoverage['plugins/image.js'][199] = 0; + _$jscoverage['plugins/image.js'][200] = 0; + _$jscoverage['plugins/image.js'][201] = 0; + _$jscoverage['plugins/image.js'][210] = 0; + _$jscoverage['plugins/image.js'][211] = 0; + _$jscoverage['plugins/image.js'][213] = 0; + _$jscoverage['plugins/image.js'][216] = 0; + _$jscoverage['plugins/image.js'][217] = 0; + _$jscoverage['plugins/image.js'][223] = 0; + _$jscoverage['plugins/image.js'][227] = 0; +} +_$jscoverage['plugins/image.js'].source = ["/**"," * 图片插入、排版插件"," * @file"," * @since 1.2.6.1"," */","","/**"," * 对图片居左居中居右排版"," * @command imagefloat"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param { String } align 对齐方式,可传left、right、none、center"," * @example"," * ```javascript"," * editor.execCommand( 'imagefloat', 'center' );"," * ```"," */","","/**"," * 如果选区所在位置是图片区域"," * @command imagefloat"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { String } 返回图片对齐方式"," * @example"," * ```javascript"," * editor.queryCommandValue( 'imagefloat' );"," * ```"," */","/**"," * 返回当前选区位置是否是图片"," * @command imagefloat"," * @method queryCommandState"," * @param { String } cmd 命令字符串"," * @return { int } 0为是,-1为不是"," * @example"," * ```javascript"," * editor.queryCommandState( 'imagefloat' );"," * ```"," */","UE.commands['imagefloat'] = {"," execCommand:function (cmd, align) {"," var me = this,"," range = me.selection.getRange();"," if (!range.collapsed) {"," var img = range.getClosedNode();"," if (img && img.tagName == 'IMG') {"," switch (align) {"," case 'left':"," case 'right':"," case 'none':"," var pN = img.parentNode, tmpNode, pre, next;"," while (dtd.$inline[pN.tagName] || pN.tagName == 'A') {"," pN = pN.parentNode;"," }"," tmpNode = pN;"," if (tmpNode.tagName == 'P' && domUtils.getStyle(tmpNode, 'text-align') == 'center') {"," if (!domUtils.isBody(tmpNode) && domUtils.getChildCount(tmpNode, function (node) {"," return !domUtils.isBr(node) && !domUtils.isWhitespace(node);"," }) == 1) {"," pre = tmpNode.previousSibling;"," next = tmpNode.nextSibling;"," if (pre && next && pre.nodeType == 1 && next.nodeType == 1 && pre.tagName == next.tagName && domUtils.isBlockElm(pre)) {"," pre.appendChild(tmpNode.firstChild);"," while (next.firstChild) {"," pre.appendChild(next.firstChild);"," }"," domUtils.remove(tmpNode);"," domUtils.remove(next);"," } else {"," domUtils.setStyle(tmpNode, 'text-align', '');"," }","",""," }",""," range.selectNode(img).select();"," }"," domUtils.setStyle(img, 'float', align == 'none' ? '' : align);"," if(align == 'none'){"," domUtils.removeAttributes(img,'align');"," }",""," break;"," case 'center':"," if (me.queryCommandValue('imagefloat') != 'center') {"," pN = img.parentNode;"," domUtils.setStyle(img, 'float', '');"," domUtils.removeAttributes(img,'align');"," tmpNode = img;"," while (pN && domUtils.getChildCount(pN, function (node) {"," return !domUtils.isBr(node) && !domUtils.isWhitespace(node);"," }) == 1"," && (dtd.$inline[pN.tagName] || pN.tagName == 'A')) {"," tmpNode = pN;"," pN = pN.parentNode;"," }"," range.setStartBefore(tmpNode).setCursor(false);"," pN = me.document.createElement('div');"," pN.appendChild(tmpNode);"," domUtils.setStyle(tmpNode, 'float', '');",""," me.execCommand('insertHtml', '<p id=\"_img_parent_tmp\" style=\"text-align:center\">' + pN.innerHTML + '</p>');",""," tmpNode = me.document.getElementById('_img_parent_tmp');"," tmpNode.removeAttribute('id');"," tmpNode = tmpNode.firstChild;"," range.selectNode(tmpNode).select();"," //去掉后边多余的元素"," next = tmpNode.parentNode.nextSibling;"," if (next && domUtils.isEmptyNode(next)) {"," domUtils.remove(next);"," }",""," }",""," break;"," }",""," }"," }"," },"," queryCommandValue:function () {"," var range = this.selection.getRange(),"," startNode, floatStyle;"," if (range.collapsed) {"," return 'none';"," }"," startNode = range.getClosedNode();"," if (startNode && startNode.nodeType == 1 && startNode.tagName == 'IMG') {"," floatStyle = startNode.getAttribute('align')||domUtils.getComputedStyle(startNode, 'float');"," if (floatStyle == 'none') {"," floatStyle = domUtils.getComputedStyle(startNode.parentNode, 'text-align') == 'center' ? 'center' : floatStyle;"," }"," return {"," left:1,"," right:1,"," center:1"," }[floatStyle] ? floatStyle : 'none';"," }"," return 'none';","",""," },"," queryCommandState:function () {"," var range = this.selection.getRange(),"," startNode;",""," if (range.collapsed) return -1;",""," startNode = range.getClosedNode();"," if (startNode && startNode.nodeType == 1 && startNode.tagName == 'IMG') {"," return 0;"," }"," return -1;"," }","};","/**"," * 向编辑器插入图片"," * @command insertimage"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param { Object } opt 属性键值对,这些属性都将被复制到当前插入图片"," * @example"," * ```javascript"," * editor.execCommand( 'insertimage', {"," * src:'a/b/c.jpg',"," * width:'100',"," * height:'100'"," * } );"," * ```"," */","UE.commands['insertimage'] = {"," execCommand:function (cmd, opt) {",""," opt = utils.isArray(opt) ? opt : [opt];"," if (!opt.length) {"," return;"," }"," var me = this,"," range = me.selection.getRange(),"," img = range.getClosedNode();"," if (img && /img/i.test(img.tagName) && img.className != \"edui-faked-video\" && !img.getAttribute(\"word_img\")) {"," var first = opt.shift();"," var floatStyle = first['floatStyle'];"," delete first['floatStyle'];","//// img.style.border = (first.border||0) +\"px solid #000\";","//// img.style.margin = (first.margin||0) +\"px\";","// img.style.cssText += ';margin:' + (first.margin||0) +\"px;\" + 'border:' + (first.border||0) +\"px solid #000\";"," domUtils.setAttributes(img, first);"," me.execCommand('imagefloat', floatStyle);"," if (opt.length > 0) {"," range.setStartAfter(img).setCursor(false, true);"," me.execCommand('insertimage', opt);"," }",""," } else {"," var html = [], str = '', ci;"," ci = opt[0];"," if (opt.length == 1) {"," str = '<img src=\"' + ci.src + '\" ' + (ci._src ? ' _src=\"' + ci._src + '\" ' : '') +"," (ci.width ? 'width=\"' + ci.width + '\" ' : '') +"," (ci.height ? ' height=\"' + ci.height + '\" ' : '') +"," (ci['floatStyle'] == 'left' || ci['floatStyle'] == 'right' ? ' style=\"float:' + ci['floatStyle'] + ';\"' : '') +"," (ci.title && ci.title != \"\" ? ' title=\"' + ci.title + '\"' : '') +"," (ci.border && ci.border != \"0\" ? ' border=\"' + ci.border + '\"' : '') +"," (ci.alt && ci.alt != \"\" ? ' alt=\"' + ci.alt + '\"' : '') +"," (ci.hspace && ci.hspace != \"0\" ? ' hspace = \"' + ci.hspace + '\"' : '') +"," (ci.vspace && ci.vspace != \"0\" ? ' vspace = \"' + ci.vspace + '\"' : '') + '/>';"," if (ci['floatStyle'] == 'center') {"," str = '<p style=\"text-align: center\">' + str + '</p>';"," }"," html.push(str);",""," } else {"," for (var i = 0; ci = opt[i++];) {"," str = '<p ' + (ci['floatStyle'] == 'center' ? 'style=\"text-align: center\" ' : '') + '><img src=\"' + ci.src + '\" ' +"," (ci.width ? 'width=\"' + ci.width + '\" ' : '') + (ci._src ? ' _src=\"' + ci._src + '\" ' : '') +"," (ci.height ? ' height=\"' + ci.height + '\" ' : '') +"," ' style=\"' + (ci['floatStyle'] && ci['floatStyle'] != 'center' ? 'float:' + ci['floatStyle'] + ';' : '') +"," (ci.border || '') + '\" ' +"," (ci.title ? ' title=\"' + ci.title + '\"' : '') + ' /></p>';"," html.push(str);"," }"," }",""," me.execCommand('insertHtml', html.join(''));"," }"," }","};"]; +_$jscoverage['plugins/image.js'][41]++; +UE.commands.imagefloat = {execCommand: (function (cmd, align) { + _$jscoverage['plugins/image.js'][43]++; + var me = this, range = me.selection.getRange(); + _$jscoverage['plugins/image.js'][45]++; + if ((! range.collapsed)) { + _$jscoverage['plugins/image.js'][46]++; + var img = range.getClosedNode(); + _$jscoverage['plugins/image.js'][47]++; + if ((img && (img.tagName == "IMG"))) { + _$jscoverage['plugins/image.js'][48]++; + switch (align) { + case "left": + case "right": + case "none": + _$jscoverage['plugins/image.js'][52]++; + var pN = img.parentNode, tmpNode, pre, next; + _$jscoverage['plugins/image.js'][53]++; + while ((dtd.$inline[pN.tagName] || (pN.tagName == "A"))) { + _$jscoverage['plugins/image.js'][54]++; + pN = pN.parentNode; +} + _$jscoverage['plugins/image.js'][56]++; + tmpNode = pN; + _$jscoverage['plugins/image.js'][57]++; + if (((tmpNode.tagName == "P") && (domUtils.getStyle(tmpNode, "text-align") == "center"))) { + _$jscoverage['plugins/image.js'][58]++; + if (((! domUtils.isBody(tmpNode)) && (domUtils.getChildCount(tmpNode, (function (node) { + _$jscoverage['plugins/image.js'][59]++; + return ((! domUtils.isBr(node)) && (! domUtils.isWhitespace(node))); +})) == 1))) { + _$jscoverage['plugins/image.js'][61]++; + pre = tmpNode.previousSibling; + _$jscoverage['plugins/image.js'][62]++; + next = tmpNode.nextSibling; + _$jscoverage['plugins/image.js'][63]++; + if ((pre && next && (pre.nodeType == 1) && (next.nodeType == 1) && (pre.tagName == next.tagName) && domUtils.isBlockElm(pre))) { + _$jscoverage['plugins/image.js'][64]++; + pre.appendChild(tmpNode.firstChild); + _$jscoverage['plugins/image.js'][65]++; + while (next.firstChild) { + _$jscoverage['plugins/image.js'][66]++; + pre.appendChild(next.firstChild); +} + _$jscoverage['plugins/image.js'][68]++; + domUtils.remove(tmpNode); + _$jscoverage['plugins/image.js'][69]++; + domUtils.remove(next); + } + else { + _$jscoverage['plugins/image.js'][71]++; + domUtils.setStyle(tmpNode, "text-align", ""); + } + } + _$jscoverage['plugins/image.js'][77]++; + range.selectNode(img).select(); + } + _$jscoverage['plugins/image.js'][79]++; + domUtils.setStyle(img, "float", ((align == "none")? "": align)); + _$jscoverage['plugins/image.js'][80]++; + if ((align == "none")) { + _$jscoverage['plugins/image.js'][81]++; + domUtils.removeAttributes(img, "align"); + } + _$jscoverage['plugins/image.js'][84]++; + break; + case "center": + _$jscoverage['plugins/image.js'][86]++; + if ((me.queryCommandValue("imagefloat") != "center")) { + _$jscoverage['plugins/image.js'][87]++; + pN = img.parentNode; + _$jscoverage['plugins/image.js'][88]++; + domUtils.setStyle(img, "float", ""); + _$jscoverage['plugins/image.js'][89]++; + domUtils.removeAttributes(img, "align"); + _$jscoverage['plugins/image.js'][90]++; + tmpNode = img; + _$jscoverage['plugins/image.js'][91]++; + while ((pN && (domUtils.getChildCount(pN, (function (node) { + _$jscoverage['plugins/image.js'][92]++; + return ((! domUtils.isBr(node)) && (! domUtils.isWhitespace(node))); +})) == 1) && (dtd.$inline[pN.tagName] || (pN.tagName == "A")))) { + _$jscoverage['plugins/image.js'][95]++; + tmpNode = pN; + _$jscoverage['plugins/image.js'][96]++; + pN = pN.parentNode; +} + _$jscoverage['plugins/image.js'][98]++; + range.setStartBefore(tmpNode).setCursor(false); + _$jscoverage['plugins/image.js'][99]++; + pN = me.document.createElement("div"); + _$jscoverage['plugins/image.js'][100]++; + pN.appendChild(tmpNode); + _$jscoverage['plugins/image.js'][101]++; + domUtils.setStyle(tmpNode, "float", ""); + _$jscoverage['plugins/image.js'][103]++; + me.execCommand("insertHtml", ("

    " + pN.innerHTML + "

    ")); + _$jscoverage['plugins/image.js'][105]++; + tmpNode = me.document.getElementById("_img_parent_tmp"); + _$jscoverage['plugins/image.js'][106]++; + tmpNode.removeAttribute("id"); + _$jscoverage['plugins/image.js'][107]++; + tmpNode = tmpNode.firstChild; + _$jscoverage['plugins/image.js'][108]++; + range.selectNode(tmpNode).select(); + _$jscoverage['plugins/image.js'][110]++; + next = tmpNode.parentNode.nextSibling; + _$jscoverage['plugins/image.js'][111]++; + if ((next && domUtils.isEmptyNode(next))) { + _$jscoverage['plugins/image.js'][112]++; + domUtils.remove(next); + } + } + _$jscoverage['plugins/image.js'][117]++; + break; + } + } + } +}), queryCommandValue: (function () { + _$jscoverage['plugins/image.js'][124]++; + var range = this.selection.getRange(), startNode, floatStyle; + _$jscoverage['plugins/image.js'][126]++; + if (range.collapsed) { + _$jscoverage['plugins/image.js'][127]++; + return "none"; + } + _$jscoverage['plugins/image.js'][129]++; + startNode = range.getClosedNode(); + _$jscoverage['plugins/image.js'][130]++; + if ((startNode && (startNode.nodeType == 1) && (startNode.tagName == "IMG"))) { + _$jscoverage['plugins/image.js'][131]++; + floatStyle = (startNode.getAttribute("align") || domUtils.getComputedStyle(startNode, "float")); + _$jscoverage['plugins/image.js'][132]++; + if ((floatStyle == "none")) { + _$jscoverage['plugins/image.js'][133]++; + floatStyle = ((domUtils.getComputedStyle(startNode.parentNode, "text-align") == "center")? "center": floatStyle); + } + _$jscoverage['plugins/image.js'][135]++; + return ({left: 1, right: 1, center: 1}[floatStyle]? floatStyle: "none"); + } + _$jscoverage['plugins/image.js'][141]++; + return "none"; +}), queryCommandState: (function () { + _$jscoverage['plugins/image.js'][146]++; + var range = this.selection.getRange(), startNode; + _$jscoverage['plugins/image.js'][149]++; + if (range.collapsed) { + _$jscoverage['plugins/image.js'][149]++; + return -1; + } + _$jscoverage['plugins/image.js'][151]++; + startNode = range.getClosedNode(); + _$jscoverage['plugins/image.js'][152]++; + if ((startNode && (startNode.nodeType == 1) && (startNode.tagName == "IMG"))) { + _$jscoverage['plugins/image.js'][153]++; + return 0; + } + _$jscoverage['plugins/image.js'][155]++; + return -1; +})}; +_$jscoverage['plugins/image.js'][173]++; +UE.commands.insertimage = {execCommand: (function (cmd, opt) { + _$jscoverage['plugins/image.js'][176]++; + opt = (utils.isArray(opt)? opt: [opt]); + _$jscoverage['plugins/image.js'][177]++; + if ((! opt.length)) { + _$jscoverage['plugins/image.js'][178]++; + return; + } + _$jscoverage['plugins/image.js'][180]++; + var me = this, range = me.selection.getRange(), img = range.getClosedNode(); + _$jscoverage['plugins/image.js'][183]++; + if ((img && /img/i.test(img.tagName) && (img.className != "edui-faked-video") && (! img.getAttribute("word_img")))) { + _$jscoverage['plugins/image.js'][184]++; + var first = opt.shift(); + _$jscoverage['plugins/image.js'][185]++; + var floatStyle = first.floatStyle; + _$jscoverage['plugins/image.js'][186]++; + (delete first.floatStyle); + _$jscoverage['plugins/image.js'][190]++; + domUtils.setAttributes(img, first); + _$jscoverage['plugins/image.js'][191]++; + me.execCommand("imagefloat", floatStyle); + _$jscoverage['plugins/image.js'][192]++; + if ((opt.length > 0)) { + _$jscoverage['plugins/image.js'][193]++; + range.setStartAfter(img).setCursor(false, true); + _$jscoverage['plugins/image.js'][194]++; + me.execCommand("insertimage", opt); + } + } + else { + _$jscoverage['plugins/image.js'][198]++; + var html = [], str = "", ci; + _$jscoverage['plugins/image.js'][199]++; + ci = opt[0]; + _$jscoverage['plugins/image.js'][200]++; + if ((opt.length == 1)) { + _$jscoverage['plugins/image.js'][201]++; + str = ("\"""); + _$jscoverage['plugins/image.js'][210]++; + if ((ci.floatStyle == "center")) { + _$jscoverage['plugins/image.js'][211]++; + str = ("

    " + str + "

    "); + } + _$jscoverage['plugins/image.js'][213]++; + html.push(str); + } + else { + _$jscoverage['plugins/image.js'][216]++; + for (var i = 0; (ci = opt[(i++)]);) { + _$jscoverage['plugins/image.js'][217]++; + str = ("

    "); + _$jscoverage['plugins/image.js'][223]++; + html.push(str); +} + } + _$jscoverage['plugins/image.js'][227]++; + me.execCommand("insertHtml", html.join("")); + } +})}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/indent.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/indent.js new file mode 100644 index 000000000..83ae81e5c --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/indent.js @@ -0,0 +1,60 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/indent.js']) { + _$jscoverage['plugins/indent.js'] = []; + _$jscoverage['plugins/indent.js'][30] = 0; + _$jscoverage['plugins/indent.js'][32] = 0; + _$jscoverage['plugins/indent.js'][33] = 0; + _$jscoverage['plugins/indent.js'][36] = 0; + _$jscoverage['plugins/indent.js'][37] = 0; +} +_$jscoverage['plugins/indent.js'].source = ["/**"," * 缩进"," * @file"," * @since 1.2.6.1"," */","","/**"," * 给选区内文本添加缩进"," * @command indent"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'indent' );"," * ```"," */","","/**"," * 返回当前选区位置是否有缩进"," * @command indent"," * @method queryCommandState"," * @param { String } cmd 命令字符串"," * @return { int } 0为不是,1为是"," * @example"," * ```javascript"," * editor.queryCommandState( 'indent' );"," * ```"," */","","UE.commands['indent'] = {"," execCommand : function() {"," var me = this,value = me.queryCommandState(\"indent\") ? \"0em\" : (me.options.indentValue || '2em');"," me.execCommand('Paragraph','p',{style:'text-indent:'+ value});"," },"," queryCommandState : function() {"," var pN = domUtils.filterNodeList(this.selection.getStartElementPath(),'p h1 h2 h3 h4 h5 h6');"," return pN && pN.style.textIndent && parseInt(pN.style.textIndent) ? 1 : 0;"," }","","};"]; +_$jscoverage['plugins/indent.js'][30]++; +UE.commands.indent = {execCommand: (function () { + _$jscoverage['plugins/indent.js'][32]++; + var me = this, value = (me.queryCommandState("indent")? "0em": (me.options.indentValue || "2em")); + _$jscoverage['plugins/indent.js'][33]++; + me.execCommand("Paragraph", "p", {style: ("text-indent:" + value)}); +}), queryCommandState: (function () { + _$jscoverage['plugins/indent.js'][36]++; + var pN = domUtils.filterNodeList(this.selection.getStartElementPath(), "p h1 h2 h3 h4 h5 h6"); + _$jscoverage['plugins/indent.js'][37]++; + return ((pN && pN.style.textIndent && parseInt(pN.style.textIndent))? 1: 0); +})}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/insertcode.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/insertcode.js new file mode 100644 index 000000000..a870678b8 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/insertcode.js @@ -0,0 +1,1066 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/insertcode.js']) { + _$jscoverage['plugins/insertcode.js'] = []; + _$jscoverage['plugins/insertcode.js'][7] = 0; + _$jscoverage['plugins/insertcode.js'][8] = 0; + _$jscoverage['plugins/insertcode.js'][9] = 0; + _$jscoverage['plugins/insertcode.js'][10] = 0; + _$jscoverage['plugins/insertcode.js'][13] = 0; + _$jscoverage['plugins/insertcode.js'][63] = 0; + _$jscoverage['plugins/insertcode.js'][65] = 0; + _$jscoverage['plugins/insertcode.js'][68] = 0; + _$jscoverage['plugins/insertcode.js'][69] = 0; + _$jscoverage['plugins/insertcode.js'][71] = 0; + _$jscoverage['plugins/insertcode.js'][72] = 0; + _$jscoverage['plugins/insertcode.js'][73] = 0; + _$jscoverage['plugins/insertcode.js'][75] = 0; + _$jscoverage['plugins/insertcode.js'][76] = 0; + _$jscoverage['plugins/insertcode.js'][77] = 0; + _$jscoverage['plugins/insertcode.js'][79] = 0; + _$jscoverage['plugins/insertcode.js'][80] = 0; + _$jscoverage['plugins/insertcode.js'][82] = 0; + _$jscoverage['plugins/insertcode.js'][83] = 0; + _$jscoverage['plugins/insertcode.js'][84] = 0; + _$jscoverage['plugins/insertcode.js'][85] = 0; + _$jscoverage['plugins/insertcode.js'][86] = 0; + _$jscoverage['plugins/insertcode.js'][87] = 0; + _$jscoverage['plugins/insertcode.js'][88] = 0; + _$jscoverage['plugins/insertcode.js'][89] = 0; + _$jscoverage['plugins/insertcode.js'][90] = 0; + _$jscoverage['plugins/insertcode.js'][91] = 0; + _$jscoverage['plugins/insertcode.js'][94] = 0; + _$jscoverage['plugins/insertcode.js'][97] = 0; + _$jscoverage['plugins/insertcode.js'][98] = 0; + _$jscoverage['plugins/insertcode.js'][102] = 0; + _$jscoverage['plugins/insertcode.js'][104] = 0; + _$jscoverage['plugins/insertcode.js'][105] = 0; + _$jscoverage['plugins/insertcode.js'][108] = 0; + _$jscoverage['plugins/insertcode.js'][110] = 0; + _$jscoverage['plugins/insertcode.js'][111] = 0; + _$jscoverage['plugins/insertcode.js'][112] = 0; + _$jscoverage['plugins/insertcode.js'][113] = 0; + _$jscoverage['plugins/insertcode.js'][114] = 0; + _$jscoverage['plugins/insertcode.js'][115] = 0; + _$jscoverage['plugins/insertcode.js'][116] = 0; + _$jscoverage['plugins/insertcode.js'][117] = 0; + _$jscoverage['plugins/insertcode.js'][118] = 0; + _$jscoverage['plugins/insertcode.js'][119] = 0; + _$jscoverage['plugins/insertcode.js'][122] = 0; + _$jscoverage['plugins/insertcode.js'][125] = 0; + _$jscoverage['plugins/insertcode.js'][126] = 0; + _$jscoverage['plugins/insertcode.js'][130] = 0; + _$jscoverage['plugins/insertcode.js'][132] = 0; + _$jscoverage['plugins/insertcode.js'][133] = 0; + _$jscoverage['plugins/insertcode.js'][137] = 0; + _$jscoverage['plugins/insertcode.js'][138] = 0; + _$jscoverage['plugins/insertcode.js'][139] = 0; + _$jscoverage['plugins/insertcode.js'][140] = 0; + _$jscoverage['plugins/insertcode.js'][141] = 0; + _$jscoverage['plugins/insertcode.js'][149] = 0; + _$jscoverage['plugins/insertcode.js'][151] = 0; + _$jscoverage['plugins/insertcode.js'][152] = 0; + _$jscoverage['plugins/insertcode.js'][153] = 0; + _$jscoverage['plugins/insertcode.js'][155] = 0; + _$jscoverage['plugins/insertcode.js'][157] = 0; + _$jscoverage['plugins/insertcode.js'][159] = 0; + _$jscoverage['plugins/insertcode.js'][160] = 0; + _$jscoverage['plugins/insertcode.js'][161] = 0; + _$jscoverage['plugins/insertcode.js'][163] = 0; + _$jscoverage['plugins/insertcode.js'][171] = 0; + _$jscoverage['plugins/insertcode.js'][172] = 0; + _$jscoverage['plugins/insertcode.js'][173] = 0; + _$jscoverage['plugins/insertcode.js'][174] = 0; + _$jscoverage['plugins/insertcode.js'][175] = 0; + _$jscoverage['plugins/insertcode.js'][176] = 0; + _$jscoverage['plugins/insertcode.js'][177] = 0; + _$jscoverage['plugins/insertcode.js'][180] = 0; + _$jscoverage['plugins/insertcode.js'][184] = 0; + _$jscoverage['plugins/insertcode.js'][185] = 0; + _$jscoverage['plugins/insertcode.js'][186] = 0; + _$jscoverage['plugins/insertcode.js'][187] = 0; + _$jscoverage['plugins/insertcode.js'][188] = 0; + _$jscoverage['plugins/insertcode.js'][189] = 0; + _$jscoverage['plugins/insertcode.js'][190] = 0; + _$jscoverage['plugins/insertcode.js'][191] = 0; + _$jscoverage['plugins/insertcode.js'][193] = 0; + _$jscoverage['plugins/insertcode.js'][195] = 0; + _$jscoverage['plugins/insertcode.js'][196] = 0; + _$jscoverage['plugins/insertcode.js'][197] = 0; + _$jscoverage['plugins/insertcode.js'][198] = 0; + _$jscoverage['plugins/insertcode.js'][199] = 0; + _$jscoverage['plugins/insertcode.js'][200] = 0; + _$jscoverage['plugins/insertcode.js'][201] = 0; + _$jscoverage['plugins/insertcode.js'][203] = 0; + _$jscoverage['plugins/insertcode.js'][207] = 0; + _$jscoverage['plugins/insertcode.js'][208] = 0; + _$jscoverage['plugins/insertcode.js'][209] = 0; + _$jscoverage['plugins/insertcode.js'][210] = 0; + _$jscoverage['plugins/insertcode.js'][211] = 0; + _$jscoverage['plugins/insertcode.js'][214] = 0; + _$jscoverage['plugins/insertcode.js'][216] = 0; + _$jscoverage['plugins/insertcode.js'][217] = 0; + _$jscoverage['plugins/insertcode.js'][219] = 0; + _$jscoverage['plugins/insertcode.js'][226] = 0; + _$jscoverage['plugins/insertcode.js'][230] = 0; + _$jscoverage['plugins/insertcode.js'][247] = 0; + _$jscoverage['plugins/insertcode.js'][248] = 0; + _$jscoverage['plugins/insertcode.js'][249] = 0; + _$jscoverage['plugins/insertcode.js'][251] = 0; + _$jscoverage['plugins/insertcode.js'][252] = 0; + _$jscoverage['plugins/insertcode.js'][254] = 0; + _$jscoverage['plugins/insertcode.js'][256] = 0; + _$jscoverage['plugins/insertcode.js'][257] = 0; + _$jscoverage['plugins/insertcode.js'][258] = 0; + _$jscoverage['plugins/insertcode.js'][259] = 0; + _$jscoverage['plugins/insertcode.js'][260] = 0; + _$jscoverage['plugins/insertcode.js'][261] = 0; + _$jscoverage['plugins/insertcode.js'][262] = 0; + _$jscoverage['plugins/insertcode.js'][264] = 0; + _$jscoverage['plugins/insertcode.js'][265] = 0; + _$jscoverage['plugins/insertcode.js'][266] = 0; + _$jscoverage['plugins/insertcode.js'][267] = 0; + _$jscoverage['plugins/insertcode.js'][268] = 0; + _$jscoverage['plugins/insertcode.js'][269] = 0; + _$jscoverage['plugins/insertcode.js'][271] = 0; + _$jscoverage['plugins/insertcode.js'][273] = 0; + _$jscoverage['plugins/insertcode.js'][274] = 0; + _$jscoverage['plugins/insertcode.js'][275] = 0; + _$jscoverage['plugins/insertcode.js'][276] = 0; + _$jscoverage['plugins/insertcode.js'][277] = 0; + _$jscoverage['plugins/insertcode.js'][278] = 0; + _$jscoverage['plugins/insertcode.js'][279] = 0; + _$jscoverage['plugins/insertcode.js'][280] = 0; + _$jscoverage['plugins/insertcode.js'][283] = 0; + _$jscoverage['plugins/insertcode.js'][284] = 0; + _$jscoverage['plugins/insertcode.js'][285] = 0; + _$jscoverage['plugins/insertcode.js'][286] = 0; + _$jscoverage['plugins/insertcode.js'][287] = 0; + _$jscoverage['plugins/insertcode.js'][289] = 0; + _$jscoverage['plugins/insertcode.js'][290] = 0; + _$jscoverage['plugins/insertcode.js'][291] = 0; + _$jscoverage['plugins/insertcode.js'][292] = 0; + _$jscoverage['plugins/insertcode.js'][296] = 0; + _$jscoverage['plugins/insertcode.js'][297] = 0; + _$jscoverage['plugins/insertcode.js'][298] = 0; + _$jscoverage['plugins/insertcode.js'][301] = 0; + _$jscoverage['plugins/insertcode.js'][303] = 0; + _$jscoverage['plugins/insertcode.js'][305] = 0; + _$jscoverage['plugins/insertcode.js'][306] = 0; + _$jscoverage['plugins/insertcode.js'][307] = 0; + _$jscoverage['plugins/insertcode.js'][308] = 0; + _$jscoverage['plugins/insertcode.js'][309] = 0; + _$jscoverage['plugins/insertcode.js'][310] = 0; + _$jscoverage['plugins/insertcode.js'][311] = 0; + _$jscoverage['plugins/insertcode.js'][312] = 0; + _$jscoverage['plugins/insertcode.js'][315] = 0; + _$jscoverage['plugins/insertcode.js'][316] = 0; + _$jscoverage['plugins/insertcode.js'][317] = 0; + _$jscoverage['plugins/insertcode.js'][318] = 0; + _$jscoverage['plugins/insertcode.js'][319] = 0; + _$jscoverage['plugins/insertcode.js'][321] = 0; + _$jscoverage['plugins/insertcode.js'][325] = 0; + _$jscoverage['plugins/insertcode.js'][326] = 0; + _$jscoverage['plugins/insertcode.js'][327] = 0; + _$jscoverage['plugins/insertcode.js'][328] = 0; + _$jscoverage['plugins/insertcode.js'][329] = 0; + _$jscoverage['plugins/insertcode.js'][330] = 0; + _$jscoverage['plugins/insertcode.js'][331] = 0; + _$jscoverage['plugins/insertcode.js'][332] = 0; + _$jscoverage['plugins/insertcode.js'][333] = 0; + _$jscoverage['plugins/insertcode.js'][334] = 0; + _$jscoverage['plugins/insertcode.js'][335] = 0; + _$jscoverage['plugins/insertcode.js'][336] = 0; + _$jscoverage['plugins/insertcode.js'][339] = 0; + _$jscoverage['plugins/insertcode.js'][340] = 0; + _$jscoverage['plugins/insertcode.js'][341] = 0; + _$jscoverage['plugins/insertcode.js'][342] = 0; + _$jscoverage['plugins/insertcode.js'][343] = 0; + _$jscoverage['plugins/insertcode.js'][345] = 0; + _$jscoverage['plugins/insertcode.js'][346] = 0; + _$jscoverage['plugins/insertcode.js'][347] = 0; + _$jscoverage['plugins/insertcode.js'][348] = 0; + _$jscoverage['plugins/insertcode.js'][353] = 0; + _$jscoverage['plugins/insertcode.js'][354] = 0; + _$jscoverage['plugins/insertcode.js'][356] = 0; + _$jscoverage['plugins/insertcode.js'][361] = 0; + _$jscoverage['plugins/insertcode.js'][362] = 0; + _$jscoverage['plugins/insertcode.js'][368] = 0; + _$jscoverage['plugins/insertcode.js'][369] = 0; + _$jscoverage['plugins/insertcode.js'][370] = 0; + _$jscoverage['plugins/insertcode.js'][371] = 0; + _$jscoverage['plugins/insertcode.js'][372] = 0; + _$jscoverage['plugins/insertcode.js'][373] = 0; + _$jscoverage['plugins/insertcode.js'][436] = 0; + _$jscoverage['plugins/insertcode.js'][437] = 0; + _$jscoverage['plugins/insertcode.js'][438] = 0; + _$jscoverage['plugins/insertcode.js'][440] = 0; + _$jscoverage['plugins/insertcode.js'][441] = 0; + _$jscoverage['plugins/insertcode.js'][442] = 0; + _$jscoverage['plugins/insertcode.js'][444] = 0; + _$jscoverage['plugins/insertcode.js'][446] = 0; + _$jscoverage['plugins/insertcode.js'][447] = 0; + _$jscoverage['plugins/insertcode.js'][449] = 0; + _$jscoverage['plugins/insertcode.js'][451] = 0; + _$jscoverage['plugins/insertcode.js'][453] = 0; + _$jscoverage['plugins/insertcode.js'][454] = 0; + _$jscoverage['plugins/insertcode.js'][455] = 0; + _$jscoverage['plugins/insertcode.js'][456] = 0; + _$jscoverage['plugins/insertcode.js'][459] = 0; + _$jscoverage['plugins/insertcode.js'][460] = 0; + _$jscoverage['plugins/insertcode.js'][461] = 0; + _$jscoverage['plugins/insertcode.js'][462] = 0; + _$jscoverage['plugins/insertcode.js'][464] = 0; + _$jscoverage['plugins/insertcode.js'][467] = 0; + _$jscoverage['plugins/insertcode.js'][469] = 0; + _$jscoverage['plugins/insertcode.js'][471] = 0; + _$jscoverage['plugins/insertcode.js'][472] = 0; + _$jscoverage['plugins/insertcode.js'][477] = 0; + _$jscoverage['plugins/insertcode.js'][478] = 0; + _$jscoverage['plugins/insertcode.js'][485] = 0; + _$jscoverage['plugins/insertcode.js'][486] = 0; + _$jscoverage['plugins/insertcode.js'][489] = 0; + _$jscoverage['plugins/insertcode.js'][490] = 0; + _$jscoverage['plugins/insertcode.js'][491] = 0; + _$jscoverage['plugins/insertcode.js'][493] = 0; + _$jscoverage['plugins/insertcode.js'][494] = 0; + _$jscoverage['plugins/insertcode.js'][496] = 0; + _$jscoverage['plugins/insertcode.js'][497] = 0; + _$jscoverage['plugins/insertcode.js'][498] = 0; + _$jscoverage['plugins/insertcode.js'][499] = 0; + _$jscoverage['plugins/insertcode.js'][500] = 0; + _$jscoverage['plugins/insertcode.js'][501] = 0; + _$jscoverage['plugins/insertcode.js'][502] = 0; + _$jscoverage['plugins/insertcode.js'][503] = 0; + _$jscoverage['plugins/insertcode.js'][504] = 0; + _$jscoverage['plugins/insertcode.js'][505] = 0; + _$jscoverage['plugins/insertcode.js'][506] = 0; + _$jscoverage['plugins/insertcode.js'][509] = 0; + _$jscoverage['plugins/insertcode.js'][512] = 0; + _$jscoverage['plugins/insertcode.js'][513] = 0; + _$jscoverage['plugins/insertcode.js'][517] = 0; + _$jscoverage['plugins/insertcode.js'][519] = 0; + _$jscoverage['plugins/insertcode.js'][520] = 0; + _$jscoverage['plugins/insertcode.js'][523] = 0; + _$jscoverage['plugins/insertcode.js'][524] = 0; + _$jscoverage['plugins/insertcode.js'][526] = 0; + _$jscoverage['plugins/insertcode.js'][528] = 0; + _$jscoverage['plugins/insertcode.js'][529] = 0; + _$jscoverage['plugins/insertcode.js'][530] = 0; + _$jscoverage['plugins/insertcode.js'][531] = 0; + _$jscoverage['plugins/insertcode.js'][532] = 0; + _$jscoverage['plugins/insertcode.js'][533] = 0; + _$jscoverage['plugins/insertcode.js'][534] = 0; + _$jscoverage['plugins/insertcode.js'][535] = 0; + _$jscoverage['plugins/insertcode.js'][537] = 0; + _$jscoverage['plugins/insertcode.js'][538] = 0; + _$jscoverage['plugins/insertcode.js'][539] = 0; + _$jscoverage['plugins/insertcode.js'][543] = 0; + _$jscoverage['plugins/insertcode.js'][547] = 0; + _$jscoverage['plugins/insertcode.js'][548] = 0; + _$jscoverage['plugins/insertcode.js'][552] = 0; + _$jscoverage['plugins/insertcode.js'][554] = 0; + _$jscoverage['plugins/insertcode.js'][555] = 0; + _$jscoverage['plugins/insertcode.js'][560] = 0; + _$jscoverage['plugins/insertcode.js'][564] = 0; + _$jscoverage['plugins/insertcode.js'][568] = 0; + _$jscoverage['plugins/insertcode.js'][569] = 0; + _$jscoverage['plugins/insertcode.js'][570] = 0; + _$jscoverage['plugins/insertcode.js'][571] = 0; + _$jscoverage['plugins/insertcode.js'][572] = 0; + _$jscoverage['plugins/insertcode.js'][573] = 0; + _$jscoverage['plugins/insertcode.js'][574] = 0; + _$jscoverage['plugins/insertcode.js'][575] = 0; + _$jscoverage['plugins/insertcode.js'][577] = 0; + _$jscoverage['plugins/insertcode.js'][578] = 0; + _$jscoverage['plugins/insertcode.js'][579] = 0; + _$jscoverage['plugins/insertcode.js'][586] = 0; + _$jscoverage['plugins/insertcode.js'][587] = 0; + _$jscoverage['plugins/insertcode.js'][588] = 0; + _$jscoverage['plugins/insertcode.js'][589] = 0; + _$jscoverage['plugins/insertcode.js'][590] = 0; + _$jscoverage['plugins/insertcode.js'][591] = 0; + _$jscoverage['plugins/insertcode.js'][592] = 0; + _$jscoverage['plugins/insertcode.js'][593] = 0; + _$jscoverage['plugins/insertcode.js'][594] = 0; + _$jscoverage['plugins/insertcode.js'][595] = 0; + _$jscoverage['plugins/insertcode.js'][596] = 0; + _$jscoverage['plugins/insertcode.js'][597] = 0; +} +_$jscoverage['plugins/insertcode.js'].source = ["/**"," * 插入代码插件"," * @file"," * @since 1.2.6.1"," */","","UE.plugins['insertcode'] = function() {"," var me = this;"," me.ready(function(){"," utils.cssRule('pre','pre{margin:.5em 0;padding:.4em .6em;border-radius:8px;background:#f8f8f8;}',"," me.document)"," });"," me.setOpt('insertcode',{"," 'as3':'ActionScript3',"," 'bash':'Bash/Shell',"," 'cpp':'C/C++',"," 'css':'Css',"," 'cf':'CodeFunction',"," 'c#':'C#',"," 'delphi':'Delphi',"," 'diff':'Diff',"," 'erlang':'Erlang',"," 'groovy':'Groovy',"," 'html':'Html',"," 'java':'Java',"," 'jfx':'JavaFx',"," 'js':'Javascript',"," 'pl':'Perl',"," 'php':'Php',"," 'plain':'Plain Text',"," 'ps':'PowerShell',"," 'python':'Python',"," 'ruby':'Ruby',"," 'scala':'Scala',"," 'sql':'Sql',"," 'vb':'Vb',"," 'xml':'Xml'"," });",""," /**"," * 根据选择的语言,插入代码编辑块"," * @command insertcode"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param { String } lang 插入代码的语言"," * @example"," * ```javascript"," * editor.execCommand( 'insertcode', 'javascript' );"," * ```"," */",""," /**"," * 如果选区所在位置是插入插入代码区域,返回代码的语言"," * @command insertcode"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { String } 返回代码的语言"," * @example"," * ```javascript"," * editor.queryCommandValue( 'insertcode' );"," * ```"," */"," me.commands['insertcode'] = {"," execCommand : function(cmd,lang){"," var me = this,"," rng = me.selection.getRange(),"," pre = domUtils.findParentByTagName(rng.startContainer,'pre',true);"," if(pre){"," pre.className = 'brush:'+lang+';toolbar:false;';"," }else{"," var code = '';"," if(rng.collapsed){"," code = browser.ie? (browser.version > 8 ? '' : '&nbsp;'):'<br/>';"," }else{"," var frag = rng.extractContents();"," var div = me.document.createElement('div');"," div.appendChild(frag);",""," utils.each(UE.filterNode(UE.htmlparser(div.innerHTML.replace(/[\\r\\t]/g,'')),me.options.filterTxtRules).children,function(node){"," if(browser.ie && browser.version > 8){",""," if(node.type =='element'){"," if(node.tagName == 'br'){"," code += '\\n'"," }else if(!dtd.$empty[node.tagName]){"," utils.each(node.children,function(cn){"," if(cn.type =='element'){"," if(cn.tagName == 'br'){"," code += '\\n'"," }else if(!dtd.$empty[node.tagName]){"," code += cn.innerText();"," }"," }else{"," code += cn.data"," }"," })"," if(!/\\n$/.test(code)){"," code += '\\n';"," }"," }"," }else{"," code += node.data + '\\n'"," }"," if(!node.nextSibling() && /\\n$/.test(code)){"," code = code.replace(/\\n$/,'');"," }"," }else{"," if(browser.ie){",""," if(node.type =='element'){"," if(node.tagName == 'br'){"," code += '<br>'"," }else if(!dtd.$empty[node.tagName]){"," utils.each(node.children,function(cn){"," if(cn.type =='element'){"," if(cn.tagName == 'br'){"," code += '<br>'"," }else if(!dtd.$empty[node.tagName]){"," code += cn.innerText();"," }"," }else{"," code += cn.data"," }"," });"," if(!/br>$/.test(code)){"," code += '<br>';"," }"," }"," }else{"," code += node.data + '<br>'"," }"," if(!node.nextSibling() && /<br>$/.test(code)){"," code = code.replace(/<br>$/,'');"," }",""," }else{"," code += (node.type == 'element' ? (dtd.$empty[node.tagName] ? '' : node.innerText()) : node.data);"," if(!/br\\/?\\s*>$/.test(code)){"," if(!node.nextSibling())"," return;"," code += '<br>'"," }"," }",""," }",""," });"," }"," me.execCommand('inserthtml','<pre id=\"coder\"class=\"brush:'+lang+';toolbar:false\">'+code+'</pre>',true);",""," pre = me.document.getElementById('coder');"," domUtils.removeAttributes(pre,'id');"," var tmpNode = pre.previousSibling;",""," if(tmpNode && (tmpNode.nodeType == 3 && tmpNode.nodeValue.length == 1 && browser.ie && browser.version == 6 || domUtils.isEmptyBlock(tmpNode))){",""," domUtils.remove(tmpNode)"," }"," var rng = me.selection.getRange();"," if(domUtils.isEmptyBlock(pre)){"," rng.setStart(pre,0).setCursor(false,true)"," }else{"," rng.selectNodeContents(pre).select()"," }"," }","","",""," },"," queryCommandValue : function(){"," var path = this.selection.getStartElementPath();"," var lang = '';"," utils.each(path,function(node){"," if(node.nodeName =='PRE'){"," var match = node.className.match(/brush:([^;]+)/);"," lang = match && match[1] ? match[1] : '';"," return false;"," }"," });"," return lang;"," }"," };",""," me.addInputRule(function(root){"," utils.each(root.getNodesByTagName('pre'),function(pre){"," var brs = pre.getNodesByTagName('br');"," if(brs.length){"," browser.ie && browser.version > 8 && utils.each(brs,function(br){"," var txt = UE.uNode.createText('\\n');"," br.parentNode.insertBefore(txt,br);"," br.parentNode.removeChild(br);"," });"," return;"," }"," if(browser.ie && browser.version > 8)"," return;"," var code = pre.innerText().split(/\\n/);"," pre.innerHTML('');"," utils.each(code,function(c){"," if(c.length){"," pre.appendChild(UE.uNode.createText(c));"," }"," pre.appendChild(UE.uNode.createElement('br'))"," })"," })"," });"," me.addOutputRule(function(root){"," utils.each(root.getNodesByTagName('pre'),function(pre){"," var code = '';"," utils.each(pre.children,function(n){"," if(n.type == 'text'){"," //在ie下文本内容有可能末尾带有\\n要去掉"," //trace:3396"," code += n.data.replace(/[ ]/g,'&nbsp;').replace(/\\n$/,'');"," }else{"," if(n.tagName == 'br'){"," code += '\\n'"," }else{"," code += (!dtd.$empty[n.tagName] ? '' : n.innerText());"," }",""," }",""," });",""," pre.innerText(code.replace(/(&nbsp;|\\n)+$/,''))"," })"," });"," //不需要判断highlight的command列表"," me.notNeedCodeQuery ={"," help:1,"," undo:1,"," redo:1,"," source:1,"," print:1,"," searchreplace:1,"," fullscreen:1,"," preview:1,"," insertparagraph:1,"," elementpath:1,"," highlightcode:1,"," insertcode:1,"," inserthtml:1,"," selectall:1"," };"," //将queyCommamndState重置"," var orgQuery = me.queryCommandState;"," me.queryCommandState = function(cmd){"," var me = this;",""," if(!me.notNeedCodeQuery[cmd.toLowerCase()] && me.selection && me.queryCommandValue('insertcode')){"," return -1;"," }"," return UE.Editor.prototype.queryCommandState.apply(this,arguments)"," };"," me.addListener('beforeenterkeydown',function(){"," var rng = me.selection.getRange();"," var pre = domUtils.findParentByTagName(rng.startContainer,'pre',true);"," if(pre){"," me.fireEvent('saveScene');"," if(!rng.collapsed){"," rng.deleteContents();"," }"," if(!browser.ie ){"," var tmpNode = me.document.createElement('br'),pre;"," rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true);"," var next = tmpNode.nextSibling;"," if(!next){"," rng.insertNode(tmpNode.cloneNode(false));"," }else{"," rng.setStartAfter(tmpNode);"," }"," pre = tmpNode.previousSibling;"," var tmp;"," while(pre ){"," tmp = pre;"," pre = pre.previousSibling;"," if(!pre || pre.nodeName == 'BR'){"," pre = tmp;"," break;"," }"," }"," if(pre){"," var str = '';"," while(pre && pre.nodeName != 'BR' && new RegExp('^[\\\\s'+domUtils.fillChar+']*$').test(pre.nodeValue)){"," str += pre.nodeValue;"," pre = pre.nextSibling;"," }"," if(pre.nodeName != 'BR'){"," var match = pre.nodeValue.match(new RegExp('^([\\\\s'+domUtils.fillChar+']+)'));"," if(match && match[1]){"," str += match[1]"," }",""," }"," if(str){"," str = me.document.createTextNode(str);"," rng.insertNode(str).setStartAfter(str);"," }"," }"," rng.collapse(true).select(true);"," }else{"," if(browser.version > 8){",""," var txt = me.document.createTextNode('\\n');"," var start = rng.startContainer;"," if(rng.startOffset == 0){"," var preNode = start.previousSibling;"," if(preNode){"," rng.insertNode(txt);"," var fillchar = me.document.createTextNode(' ');"," rng.setStartAfter(txt).insertNode(fillchar).setStart(fillchar,0).collapse(true).select(true)"," }"," }else{"," rng.insertNode(txt).setStartAfter(txt);"," var fillchar = me.document.createTextNode(' ');"," start = rng.startContainer.childNodes[rng.startOffset];"," if(start && !/^\\n/.test(start.nodeValue)){"," rng.setStartBefore(txt)"," }"," rng.insertNode(fillchar).setStart(fillchar,0).collapse(true).select(true)"," }",""," }else{"," var tmpNode = me.document.createElement('br');"," rng.insertNode(tmpNode);"," rng.insertNode(me.document.createTextNode(domUtils.fillChar));"," rng.setStartAfter(tmpNode);"," pre = tmpNode.previousSibling;"," var tmp;"," while(pre ){"," tmp = pre;"," pre = pre.previousSibling;"," if(!pre || pre.nodeName == 'BR'){"," pre = tmp;"," break;"," }"," }"," if(pre){"," var str = '';"," while(pre && pre.nodeName != 'BR' && new RegExp('^[ '+domUtils.fillChar+']*$').test(pre.nodeValue)){"," str += pre.nodeValue;"," pre = pre.nextSibling;"," }"," if(pre.nodeName != 'BR'){"," var match = pre.nodeValue.match(new RegExp('^([ '+domUtils.fillChar+']+)'));"," if(match && match[1]){"," str += match[1]"," }",""," }",""," str = me.document.createTextNode(str);"," rng.insertNode(str).setStartAfter(str);"," }"," rng.collapse(true).select();"," }","",""," }"," me.fireEvent('saveScene');"," return true;"," }","",""," });",""," me.addListener('tabkeydown',function(cmd,evt){"," var rng = me.selection.getRange();"," var pre = domUtils.findParentByTagName(rng.startContainer,'pre',true);"," if(pre){"," me.fireEvent('saveScene');"," if(evt.shiftKey){","","// if(!rng.collapsed){","// var bk = rng.createBookmark();","// var start = bk.start.previousSibling;","// if(start === pre.firstChild){","// start.nodeValue = start.nodeValue.replace(/^\\s{4}/,'');","// }else{","// while(start){","// if(domUtils.isBr(start)){","// start = start.nextSibling;","// start.nodeValue = start.nodeValue.replace(/^\\s{4}/,'');","// break;","// }","// while(start.previousSibling && start.previousSibling.nodeType == 3){","// start.nodeValue = start.previousSibling.nodeValue + start.nodeValue;","// domUtils.remove(start.previousSibling)","// }","// start = start.previousSibling;","// }","// }","//","// var end = bk.end;","// start = bk.start.nextSibling;","//","// while(start && start !== end){","// if(domUtils.isBr(start) && start.nextSibling){","// if(start.nextSibling === end){","// break;","// }","// start = start.nextSibling;","// while(start.nextSibling && start.nextSibling.nodeType == 3){","// start.nodeValue += start.nextSibling.nodeValue;","// domUtils.remove(start.nextSibling)","// }","//","// start.nodeValue = start.nodeValue.replace(/^\\s{4}/,'');","// }","//","// start = start.nextSibling;","// }","// rng.moveToBookmark(bk).select();","// }else{","// var bk = rng.createBookmark();","// var start = bk.start.previousSibling;","// if(start === pre.firstChild){","// start.nodeValue = start.nodeValue.replace(/^\\s{4}/,'');","// }else{","// while(start){","// if(domUtils.isBr(start)){","// start = start.nextSibling;","// start.nodeValue = start.nodeValue.replace(/^\\s{4}/,'');","// break;","// }","// while(start.previousSibling && start.previousSibling.nodeType == 3){","// start.nodeValue = start.previousSibling.nodeValue + start.nodeValue;","// domUtils.remove(start.previousSibling)","// }","// start = start.previousSibling;","// }","// }","// }"," }else{"," if(!rng.collapsed){"," var bk = rng.createBookmark();"," var start = bk.start.previousSibling;",""," while(start){"," if(pre.firstChild === start && !domUtils.isBr(start)){"," pre.insertBefore(me.document.createTextNode(' '),start);",""," break;"," }"," if(domUtils.isBr(start)){"," pre.insertBefore(me.document.createTextNode(' '),start.nextSibling);",""," break;"," }"," start = start.previousSibling;"," }"," var end = bk.end;"," start = bk.start.nextSibling;"," if(pre.firstChild === bk.start){"," pre.insertBefore(me.document.createTextNode(' '),start.nextSibling)",""," }"," while(start && start !== end){"," if(domUtils.isBr(start) && start.nextSibling){"," if(start.nextSibling === end){"," break;"," }"," pre.insertBefore(me.document.createTextNode(' '),start.nextSibling)"," }",""," start = start.nextSibling;"," }"," rng.moveToBookmark(bk).select();"," }else{"," var tmpNode = me.document.createTextNode(' ');"," rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true).select(true);"," }"," }","",""," me.fireEvent('saveScene');"," return true;"," }","",""," });","",""," me.addListener('beforeinserthtml',function(evtName,html){"," var me = this,"," rng = me.selection.getRange(),"," pre = domUtils.findParentByTagName(rng.startContainer,'pre',true);"," if(pre){"," if(!rng.collapsed){"," rng.deleteContents()"," }"," var htmlstr = '';"," if(browser.ie && browser.version > 8){",""," utils.each(UE.filterNode(UE.htmlparser(html),me.options.filterTxtRules).children,function(node){"," if(node.type =='element'){"," if(node.tagName == 'br'){"," htmlstr += '\\n'"," }else if(!dtd.$empty[node.tagName]){"," utils.each(node.children,function(cn){"," if(cn.type =='element'){"," if(cn.tagName == 'br'){"," htmlstr += '\\n'"," }else if(!dtd.$empty[node.tagName]){"," htmlstr += cn.innerText();"," }"," }else{"," htmlstr += cn.data"," }"," })"," if(!/\\n$/.test(htmlstr)){"," htmlstr += '\\n';"," }"," }"," }else{"," htmlstr += node.data + '\\n'"," }"," if(!node.nextSibling() && /\\n$/.test(htmlstr)){"," htmlstr = htmlstr.replace(/\\n$/,'');"," }"," });"," var tmpNode = me.document.createTextNode(utils.html(htmlstr.replace(/&nbsp;/g,' ')));"," rng.insertNode(tmpNode).selectNode(tmpNode).select();"," }else{"," var frag = me.document.createDocumentFragment();",""," utils.each(UE.filterNode(UE.htmlparser(html),me.options.filterTxtRules).children,function(node){"," if(node.type =='element'){"," if(node.tagName == 'br'){"," frag.appendChild(me.document.createElement('br'))"," }else if(!dtd.$empty[node.tagName]){"," utils.each(node.children,function(cn){"," if(cn.type =='element'){"," if(cn.tagName == 'br'){",""," frag.appendChild(me.document.createElement('br'))"," }else if(!dtd.$empty[node.tagName]){"," frag.appendChild(me.document.createTextNode(utils.html(cn.innerText().replace(/&nbsp;/g,' '))));",""," }"," }else{"," frag.appendChild(me.document.createTextNode(utils.html( cn.data.replace(/&nbsp;/g,' '))));",""," }"," })"," if(frag.lastChild.nodeName != 'BR'){"," frag.appendChild(me.document.createElement('br'))"," }"," }"," }else{"," frag.appendChild(me.document.createTextNode(utils.html( node.data.replace(/&nbsp;/g,' '))));"," }"," if(!node.nextSibling() && frag.lastChild.nodeName == 'BR'){"," frag.removeChild(frag.lastChild)"," }","",""," });"," rng.insertNode(frag).select();",""," }",""," return true;"," }"," });"," //方向键的处理"," me.addListener('keydown',function(cmd,evt){"," var me = this,keyCode = evt.keyCode || evt.which;"," if(keyCode == 40){"," var rng = me.selection.getRange(),pre,start = rng.startContainer;"," if(rng.collapsed && (pre = domUtils.findParentByTagName(rng.startContainer,'pre',true)) && !pre.nextSibling){"," var last = pre.lastChild"," while(last && last.nodeName == 'BR'){"," last = last.previousSibling;"," }"," if(last === start || rng.startContainer === pre && rng.startOffset == pre.childNodes.length){"," me.execCommand('insertparagraph');"," domUtils.preventDefault(evt)"," }",""," }"," }"," });"," //trace:3395"," me.addListener('delkeydown',function(type,evt){"," var rng = this.selection.getRange();"," rng.txtToElmBoundary(true);"," var start = rng.startContainer;"," if(domUtils.isTagNode(start,'pre') && rng.collapsed && domUtils.isStartInblock(rng)){"," var p = me.document.createElement('p');"," domUtils.fillNode(me.document,p);"," start.parentNode.insertBefore(p,start);"," domUtils.remove(start);"," rng.setStart(p,0).setCursor(false,true);"," domUtils.preventDefault(evt);"," return true;"," }"," })","};"]; +_$jscoverage['plugins/insertcode.js'][7]++; +UE.plugins.insertcode = (function () { + _$jscoverage['plugins/insertcode.js'][8]++; + var me = this; + _$jscoverage['plugins/insertcode.js'][9]++; + me.ready((function () { + _$jscoverage['plugins/insertcode.js'][10]++; + utils.cssRule("pre", "pre{margin:.5em 0;padding:.4em .6em;border-radius:8px;background:#f8f8f8;}", me.document); +})); + _$jscoverage['plugins/insertcode.js'][13]++; + me.setOpt("insertcode", {"as3": "ActionScript3", "bash": "Bash/Shell", "cpp": "C/C++", "css": "Css", "cf": "CodeFunction", "c#": "C#", "delphi": "Delphi", "diff": "Diff", "erlang": "Erlang", "groovy": "Groovy", "html": "Html", "java": "Java", "jfx": "JavaFx", "js": "Javascript", "pl": "Perl", "php": "Php", "plain": "Plain Text", "ps": "PowerShell", "python": "Python", "ruby": "Ruby", "scala": "Scala", "sql": "Sql", "vb": "Vb", "xml": "Xml"}); + _$jscoverage['plugins/insertcode.js'][63]++; + me.commands.insertcode = {execCommand: (function (cmd, lang) { + _$jscoverage['plugins/insertcode.js'][65]++; + var me = this, rng = me.selection.getRange(), pre = domUtils.findParentByTagName(rng.startContainer, "pre", true); + _$jscoverage['plugins/insertcode.js'][68]++; + if (pre) { + _$jscoverage['plugins/insertcode.js'][69]++; + pre.className = ("brush:" + lang + ";toolbar:false;"); + } + else { + _$jscoverage['plugins/insertcode.js'][71]++; + var code = ""; + _$jscoverage['plugins/insertcode.js'][72]++; + if (rng.collapsed) { + _$jscoverage['plugins/insertcode.js'][73]++; + code = (browser.ie? ((browser.version > 8)? "": " "): "
    "); + } + else { + _$jscoverage['plugins/insertcode.js'][75]++; + var frag = rng.extractContents(); + _$jscoverage['plugins/insertcode.js'][76]++; + var div = me.document.createElement("div"); + _$jscoverage['plugins/insertcode.js'][77]++; + div.appendChild(frag); + _$jscoverage['plugins/insertcode.js'][79]++; + utils.each(UE.filterNode(UE.htmlparser(div.innerHTML.replace(/[\r\t]/g, "")), me.options.filterTxtRules).children, (function (node) { + _$jscoverage['plugins/insertcode.js'][80]++; + if ((browser.ie && (browser.version > 8))) { + _$jscoverage['plugins/insertcode.js'][82]++; + if ((node.type == "element")) { + _$jscoverage['plugins/insertcode.js'][83]++; + if ((node.tagName == "br")) { + _$jscoverage['plugins/insertcode.js'][84]++; + code += "\n"; + } + else { + _$jscoverage['plugins/insertcode.js'][85]++; + if ((! dtd.$empty[node.tagName])) { + _$jscoverage['plugins/insertcode.js'][86]++; + utils.each(node.children, (function (cn) { + _$jscoverage['plugins/insertcode.js'][87]++; + if ((cn.type == "element")) { + _$jscoverage['plugins/insertcode.js'][88]++; + if ((cn.tagName == "br")) { + _$jscoverage['plugins/insertcode.js'][89]++; + code += "\n"; + } + else { + _$jscoverage['plugins/insertcode.js'][90]++; + if ((! dtd.$empty[node.tagName])) { + _$jscoverage['plugins/insertcode.js'][91]++; + code += cn.innerText(); + } + } + } + else { + _$jscoverage['plugins/insertcode.js'][94]++; + code += cn.data; + } +})); + _$jscoverage['plugins/insertcode.js'][97]++; + if ((! /\n$/.test(code))) { + _$jscoverage['plugins/insertcode.js'][98]++; + code += "\n"; + } + } + } + } + else { + _$jscoverage['plugins/insertcode.js'][102]++; + code += (node.data + "\n"); + } + _$jscoverage['plugins/insertcode.js'][104]++; + if (((! node.nextSibling()) && /\n$/.test(code))) { + _$jscoverage['plugins/insertcode.js'][105]++; + code = code.replace(/\n$/, ""); + } + } + else { + _$jscoverage['plugins/insertcode.js'][108]++; + if (browser.ie) { + _$jscoverage['plugins/insertcode.js'][110]++; + if ((node.type == "element")) { + _$jscoverage['plugins/insertcode.js'][111]++; + if ((node.tagName == "br")) { + _$jscoverage['plugins/insertcode.js'][112]++; + code += "
    "; + } + else { + _$jscoverage['plugins/insertcode.js'][113]++; + if ((! dtd.$empty[node.tagName])) { + _$jscoverage['plugins/insertcode.js'][114]++; + utils.each(node.children, (function (cn) { + _$jscoverage['plugins/insertcode.js'][115]++; + if ((cn.type == "element")) { + _$jscoverage['plugins/insertcode.js'][116]++; + if ((cn.tagName == "br")) { + _$jscoverage['plugins/insertcode.js'][117]++; + code += "
    "; + } + else { + _$jscoverage['plugins/insertcode.js'][118]++; + if ((! dtd.$empty[node.tagName])) { + _$jscoverage['plugins/insertcode.js'][119]++; + code += cn.innerText(); + } + } + } + else { + _$jscoverage['plugins/insertcode.js'][122]++; + code += cn.data; + } +})); + _$jscoverage['plugins/insertcode.js'][125]++; + if ((! /br>$/.test(code))) { + _$jscoverage['plugins/insertcode.js'][126]++; + code += "
    "; + } + } + } + } + else { + _$jscoverage['plugins/insertcode.js'][130]++; + code += (node.data + "
    "); + } + _$jscoverage['plugins/insertcode.js'][132]++; + if (((! node.nextSibling()) && /
    $/.test(code))) { + _$jscoverage['plugins/insertcode.js'][133]++; + code = code.replace(/
    $/, ""); + } + } + else { + _$jscoverage['plugins/insertcode.js'][137]++; + code += ((node.type == "element")? (dtd.$empty[node.tagName]? "": node.innerText()): node.data); + _$jscoverage['plugins/insertcode.js'][138]++; + if ((! /br\/?\s*>$/.test(code))) { + _$jscoverage['plugins/insertcode.js'][139]++; + if ((! node.nextSibling())) { + _$jscoverage['plugins/insertcode.js'][140]++; + return; + } + _$jscoverage['plugins/insertcode.js'][141]++; + code += "
    "; + } + } + } +})); + } + _$jscoverage['plugins/insertcode.js'][149]++; + me.execCommand("inserthtml", ("
    " + code + "
    "), true); + _$jscoverage['plugins/insertcode.js'][151]++; + pre = me.document.getElementById("coder"); + _$jscoverage['plugins/insertcode.js'][152]++; + domUtils.removeAttributes(pre, "id"); + _$jscoverage['plugins/insertcode.js'][153]++; + var tmpNode = pre.previousSibling; + _$jscoverage['plugins/insertcode.js'][155]++; + if ((tmpNode && (((tmpNode.nodeType == 3) && (tmpNode.nodeValue.length == 1) && browser.ie && (browser.version == 6)) || domUtils.isEmptyBlock(tmpNode)))) { + _$jscoverage['plugins/insertcode.js'][157]++; + domUtils.remove(tmpNode); + } + _$jscoverage['plugins/insertcode.js'][159]++; + var rng = me.selection.getRange(); + _$jscoverage['plugins/insertcode.js'][160]++; + if (domUtils.isEmptyBlock(pre)) { + _$jscoverage['plugins/insertcode.js'][161]++; + rng.setStart(pre, 0).setCursor(false, true); + } + else { + _$jscoverage['plugins/insertcode.js'][163]++; + rng.selectNodeContents(pre).select(); + } + } +}), queryCommandValue: (function () { + _$jscoverage['plugins/insertcode.js'][171]++; + var path = this.selection.getStartElementPath(); + _$jscoverage['plugins/insertcode.js'][172]++; + var lang = ""; + _$jscoverage['plugins/insertcode.js'][173]++; + utils.each(path, (function (node) { + _$jscoverage['plugins/insertcode.js'][174]++; + if ((node.nodeName == "PRE")) { + _$jscoverage['plugins/insertcode.js'][175]++; + var match = node.className.match(/brush:([^;]+)/); + _$jscoverage['plugins/insertcode.js'][176]++; + lang = ((match && match[1])? match[1]: ""); + _$jscoverage['plugins/insertcode.js'][177]++; + return false; + } +})); + _$jscoverage['plugins/insertcode.js'][180]++; + return lang; +})}; + _$jscoverage['plugins/insertcode.js'][184]++; + me.addInputRule((function (root) { + _$jscoverage['plugins/insertcode.js'][185]++; + utils.each(root.getNodesByTagName("pre"), (function (pre) { + _$jscoverage['plugins/insertcode.js'][186]++; + var brs = pre.getNodesByTagName("br"); + _$jscoverage['plugins/insertcode.js'][187]++; + if (brs.length) { + _$jscoverage['plugins/insertcode.js'][188]++; + (browser.ie && (browser.version > 8) && utils.each(brs, (function (br) { + _$jscoverage['plugins/insertcode.js'][189]++; + var txt = UE.uNode.createText("\n"); + _$jscoverage['plugins/insertcode.js'][190]++; + br.parentNode.insertBefore(txt, br); + _$jscoverage['plugins/insertcode.js'][191]++; + br.parentNode.removeChild(br); +}))); + _$jscoverage['plugins/insertcode.js'][193]++; + return; + } + _$jscoverage['plugins/insertcode.js'][195]++; + if ((browser.ie && (browser.version > 8))) { + _$jscoverage['plugins/insertcode.js'][196]++; + return; + } + _$jscoverage['plugins/insertcode.js'][197]++; + var code = pre.innerText().split(/\n/); + _$jscoverage['plugins/insertcode.js'][198]++; + pre.innerHTML(""); + _$jscoverage['plugins/insertcode.js'][199]++; + utils.each(code, (function (c) { + _$jscoverage['plugins/insertcode.js'][200]++; + if (c.length) { + _$jscoverage['plugins/insertcode.js'][201]++; + pre.appendChild(UE.uNode.createText(c)); + } + _$jscoverage['plugins/insertcode.js'][203]++; + pre.appendChild(UE.uNode.createElement("br")); +})); +})); +})); + _$jscoverage['plugins/insertcode.js'][207]++; + me.addOutputRule((function (root) { + _$jscoverage['plugins/insertcode.js'][208]++; + utils.each(root.getNodesByTagName("pre"), (function (pre) { + _$jscoverage['plugins/insertcode.js'][209]++; + var code = ""; + _$jscoverage['plugins/insertcode.js'][210]++; + utils.each(pre.children, (function (n) { + _$jscoverage['plugins/insertcode.js'][211]++; + if ((n.type == "text")) { + _$jscoverage['plugins/insertcode.js'][214]++; + code += n.data.replace(/[ ]/g, " ").replace(/\n$/, ""); + } + else { + _$jscoverage['plugins/insertcode.js'][216]++; + if ((n.tagName == "br")) { + _$jscoverage['plugins/insertcode.js'][217]++; + code += "\n"; + } + else { + _$jscoverage['plugins/insertcode.js'][219]++; + code += ((! dtd.$empty[n.tagName])? "": n.innerText()); + } + } +})); + _$jscoverage['plugins/insertcode.js'][226]++; + pre.innerText(code.replace(/( |\n)+$/, "")); +})); +})); + _$jscoverage['plugins/insertcode.js'][230]++; + me.notNeedCodeQuery = {help: 1, undo: 1, redo: 1, source: 1, print: 1, searchreplace: 1, fullscreen: 1, preview: 1, insertparagraph: 1, elementpath: 1, highlightcode: 1, insertcode: 1, inserthtml: 1, selectall: 1}; + _$jscoverage['plugins/insertcode.js'][247]++; + var orgQuery = me.queryCommandState; + _$jscoverage['plugins/insertcode.js'][248]++; + me.queryCommandState = (function (cmd) { + _$jscoverage['plugins/insertcode.js'][249]++; + var me = this; + _$jscoverage['plugins/insertcode.js'][251]++; + if (((! me.notNeedCodeQuery[cmd.toLowerCase()]) && me.selection && me.queryCommandValue("insertcode"))) { + _$jscoverage['plugins/insertcode.js'][252]++; + return -1; + } + _$jscoverage['plugins/insertcode.js'][254]++; + return UE.Editor.prototype.queryCommandState.apply(this, arguments); +}); + _$jscoverage['plugins/insertcode.js'][256]++; + me.addListener("beforeenterkeydown", (function () { + _$jscoverage['plugins/insertcode.js'][257]++; + var rng = me.selection.getRange(); + _$jscoverage['plugins/insertcode.js'][258]++; + var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true); + _$jscoverage['plugins/insertcode.js'][259]++; + if (pre) { + _$jscoverage['plugins/insertcode.js'][260]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/insertcode.js'][261]++; + if ((! rng.collapsed)) { + _$jscoverage['plugins/insertcode.js'][262]++; + rng.deleteContents(); + } + _$jscoverage['plugins/insertcode.js'][264]++; + if ((! browser.ie)) { + _$jscoverage['plugins/insertcode.js'][265]++; + var tmpNode = me.document.createElement("br"), pre = pre; + _$jscoverage['plugins/insertcode.js'][266]++; + rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true); + _$jscoverage['plugins/insertcode.js'][267]++; + var next = tmpNode.nextSibling; + _$jscoverage['plugins/insertcode.js'][268]++; + if ((! next)) { + _$jscoverage['plugins/insertcode.js'][269]++; + rng.insertNode(tmpNode.cloneNode(false)); + } + else { + _$jscoverage['plugins/insertcode.js'][271]++; + rng.setStartAfter(tmpNode); + } + _$jscoverage['plugins/insertcode.js'][273]++; + pre = tmpNode.previousSibling; + _$jscoverage['plugins/insertcode.js'][274]++; + var tmp; + _$jscoverage['plugins/insertcode.js'][275]++; + while (pre) { + _$jscoverage['plugins/insertcode.js'][276]++; + tmp = pre; + _$jscoverage['plugins/insertcode.js'][277]++; + pre = pre.previousSibling; + _$jscoverage['plugins/insertcode.js'][278]++; + if (((! pre) || (pre.nodeName == "BR"))) { + _$jscoverage['plugins/insertcode.js'][279]++; + pre = tmp; + _$jscoverage['plugins/insertcode.js'][280]++; + break; + } +} + _$jscoverage['plugins/insertcode.js'][283]++; + if (pre) { + _$jscoverage['plugins/insertcode.js'][284]++; + var str = ""; + _$jscoverage['plugins/insertcode.js'][285]++; + while ((pre && (pre.nodeName != "BR") && new RegExp(("^[\\s" + domUtils.fillChar + "]*$")).test(pre.nodeValue))) { + _$jscoverage['plugins/insertcode.js'][286]++; + str += pre.nodeValue; + _$jscoverage['plugins/insertcode.js'][287]++; + pre = pre.nextSibling; +} + _$jscoverage['plugins/insertcode.js'][289]++; + if ((pre.nodeName != "BR")) { + _$jscoverage['plugins/insertcode.js'][290]++; + var match = pre.nodeValue.match(new RegExp(("^([\\s" + domUtils.fillChar + "]+)"))); + _$jscoverage['plugins/insertcode.js'][291]++; + if ((match && match[1])) { + _$jscoverage['plugins/insertcode.js'][292]++; + str += match[1]; + } + } + _$jscoverage['plugins/insertcode.js'][296]++; + if (str) { + _$jscoverage['plugins/insertcode.js'][297]++; + str = me.document.createTextNode(str); + _$jscoverage['plugins/insertcode.js'][298]++; + rng.insertNode(str).setStartAfter(str); + } + } + _$jscoverage['plugins/insertcode.js'][301]++; + rng.collapse(true).select(true); + } + else { + _$jscoverage['plugins/insertcode.js'][303]++; + if ((browser.version > 8)) { + _$jscoverage['plugins/insertcode.js'][305]++; + var txt = me.document.createTextNode("\n"); + _$jscoverage['plugins/insertcode.js'][306]++; + var start = rng.startContainer; + _$jscoverage['plugins/insertcode.js'][307]++; + if ((rng.startOffset == 0)) { + _$jscoverage['plugins/insertcode.js'][308]++; + var preNode = start.previousSibling; + _$jscoverage['plugins/insertcode.js'][309]++; + if (preNode) { + _$jscoverage['plugins/insertcode.js'][310]++; + rng.insertNode(txt); + _$jscoverage['plugins/insertcode.js'][311]++; + var fillchar = me.document.createTextNode(" "); + _$jscoverage['plugins/insertcode.js'][312]++; + rng.setStartAfter(txt).insertNode(fillchar).setStart(fillchar, 0).collapse(true).select(true); + } + } + else { + _$jscoverage['plugins/insertcode.js'][315]++; + rng.insertNode(txt).setStartAfter(txt); + _$jscoverage['plugins/insertcode.js'][316]++; + var fillchar = me.document.createTextNode(" "); + _$jscoverage['plugins/insertcode.js'][317]++; + start = rng.startContainer.childNodes[rng.startOffset]; + _$jscoverage['plugins/insertcode.js'][318]++; + if ((start && (! /^\n/.test(start.nodeValue)))) { + _$jscoverage['plugins/insertcode.js'][319]++; + rng.setStartBefore(txt); + } + _$jscoverage['plugins/insertcode.js'][321]++; + rng.insertNode(fillchar).setStart(fillchar, 0).collapse(true).select(true); + } + } + else { + _$jscoverage['plugins/insertcode.js'][325]++; + var tmpNode = me.document.createElement("br"); + _$jscoverage['plugins/insertcode.js'][326]++; + rng.insertNode(tmpNode); + _$jscoverage['plugins/insertcode.js'][327]++; + rng.insertNode(me.document.createTextNode(domUtils.fillChar)); + _$jscoverage['plugins/insertcode.js'][328]++; + rng.setStartAfter(tmpNode); + _$jscoverage['plugins/insertcode.js'][329]++; + pre = tmpNode.previousSibling; + _$jscoverage['plugins/insertcode.js'][330]++; + var tmp = tmp; + _$jscoverage['plugins/insertcode.js'][331]++; + while (pre) { + _$jscoverage['plugins/insertcode.js'][332]++; + tmp = pre; + _$jscoverage['plugins/insertcode.js'][333]++; + pre = pre.previousSibling; + _$jscoverage['plugins/insertcode.js'][334]++; + if (((! pre) || (pre.nodeName == "BR"))) { + _$jscoverage['plugins/insertcode.js'][335]++; + pre = tmp; + _$jscoverage['plugins/insertcode.js'][336]++; + break; + } +} + _$jscoverage['plugins/insertcode.js'][339]++; + if (pre) { + _$jscoverage['plugins/insertcode.js'][340]++; + var str = ""; + _$jscoverage['plugins/insertcode.js'][341]++; + while ((pre && (pre.nodeName != "BR") && new RegExp(("^[ " + domUtils.fillChar + "]*$")).test(pre.nodeValue))) { + _$jscoverage['plugins/insertcode.js'][342]++; + str += pre.nodeValue; + _$jscoverage['plugins/insertcode.js'][343]++; + pre = pre.nextSibling; +} + _$jscoverage['plugins/insertcode.js'][345]++; + if ((pre.nodeName != "BR")) { + _$jscoverage['plugins/insertcode.js'][346]++; + var match = pre.nodeValue.match(new RegExp(("^([ " + domUtils.fillChar + "]+)"))); + _$jscoverage['plugins/insertcode.js'][347]++; + if ((match && match[1])) { + _$jscoverage['plugins/insertcode.js'][348]++; + str += match[1]; + } + } + _$jscoverage['plugins/insertcode.js'][353]++; + str = me.document.createTextNode(str); + _$jscoverage['plugins/insertcode.js'][354]++; + rng.insertNode(str).setStartAfter(str); + } + _$jscoverage['plugins/insertcode.js'][356]++; + rng.collapse(true).select(); + } + } + _$jscoverage['plugins/insertcode.js'][361]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/insertcode.js'][362]++; + return true; + } +})); + _$jscoverage['plugins/insertcode.js'][368]++; + me.addListener("tabkeydown", (function (cmd, evt) { + _$jscoverage['plugins/insertcode.js'][369]++; + var rng = me.selection.getRange(); + _$jscoverage['plugins/insertcode.js'][370]++; + var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true); + _$jscoverage['plugins/insertcode.js'][371]++; + if (pre) { + _$jscoverage['plugins/insertcode.js'][372]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/insertcode.js'][373]++; + if (evt.shiftKey) { + } + else { + _$jscoverage['plugins/insertcode.js'][436]++; + if ((! rng.collapsed)) { + _$jscoverage['plugins/insertcode.js'][437]++; + var bk = rng.createBookmark(); + _$jscoverage['plugins/insertcode.js'][438]++; + var start = bk.start.previousSibling; + _$jscoverage['plugins/insertcode.js'][440]++; + while (start) { + _$jscoverage['plugins/insertcode.js'][441]++; + if (((pre.firstChild === start) && (! domUtils.isBr(start)))) { + _$jscoverage['plugins/insertcode.js'][442]++; + pre.insertBefore(me.document.createTextNode(" "), start); + _$jscoverage['plugins/insertcode.js'][444]++; + break; + } + _$jscoverage['plugins/insertcode.js'][446]++; + if (domUtils.isBr(start)) { + _$jscoverage['plugins/insertcode.js'][447]++; + pre.insertBefore(me.document.createTextNode(" "), start.nextSibling); + _$jscoverage['plugins/insertcode.js'][449]++; + break; + } + _$jscoverage['plugins/insertcode.js'][451]++; + start = start.previousSibling; +} + _$jscoverage['plugins/insertcode.js'][453]++; + var end = bk.end; + _$jscoverage['plugins/insertcode.js'][454]++; + start = bk.start.nextSibling; + _$jscoverage['plugins/insertcode.js'][455]++; + if ((pre.firstChild === bk.start)) { + _$jscoverage['plugins/insertcode.js'][456]++; + pre.insertBefore(me.document.createTextNode(" "), start.nextSibling); + } + _$jscoverage['plugins/insertcode.js'][459]++; + while ((start && (start !== end))) { + _$jscoverage['plugins/insertcode.js'][460]++; + if ((domUtils.isBr(start) && start.nextSibling)) { + _$jscoverage['plugins/insertcode.js'][461]++; + if ((start.nextSibling === end)) { + _$jscoverage['plugins/insertcode.js'][462]++; + break; + } + _$jscoverage['plugins/insertcode.js'][464]++; + pre.insertBefore(me.document.createTextNode(" "), start.nextSibling); + } + _$jscoverage['plugins/insertcode.js'][467]++; + start = start.nextSibling; +} + _$jscoverage['plugins/insertcode.js'][469]++; + rng.moveToBookmark(bk).select(); + } + else { + _$jscoverage['plugins/insertcode.js'][471]++; + var tmpNode = me.document.createTextNode(" "); + _$jscoverage['plugins/insertcode.js'][472]++; + rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true).select(true); + } + } + _$jscoverage['plugins/insertcode.js'][477]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/insertcode.js'][478]++; + return true; + } +})); + _$jscoverage['plugins/insertcode.js'][485]++; + me.addListener("beforeinserthtml", (function (evtName, html) { + _$jscoverage['plugins/insertcode.js'][486]++; + var me = this, rng = me.selection.getRange(), pre = domUtils.findParentByTagName(rng.startContainer, "pre", true); + _$jscoverage['plugins/insertcode.js'][489]++; + if (pre) { + _$jscoverage['plugins/insertcode.js'][490]++; + if ((! rng.collapsed)) { + _$jscoverage['plugins/insertcode.js'][491]++; + rng.deleteContents(); + } + _$jscoverage['plugins/insertcode.js'][493]++; + var htmlstr = ""; + _$jscoverage['plugins/insertcode.js'][494]++; + if ((browser.ie && (browser.version > 8))) { + _$jscoverage['plugins/insertcode.js'][496]++; + utils.each(UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules).children, (function (node) { + _$jscoverage['plugins/insertcode.js'][497]++; + if ((node.type == "element")) { + _$jscoverage['plugins/insertcode.js'][498]++; + if ((node.tagName == "br")) { + _$jscoverage['plugins/insertcode.js'][499]++; + htmlstr += "\n"; + } + else { + _$jscoverage['plugins/insertcode.js'][500]++; + if ((! dtd.$empty[node.tagName])) { + _$jscoverage['plugins/insertcode.js'][501]++; + utils.each(node.children, (function (cn) { + _$jscoverage['plugins/insertcode.js'][502]++; + if ((cn.type == "element")) { + _$jscoverage['plugins/insertcode.js'][503]++; + if ((cn.tagName == "br")) { + _$jscoverage['plugins/insertcode.js'][504]++; + htmlstr += "\n"; + } + else { + _$jscoverage['plugins/insertcode.js'][505]++; + if ((! dtd.$empty[node.tagName])) { + _$jscoverage['plugins/insertcode.js'][506]++; + htmlstr += cn.innerText(); + } + } + } + else { + _$jscoverage['plugins/insertcode.js'][509]++; + htmlstr += cn.data; + } +})); + _$jscoverage['plugins/insertcode.js'][512]++; + if ((! /\n$/.test(htmlstr))) { + _$jscoverage['plugins/insertcode.js'][513]++; + htmlstr += "\n"; + } + } + } + } + else { + _$jscoverage['plugins/insertcode.js'][517]++; + htmlstr += (node.data + "\n"); + } + _$jscoverage['plugins/insertcode.js'][519]++; + if (((! node.nextSibling()) && /\n$/.test(htmlstr))) { + _$jscoverage['plugins/insertcode.js'][520]++; + htmlstr = htmlstr.replace(/\n$/, ""); + } +})); + _$jscoverage['plugins/insertcode.js'][523]++; + var tmpNode = me.document.createTextNode(utils.html(htmlstr.replace(/ /g, " "))); + _$jscoverage['plugins/insertcode.js'][524]++; + rng.insertNode(tmpNode).selectNode(tmpNode).select(); + } + else { + _$jscoverage['plugins/insertcode.js'][526]++; + var frag = me.document.createDocumentFragment(); + _$jscoverage['plugins/insertcode.js'][528]++; + utils.each(UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules).children, (function (node) { + _$jscoverage['plugins/insertcode.js'][529]++; + if ((node.type == "element")) { + _$jscoverage['plugins/insertcode.js'][530]++; + if ((node.tagName == "br")) { + _$jscoverage['plugins/insertcode.js'][531]++; + frag.appendChild(me.document.createElement("br")); + } + else { + _$jscoverage['plugins/insertcode.js'][532]++; + if ((! dtd.$empty[node.tagName])) { + _$jscoverage['plugins/insertcode.js'][533]++; + utils.each(node.children, (function (cn) { + _$jscoverage['plugins/insertcode.js'][534]++; + if ((cn.type == "element")) { + _$jscoverage['plugins/insertcode.js'][535]++; + if ((cn.tagName == "br")) { + _$jscoverage['plugins/insertcode.js'][537]++; + frag.appendChild(me.document.createElement("br")); + } + else { + _$jscoverage['plugins/insertcode.js'][538]++; + if ((! dtd.$empty[node.tagName])) { + _$jscoverage['plugins/insertcode.js'][539]++; + frag.appendChild(me.document.createTextNode(utils.html(cn.innerText().replace(/ /g, " ")))); + } + } + } + else { + _$jscoverage['plugins/insertcode.js'][543]++; + frag.appendChild(me.document.createTextNode(utils.html(cn.data.replace(/ /g, " ")))); + } +})); + _$jscoverage['plugins/insertcode.js'][547]++; + if ((frag.lastChild.nodeName != "BR")) { + _$jscoverage['plugins/insertcode.js'][548]++; + frag.appendChild(me.document.createElement("br")); + } + } + } + } + else { + _$jscoverage['plugins/insertcode.js'][552]++; + frag.appendChild(me.document.createTextNode(utils.html(node.data.replace(/ /g, " ")))); + } + _$jscoverage['plugins/insertcode.js'][554]++; + if (((! node.nextSibling()) && (frag.lastChild.nodeName == "BR"))) { + _$jscoverage['plugins/insertcode.js'][555]++; + frag.removeChild(frag.lastChild); + } +})); + _$jscoverage['plugins/insertcode.js'][560]++; + rng.insertNode(frag).select(); + } + _$jscoverage['plugins/insertcode.js'][564]++; + return true; + } +})); + _$jscoverage['plugins/insertcode.js'][568]++; + me.addListener("keydown", (function (cmd, evt) { + _$jscoverage['plugins/insertcode.js'][569]++; + var me = this, keyCode = (evt.keyCode || evt.which); + _$jscoverage['plugins/insertcode.js'][570]++; + if ((keyCode == 40)) { + _$jscoverage['plugins/insertcode.js'][571]++; + var rng = me.selection.getRange(), pre, start = rng.startContainer; + _$jscoverage['plugins/insertcode.js'][572]++; + if ((rng.collapsed && (pre = domUtils.findParentByTagName(rng.startContainer, "pre", true)) && (! pre.nextSibling))) { + _$jscoverage['plugins/insertcode.js'][573]++; + var last = pre.lastChild; + _$jscoverage['plugins/insertcode.js'][574]++; + while ((last && (last.nodeName == "BR"))) { + _$jscoverage['plugins/insertcode.js'][575]++; + last = last.previousSibling; +} + _$jscoverage['plugins/insertcode.js'][577]++; + if (((last === start) || ((rng.startContainer === pre) && (rng.startOffset == pre.childNodes.length)))) { + _$jscoverage['plugins/insertcode.js'][578]++; + me.execCommand("insertparagraph"); + _$jscoverage['plugins/insertcode.js'][579]++; + domUtils.preventDefault(evt); + } + } + } +})); + _$jscoverage['plugins/insertcode.js'][586]++; + me.addListener("delkeydown", (function (type, evt) { + _$jscoverage['plugins/insertcode.js'][587]++; + var rng = this.selection.getRange(); + _$jscoverage['plugins/insertcode.js'][588]++; + rng.txtToElmBoundary(true); + _$jscoverage['plugins/insertcode.js'][589]++; + var start = rng.startContainer; + _$jscoverage['plugins/insertcode.js'][590]++; + if ((domUtils.isTagNode(start, "pre") && rng.collapsed && domUtils.isStartInblock(rng))) { + _$jscoverage['plugins/insertcode.js'][591]++; + var p = me.document.createElement("p"); + _$jscoverage['plugins/insertcode.js'][592]++; + domUtils.fillNode(me.document, p); + _$jscoverage['plugins/insertcode.js'][593]++; + start.parentNode.insertBefore(p, start); + _$jscoverage['plugins/insertcode.js'][594]++; + domUtils.remove(start); + _$jscoverage['plugins/insertcode.js'][595]++; + rng.setStart(p, 0).setCursor(false, true); + _$jscoverage['plugins/insertcode.js'][596]++; + domUtils.preventDefault(evt); + _$jscoverage['plugins/insertcode.js'][597]++; + return true; + } +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/inserthtml.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/inserthtml.js new file mode 100644 index 000000000..2e7ccbac2 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/inserthtml.js @@ -0,0 +1,504 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/inserthtml.js']) { + _$jscoverage['plugins/inserthtml.js'] = []; + _$jscoverage['plugins/inserthtml.js'][31] = 0; + _$jscoverage['plugins/inserthtml.js'][33] = 0; + _$jscoverage['plugins/inserthtml.js'][36] = 0; + _$jscoverage['plugins/inserthtml.js'][37] = 0; + _$jscoverage['plugins/inserthtml.js'][39] = 0; + _$jscoverage['plugins/inserthtml.js'][40] = 0; + _$jscoverage['plugins/inserthtml.js'][42] = 0; + _$jscoverage['plugins/inserthtml.js'][43] = 0; + _$jscoverage['plugins/inserthtml.js'][44] = 0; + _$jscoverage['plugins/inserthtml.js'][46] = 0; + _$jscoverage['plugins/inserthtml.js'][47] = 0; + _$jscoverage['plugins/inserthtml.js'][49] = 0; + _$jscoverage['plugins/inserthtml.js'][50] = 0; + _$jscoverage['plugins/inserthtml.js'][53] = 0; + _$jscoverage['plugins/inserthtml.js'][54] = 0; + _$jscoverage['plugins/inserthtml.js'][56] = 0; + _$jscoverage['plugins/inserthtml.js'][58] = 0; + _$jscoverage['plugins/inserthtml.js'][59] = 0; + _$jscoverage['plugins/inserthtml.js'][60] = 0; + _$jscoverage['plugins/inserthtml.js'][61] = 0; + _$jscoverage['plugins/inserthtml.js'][63] = 0; + _$jscoverage['plugins/inserthtml.js'][64] = 0; + _$jscoverage['plugins/inserthtml.js'][65] = 0; + _$jscoverage['plugins/inserthtml.js'][67] = 0; + _$jscoverage['plugins/inserthtml.js'][70] = 0; + _$jscoverage['plugins/inserthtml.js'][71] = 0; + _$jscoverage['plugins/inserthtml.js'][72] = 0; + _$jscoverage['plugins/inserthtml.js'][73] = 0; + _$jscoverage['plugins/inserthtml.js'][76] = 0; + _$jscoverage['plugins/inserthtml.js'][77] = 0; + _$jscoverage['plugins/inserthtml.js'][78] = 0; + _$jscoverage['plugins/inserthtml.js'][79] = 0; + _$jscoverage['plugins/inserthtml.js'][80] = 0; + _$jscoverage['plugins/inserthtml.js'][81] = 0; + _$jscoverage['plugins/inserthtml.js'][82] = 0; + _$jscoverage['plugins/inserthtml.js'][87] = 0; + _$jscoverage['plugins/inserthtml.js'][88] = 0; + _$jscoverage['plugins/inserthtml.js'][89] = 0; + _$jscoverage['plugins/inserthtml.js'][90] = 0; + _$jscoverage['plugins/inserthtml.js'][91] = 0; + _$jscoverage['plugins/inserthtml.js'][92] = 0; + _$jscoverage['plugins/inserthtml.js'][93] = 0; + _$jscoverage['plugins/inserthtml.js'][95] = 0; + _$jscoverage['plugins/inserthtml.js'][102] = 0; + _$jscoverage['plugins/inserthtml.js'][104] = 0; + _$jscoverage['plugins/inserthtml.js'][105] = 0; + _$jscoverage['plugins/inserthtml.js'][106] = 0; + _$jscoverage['plugins/inserthtml.js'][107] = 0; + _$jscoverage['plugins/inserthtml.js'][108] = 0; + _$jscoverage['plugins/inserthtml.js'][109] = 0; + _$jscoverage['plugins/inserthtml.js'][110] = 0; + _$jscoverage['plugins/inserthtml.js'][111] = 0; + _$jscoverage['plugins/inserthtml.js'][112] = 0; + _$jscoverage['plugins/inserthtml.js'][116] = 0; + _$jscoverage['plugins/inserthtml.js'][117] = 0; + _$jscoverage['plugins/inserthtml.js'][118] = 0; + _$jscoverage['plugins/inserthtml.js'][119] = 0; + _$jscoverage['plugins/inserthtml.js'][121] = 0; + _$jscoverage['plugins/inserthtml.js'][122] = 0; + _$jscoverage['plugins/inserthtml.js'][123] = 0; + _$jscoverage['plugins/inserthtml.js'][124] = 0; + _$jscoverage['plugins/inserthtml.js'][125] = 0; + _$jscoverage['plugins/inserthtml.js'][128] = 0; + _$jscoverage['plugins/inserthtml.js'][129] = 0; + _$jscoverage['plugins/inserthtml.js'][130] = 0; + _$jscoverage['plugins/inserthtml.js'][131] = 0; + _$jscoverage['plugins/inserthtml.js'][132] = 0; + _$jscoverage['plugins/inserthtml.js'][133] = 0; + _$jscoverage['plugins/inserthtml.js'][135] = 0; + _$jscoverage['plugins/inserthtml.js'][137] = 0; + _$jscoverage['plugins/inserthtml.js'][138] = 0; + _$jscoverage['plugins/inserthtml.js'][139] = 0; + _$jscoverage['plugins/inserthtml.js'][140] = 0; + _$jscoverage['plugins/inserthtml.js'][141] = 0; + _$jscoverage['plugins/inserthtml.js'][142] = 0; + _$jscoverage['plugins/inserthtml.js'][143] = 0; + _$jscoverage['plugins/inserthtml.js'][144] = 0; + _$jscoverage['plugins/inserthtml.js'][148] = 0; + _$jscoverage['plugins/inserthtml.js'][149] = 0; + _$jscoverage['plugins/inserthtml.js'][150] = 0; + _$jscoverage['plugins/inserthtml.js'][152] = 0; + _$jscoverage['plugins/inserthtml.js'][154] = 0; + _$jscoverage['plugins/inserthtml.js'][157] = 0; + _$jscoverage['plugins/inserthtml.js'][158] = 0; + _$jscoverage['plugins/inserthtml.js'][159] = 0; + _$jscoverage['plugins/inserthtml.js'][160] = 0; + _$jscoverage['plugins/inserthtml.js'][161] = 0; + _$jscoverage['plugins/inserthtml.js'][162] = 0; + _$jscoverage['plugins/inserthtml.js'][163] = 0; + _$jscoverage['plugins/inserthtml.js'][165] = 0; + _$jscoverage['plugins/inserthtml.js'][167] = 0; + _$jscoverage['plugins/inserthtml.js'][170] = 0; + _$jscoverage['plugins/inserthtml.js'][171] = 0; + _$jscoverage['plugins/inserthtml.js'][172] = 0; + _$jscoverage['plugins/inserthtml.js'][174] = 0; + _$jscoverage['plugins/inserthtml.js'][175] = 0; + _$jscoverage['plugins/inserthtml.js'][176] = 0; + _$jscoverage['plugins/inserthtml.js'][177] = 0; + _$jscoverage['plugins/inserthtml.js'][179] = 0; + _$jscoverage['plugins/inserthtml.js'][180] = 0; + _$jscoverage['plugins/inserthtml.js'][181] = 0; + _$jscoverage['plugins/inserthtml.js'][182] = 0; + _$jscoverage['plugins/inserthtml.js'][188] = 0; + _$jscoverage['plugins/inserthtml.js'][190] = 0; + _$jscoverage['plugins/inserthtml.js'][191] = 0; + _$jscoverage['plugins/inserthtml.js'][192] = 0; + _$jscoverage['plugins/inserthtml.js'][193] = 0; + _$jscoverage['plugins/inserthtml.js'][197] = 0; + _$jscoverage['plugins/inserthtml.js'][202] = 0; + _$jscoverage['plugins/inserthtml.js'][204] = 0; + _$jscoverage['plugins/inserthtml.js'][207] = 0; + _$jscoverage['plugins/inserthtml.js'][208] = 0; + _$jscoverage['plugins/inserthtml.js'][210] = 0; + _$jscoverage['plugins/inserthtml.js'][211] = 0; + _$jscoverage['plugins/inserthtml.js'][213] = 0; + _$jscoverage['plugins/inserthtml.js'][217] = 0; + _$jscoverage['plugins/inserthtml.js'][219] = 0; + _$jscoverage['plugins/inserthtml.js'][220] = 0; + _$jscoverage['plugins/inserthtml.js'][223] = 0; + _$jscoverage['plugins/inserthtml.js'][224] = 0; + _$jscoverage['plugins/inserthtml.js'][225] = 0; + _$jscoverage['plugins/inserthtml.js'][226] = 0; + _$jscoverage['plugins/inserthtml.js'][228] = 0; + _$jscoverage['plugins/inserthtml.js'][232] = 0; + _$jscoverage['plugins/inserthtml.js'][233] = 0; + _$jscoverage['plugins/inserthtml.js'][235] = 0; + _$jscoverage['plugins/inserthtml.js'][236] = 0; + _$jscoverage['plugins/inserthtml.js'][243] = 0; + _$jscoverage['plugins/inserthtml.js'][244] = 0; + _$jscoverage['plugins/inserthtml.js'][251] = 0; + _$jscoverage['plugins/inserthtml.js'][252] = 0; + _$jscoverage['plugins/inserthtml.js'][253] = 0; + _$jscoverage['plugins/inserthtml.js'][254] = 0; +} +_$jscoverage['plugins/inserthtml.js'].source = ["/**"," * 插入html字符串插件"," * @file"," * @since 1.2.6.1"," */","","/**"," * 对编辑器区域插入html字符串"," * @command inserthtml"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param { String } html 插入的html字符串"," * @example"," * ```javascript"," * editor.execCommand( 'insertcode', '<p>我是UEdtior开发者</P>' );"," * ```"," */","/**"," * 对编辑器区域插入html字符串"," * @command inserthtml"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param { String } html 插入的html字符串"," * @param { Bool } notNeedFilter 传true时不走过滤规则,反之要走配置项过滤规则"," * @example"," * ```javascript"," * editor.execCommand( 'inserthtml', '<div>我是UEdtior开发者</div>' ,true);"," * ```"," */","","UE.commands['inserthtml'] = {"," execCommand: function (command,html,notNeedFilter){"," var me = this,"," range,"," div;"," if(!html){"," return;"," }"," if(me.fireEvent('beforeinserthtml',html) === true){"," return;"," }"," range = me.selection.getRange();"," div = range.document.createElement( 'div' );"," div.style.display = 'inline';",""," if (!notNeedFilter) {"," var root = UE.htmlparser(html);"," //如果给了过滤规则就先进行过滤"," if(me.options.filterRules){"," UE.filterNode(root,me.options.filterRules);"," }"," //执行默认的处理"," me.filterInputRule(root);"," html = root.toHtml()"," }"," div.innerHTML = utils.trim( html );",""," if ( !range.collapsed ) {"," var tmpNode = range.startContainer;"," if(domUtils.isFillChar(tmpNode)){"," range.setStartBefore(tmpNode)"," }"," tmpNode = range.endContainer;"," if(domUtils.isFillChar(tmpNode)){"," range.setEndAfter(tmpNode)"," }"," range.txtToElmBoundary();"," //结束边界可能放到了br的前边,要把br包含进来"," // x[xxx]<br/>"," if(range.endContainer && range.endContainer.nodeType == 1){"," tmpNode = range.endContainer.childNodes[range.endOffset];"," if(tmpNode && domUtils.isBr(tmpNode)){"," range.setEndAfter(tmpNode);"," }"," }"," if(range.startOffset == 0){"," tmpNode = range.startContainer;"," if(domUtils.isBoundaryNode(tmpNode,'firstChild') ){"," tmpNode = range.endContainer;"," if(range.endOffset == (tmpNode.nodeType == 3 ? tmpNode.nodeValue.length : tmpNode.childNodes.length) && domUtils.isBoundaryNode(tmpNode,'lastChild')){"," me.body.innerHTML = '<p>'+(browser.ie ? '' : '<br/>')+'</p>';"," range.setStart(me.body.firstChild,0).collapse(true)",""," }"," }"," }"," !range.collapsed && range.deleteContents();"," if(range.startContainer.nodeType == 1){"," var child = range.startContainer.childNodes[range.startOffset],pre;"," if(child && domUtils.isBlockElm(child) && (pre = child.previousSibling) && domUtils.isBlockElm(pre)){"," range.setEnd(pre,pre.childNodes.length).collapse();"," while(child.firstChild){"," pre.appendChild(child.firstChild);"," }"," domUtils.remove(child);"," }"," }",""," }","",""," var child,parent,pre,tmp,hadBreak = 0, nextNode;"," //如果当前位置选中了fillchar要干掉,要不会产生空行"," if(range.inFillChar()){"," child = range.startContainer;"," if(domUtils.isFillChar(child)){"," range.setStartBefore(child).collapse(true);"," domUtils.remove(child);"," }else if(domUtils.isFillChar(child,true)){"," child.nodeValue = child.nodeValue.replace(fillCharReg,'');"," range.startOffset--;"," range.collapsed && range.collapse(true)"," }"," }"," //列表单独处理"," var li = domUtils.findParentByTagName(range.startContainer,'li',true);"," if(li){"," var next,last;"," while(child = div.firstChild){"," //针对hr单独处理一下先"," while(child && (child.nodeType == 3 || !domUtils.isBlockElm(child) || child.tagName=='HR' )){"," next = child.nextSibling;"," range.insertNode( child).collapse();"," last = child;"," child = next;",""," }"," if(child){"," if(/^(ol|ul)$/i.test(child.tagName)){"," while(child.firstChild){"," last = child.firstChild;"," domUtils.insertAfter(li,child.firstChild);"," li = li.nextSibling;"," }"," domUtils.remove(child)"," }else{"," var tmpLi;"," next = child.nextSibling;"," tmpLi = me.document.createElement('li');"," domUtils.insertAfter(li,tmpLi);"," tmpLi.appendChild(child);"," last = child;"," child = next;"," li = tmpLi;"," }"," }"," }"," li = domUtils.findParentByTagName(range.startContainer,'li',true);"," if(domUtils.isEmptyBlock(li)){"," domUtils.remove(li)"," }"," if(last){",""," range.setStartAfter(last).collapse(true).select(true)"," }"," }else{"," while ( child = div.firstChild ) {"," if(hadBreak){"," var p = me.document.createElement('p');"," while(child && (child.nodeType == 3 || !dtd.$block[child.tagName])){"," nextNode = child.nextSibling;"," p.appendChild(child);"," child = nextNode;"," }"," if(p.firstChild){",""," child = p"," }"," }"," range.insertNode( child );"," nextNode = child.nextSibling;"," if ( !hadBreak && child.nodeType == domUtils.NODE_ELEMENT && domUtils.isBlockElm( child ) ){",""," parent = domUtils.findParent( child,function ( node ){ return domUtils.isBlockElm( node ); } );"," if ( parent && parent.tagName.toLowerCase() != 'body' && !(dtd[parent.tagName][child.nodeName] && child.parentNode === parent)){"," if(!dtd[parent.tagName][child.nodeName]){"," pre = parent;"," }else{"," tmp = child.parentNode;"," while (tmp !== parent){"," pre = tmp;"," tmp = tmp.parentNode;",""," }"," }","",""," domUtils.breakParent( child, pre || tmp );"," //去掉break后前一个多余的节点 <p>|<[p> ==> <p></p><div></div><p>|</p>"," var pre = child.previousSibling;"," domUtils.trimWhiteTextNode(pre);"," if(!pre.childNodes.length){"," domUtils.remove(pre);"," }"," //trace:2012,在非ie的情况,切开后剩下的节点有可能不能点入光标添加br占位",""," if(!browser.ie &&"," (next = child.nextSibling) &&"," domUtils.isBlockElm(next) &&"," next.lastChild &&"," !domUtils.isBr(next.lastChild)){"," next.appendChild(me.document.createElement('br'));"," }"," hadBreak = 1;"," }"," }"," var next = child.nextSibling;"," if(!div.firstChild && next && domUtils.isBlockElm(next)){",""," range.setStart(next,0).collapse(true);"," break;"," }"," range.setEndAfter( child ).collapse();",""," }",""," child = range.startContainer;",""," if(nextNode && domUtils.isBr(nextNode)){"," domUtils.remove(nextNode)"," }"," //用chrome可能有空白展位符"," if(domUtils.isBlockElm(child) && domUtils.isEmptyNode(child)){"," if(nextNode = child.nextSibling){"," domUtils.remove(child);"," if(nextNode.nodeType == 1 && dtd.$block[nextNode.tagName]){",""," range.setStart(nextNode,0).collapse(true).shrinkBoundary()"," }"," }else{",""," try{"," child.innerHTML = browser.ie ? domUtils.fillChar : '<br/>';"," }catch(e){"," range.setStartBefore(child);"," domUtils.remove(child)"," }",""," }",""," }"," //加上true因为在删除表情等时会删两次,第一次是删的fillData"," try{"," range.select(true);"," }catch(e){}",""," }","","",""," setTimeout(function(){"," range = me.selection.getRange();"," range.scrollToView(me.autoHeightEnabled,me.autoHeightEnabled ? domUtils.getXY(me.iframe).y:0);"," me.fireEvent('afterinserthtml');"," },200);"," }","};"]; +_$jscoverage['plugins/inserthtml.js'][31]++; +UE.commands.inserthtml = {execCommand: (function (command, html, notNeedFilter) { + _$jscoverage['plugins/inserthtml.js'][33]++; + var me = this, range, div; + _$jscoverage['plugins/inserthtml.js'][36]++; + if ((! html)) { + _$jscoverage['plugins/inserthtml.js'][37]++; + return; + } + _$jscoverage['plugins/inserthtml.js'][39]++; + if ((me.fireEvent("beforeinserthtml", html) === true)) { + _$jscoverage['plugins/inserthtml.js'][40]++; + return; + } + _$jscoverage['plugins/inserthtml.js'][42]++; + range = me.selection.getRange(); + _$jscoverage['plugins/inserthtml.js'][43]++; + div = range.document.createElement("div"); + _$jscoverage['plugins/inserthtml.js'][44]++; + div.style.display = "inline"; + _$jscoverage['plugins/inserthtml.js'][46]++; + if ((! notNeedFilter)) { + _$jscoverage['plugins/inserthtml.js'][47]++; + var root = UE.htmlparser(html); + _$jscoverage['plugins/inserthtml.js'][49]++; + if (me.options.filterRules) { + _$jscoverage['plugins/inserthtml.js'][50]++; + UE.filterNode(root, me.options.filterRules); + } + _$jscoverage['plugins/inserthtml.js'][53]++; + me.filterInputRule(root); + _$jscoverage['plugins/inserthtml.js'][54]++; + html = root.toHtml(); + } + _$jscoverage['plugins/inserthtml.js'][56]++; + div.innerHTML = utils.trim(html); + _$jscoverage['plugins/inserthtml.js'][58]++; + if ((! range.collapsed)) { + _$jscoverage['plugins/inserthtml.js'][59]++; + var tmpNode = range.startContainer; + _$jscoverage['plugins/inserthtml.js'][60]++; + if (domUtils.isFillChar(tmpNode)) { + _$jscoverage['plugins/inserthtml.js'][61]++; + range.setStartBefore(tmpNode); + } + _$jscoverage['plugins/inserthtml.js'][63]++; + tmpNode = range.endContainer; + _$jscoverage['plugins/inserthtml.js'][64]++; + if (domUtils.isFillChar(tmpNode)) { + _$jscoverage['plugins/inserthtml.js'][65]++; + range.setEndAfter(tmpNode); + } + _$jscoverage['plugins/inserthtml.js'][67]++; + range.txtToElmBoundary(); + _$jscoverage['plugins/inserthtml.js'][70]++; + if ((range.endContainer && (range.endContainer.nodeType == 1))) { + _$jscoverage['plugins/inserthtml.js'][71]++; + tmpNode = range.endContainer.childNodes[range.endOffset]; + _$jscoverage['plugins/inserthtml.js'][72]++; + if ((tmpNode && domUtils.isBr(tmpNode))) { + _$jscoverage['plugins/inserthtml.js'][73]++; + range.setEndAfter(tmpNode); + } + } + _$jscoverage['plugins/inserthtml.js'][76]++; + if ((range.startOffset == 0)) { + _$jscoverage['plugins/inserthtml.js'][77]++; + tmpNode = range.startContainer; + _$jscoverage['plugins/inserthtml.js'][78]++; + if (domUtils.isBoundaryNode(tmpNode, "firstChild")) { + _$jscoverage['plugins/inserthtml.js'][79]++; + tmpNode = range.endContainer; + _$jscoverage['plugins/inserthtml.js'][80]++; + if (((range.endOffset == ((tmpNode.nodeType == 3)? tmpNode.nodeValue.length: tmpNode.childNodes.length)) && domUtils.isBoundaryNode(tmpNode, "lastChild"))) { + _$jscoverage['plugins/inserthtml.js'][81]++; + me.body.innerHTML = ("

    " + (browser.ie? "": "
    ") + "

    "); + _$jscoverage['plugins/inserthtml.js'][82]++; + range.setStart(me.body.firstChild, 0).collapse(true); + } + } + } + _$jscoverage['plugins/inserthtml.js'][87]++; + ((! range.collapsed) && range.deleteContents()); + _$jscoverage['plugins/inserthtml.js'][88]++; + if ((range.startContainer.nodeType == 1)) { + _$jscoverage['plugins/inserthtml.js'][89]++; + var child = range.startContainer.childNodes[range.startOffset], pre; + _$jscoverage['plugins/inserthtml.js'][90]++; + if ((child && domUtils.isBlockElm(child) && (pre = child.previousSibling) && domUtils.isBlockElm(pre))) { + _$jscoverage['plugins/inserthtml.js'][91]++; + range.setEnd(pre, pre.childNodes.length).collapse(); + _$jscoverage['plugins/inserthtml.js'][92]++; + while (child.firstChild) { + _$jscoverage['plugins/inserthtml.js'][93]++; + pre.appendChild(child.firstChild); +} + _$jscoverage['plugins/inserthtml.js'][95]++; + domUtils.remove(child); + } + } + } + _$jscoverage['plugins/inserthtml.js'][102]++; + var child = child, parent, pre = pre, tmp, hadBreak = 0, nextNode; + _$jscoverage['plugins/inserthtml.js'][104]++; + if (range.inFillChar()) { + _$jscoverage['plugins/inserthtml.js'][105]++; + child = range.startContainer; + _$jscoverage['plugins/inserthtml.js'][106]++; + if (domUtils.isFillChar(child)) { + _$jscoverage['plugins/inserthtml.js'][107]++; + range.setStartBefore(child).collapse(true); + _$jscoverage['plugins/inserthtml.js'][108]++; + domUtils.remove(child); + } + else { + _$jscoverage['plugins/inserthtml.js'][109]++; + if (domUtils.isFillChar(child, true)) { + _$jscoverage['plugins/inserthtml.js'][110]++; + child.nodeValue = child.nodeValue.replace(fillCharReg, ""); + _$jscoverage['plugins/inserthtml.js'][111]++; + (range.startOffset--); + _$jscoverage['plugins/inserthtml.js'][112]++; + (range.collapsed && range.collapse(true)); + } + } + } + _$jscoverage['plugins/inserthtml.js'][116]++; + var li = domUtils.findParentByTagName(range.startContainer, "li", true); + _$jscoverage['plugins/inserthtml.js'][117]++; + if (li) { + _$jscoverage['plugins/inserthtml.js'][118]++; + var next, last; + _$jscoverage['plugins/inserthtml.js'][119]++; + while ((child = div.firstChild)) { + _$jscoverage['plugins/inserthtml.js'][121]++; + while ((child && ((child.nodeType == 3) || (! domUtils.isBlockElm(child)) || (child.tagName == "HR")))) { + _$jscoverage['plugins/inserthtml.js'][122]++; + next = child.nextSibling; + _$jscoverage['plugins/inserthtml.js'][123]++; + range.insertNode(child).collapse(); + _$jscoverage['plugins/inserthtml.js'][124]++; + last = child; + _$jscoverage['plugins/inserthtml.js'][125]++; + child = next; +} + _$jscoverage['plugins/inserthtml.js'][128]++; + if (child) { + _$jscoverage['plugins/inserthtml.js'][129]++; + if (/^(ol|ul)$/i.test(child.tagName)) { + _$jscoverage['plugins/inserthtml.js'][130]++; + while (child.firstChild) { + _$jscoverage['plugins/inserthtml.js'][131]++; + last = child.firstChild; + _$jscoverage['plugins/inserthtml.js'][132]++; + domUtils.insertAfter(li, child.firstChild); + _$jscoverage['plugins/inserthtml.js'][133]++; + li = li.nextSibling; +} + _$jscoverage['plugins/inserthtml.js'][135]++; + domUtils.remove(child); + } + else { + _$jscoverage['plugins/inserthtml.js'][137]++; + var tmpLi; + _$jscoverage['plugins/inserthtml.js'][138]++; + next = child.nextSibling; + _$jscoverage['plugins/inserthtml.js'][139]++; + tmpLi = me.document.createElement("li"); + _$jscoverage['plugins/inserthtml.js'][140]++; + domUtils.insertAfter(li, tmpLi); + _$jscoverage['plugins/inserthtml.js'][141]++; + tmpLi.appendChild(child); + _$jscoverage['plugins/inserthtml.js'][142]++; + last = child; + _$jscoverage['plugins/inserthtml.js'][143]++; + child = next; + _$jscoverage['plugins/inserthtml.js'][144]++; + li = tmpLi; + } + } +} + _$jscoverage['plugins/inserthtml.js'][148]++; + li = domUtils.findParentByTagName(range.startContainer, "li", true); + _$jscoverage['plugins/inserthtml.js'][149]++; + if (domUtils.isEmptyBlock(li)) { + _$jscoverage['plugins/inserthtml.js'][150]++; + domUtils.remove(li); + } + _$jscoverage['plugins/inserthtml.js'][152]++; + if (last) { + _$jscoverage['plugins/inserthtml.js'][154]++; + range.setStartAfter(last).collapse(true).select(true); + } + } + else { + _$jscoverage['plugins/inserthtml.js'][157]++; + while ((child = div.firstChild)) { + _$jscoverage['plugins/inserthtml.js'][158]++; + if (hadBreak) { + _$jscoverage['plugins/inserthtml.js'][159]++; + var p = me.document.createElement("p"); + _$jscoverage['plugins/inserthtml.js'][160]++; + while ((child && ((child.nodeType == 3) || (! dtd.$block[child.tagName])))) { + _$jscoverage['plugins/inserthtml.js'][161]++; + nextNode = child.nextSibling; + _$jscoverage['plugins/inserthtml.js'][162]++; + p.appendChild(child); + _$jscoverage['plugins/inserthtml.js'][163]++; + child = nextNode; +} + _$jscoverage['plugins/inserthtml.js'][165]++; + if (p.firstChild) { + _$jscoverage['plugins/inserthtml.js'][167]++; + child = p; + } + } + _$jscoverage['plugins/inserthtml.js'][170]++; + range.insertNode(child); + _$jscoverage['plugins/inserthtml.js'][171]++; + nextNode = child.nextSibling; + _$jscoverage['plugins/inserthtml.js'][172]++; + if (((! hadBreak) && (child.nodeType == domUtils.NODE_ELEMENT) && domUtils.isBlockElm(child))) { + _$jscoverage['plugins/inserthtml.js'][174]++; + parent = domUtils.findParent(child, (function (node) { + _$jscoverage['plugins/inserthtml.js'][174]++; + return domUtils.isBlockElm(node); +})); + _$jscoverage['plugins/inserthtml.js'][175]++; + if ((parent && (parent.tagName.toLowerCase() != "body") && (! (dtd[parent.tagName][child.nodeName] && (child.parentNode === parent))))) { + _$jscoverage['plugins/inserthtml.js'][176]++; + if ((! dtd[parent.tagName][child.nodeName])) { + _$jscoverage['plugins/inserthtml.js'][177]++; + pre = parent; + } + else { + _$jscoverage['plugins/inserthtml.js'][179]++; + tmp = child.parentNode; + _$jscoverage['plugins/inserthtml.js'][180]++; + while ((tmp !== parent)) { + _$jscoverage['plugins/inserthtml.js'][181]++; + pre = tmp; + _$jscoverage['plugins/inserthtml.js'][182]++; + tmp = tmp.parentNode; +} + } + _$jscoverage['plugins/inserthtml.js'][188]++; + domUtils.breakParent(child, (pre || tmp)); + _$jscoverage['plugins/inserthtml.js'][190]++; + var pre = child.previousSibling; + _$jscoverage['plugins/inserthtml.js'][191]++; + domUtils.trimWhiteTextNode(pre); + _$jscoverage['plugins/inserthtml.js'][192]++; + if ((! pre.childNodes.length)) { + _$jscoverage['plugins/inserthtml.js'][193]++; + domUtils.remove(pre); + } + _$jscoverage['plugins/inserthtml.js'][197]++; + if (((! browser.ie) && (next = child.nextSibling) && domUtils.isBlockElm(next) && next.lastChild && (! domUtils.isBr(next.lastChild)))) { + _$jscoverage['plugins/inserthtml.js'][202]++; + next.appendChild(me.document.createElement("br")); + } + _$jscoverage['plugins/inserthtml.js'][204]++; + hadBreak = 1; + } + } + _$jscoverage['plugins/inserthtml.js'][207]++; + var next = child.nextSibling; + _$jscoverage['plugins/inserthtml.js'][208]++; + if (((! div.firstChild) && next && domUtils.isBlockElm(next))) { + _$jscoverage['plugins/inserthtml.js'][210]++; + range.setStart(next, 0).collapse(true); + _$jscoverage['plugins/inserthtml.js'][211]++; + break; + } + _$jscoverage['plugins/inserthtml.js'][213]++; + range.setEndAfter(child).collapse(); +} + _$jscoverage['plugins/inserthtml.js'][217]++; + child = range.startContainer; + _$jscoverage['plugins/inserthtml.js'][219]++; + if ((nextNode && domUtils.isBr(nextNode))) { + _$jscoverage['plugins/inserthtml.js'][220]++; + domUtils.remove(nextNode); + } + _$jscoverage['plugins/inserthtml.js'][223]++; + if ((domUtils.isBlockElm(child) && domUtils.isEmptyNode(child))) { + _$jscoverage['plugins/inserthtml.js'][224]++; + if ((nextNode = child.nextSibling)) { + _$jscoverage['plugins/inserthtml.js'][225]++; + domUtils.remove(child); + _$jscoverage['plugins/inserthtml.js'][226]++; + if (((nextNode.nodeType == 1) && dtd.$block[nextNode.tagName])) { + _$jscoverage['plugins/inserthtml.js'][228]++; + range.setStart(nextNode, 0).collapse(true).shrinkBoundary(); + } + } + else { + _$jscoverage['plugins/inserthtml.js'][232]++; + try { + _$jscoverage['plugins/inserthtml.js'][233]++; + child.innerHTML = (browser.ie? domUtils.fillChar: "
    "); + } + catch (e) { + _$jscoverage['plugins/inserthtml.js'][235]++; + range.setStartBefore(child); + _$jscoverage['plugins/inserthtml.js'][236]++; + domUtils.remove(child); + } + } + } + _$jscoverage['plugins/inserthtml.js'][243]++; + try { + _$jscoverage['plugins/inserthtml.js'][244]++; + range.select(true); + } + catch (e) { + } + } + _$jscoverage['plugins/inserthtml.js'][251]++; + setTimeout((function () { + _$jscoverage['plugins/inserthtml.js'][252]++; + range = me.selection.getRange(); + _$jscoverage['plugins/inserthtml.js'][253]++; + range.scrollToView(me.autoHeightEnabled, (me.autoHeightEnabled? domUtils.getXY(me.iframe).y: 0)); + _$jscoverage['plugins/inserthtml.js'][254]++; + me.fireEvent("afterinserthtml"); +}), 200); +})}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/insertparagraph.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/insertparagraph.js new file mode 100644 index 000000000..d95607770 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/insertparagraph.js @@ -0,0 +1,92 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/insertparagraph.js']) { + _$jscoverage['plugins/insertparagraph.js'] = []; + _$jscoverage['plugins/insertparagraph.js'][20] = 0; + _$jscoverage['plugins/insertparagraph.js'][22] = 0; + _$jscoverage['plugins/insertparagraph.js'][25] = 0; + _$jscoverage['plugins/insertparagraph.js'][26] = 0; + _$jscoverage['plugins/insertparagraph.js'][27] = 0; + _$jscoverage['plugins/insertparagraph.js'][29] = 0; + _$jscoverage['plugins/insertparagraph.js'][30] = 0; + _$jscoverage['plugins/insertparagraph.js'][32] = 0; + _$jscoverage['plugins/insertparagraph.js'][33] = 0; + _$jscoverage['plugins/insertparagraph.js'][34] = 0; + _$jscoverage['plugins/insertparagraph.js'][35] = 0; + _$jscoverage['plugins/insertparagraph.js'][37] = 0; + _$jscoverage['plugins/insertparagraph.js'][39] = 0; + _$jscoverage['plugins/insertparagraph.js'][40] = 0; +} +_$jscoverage['plugins/insertparagraph.js'].source = ["/**"," * 插入新的段落"," * @file"," * @since 1.2.6.1"," */","","","/**"," * 在当前光标位置处插入新段落, 如果光标已经在段落之中, 则会在该段落之后插入一个新的段落。"," * @command insertparagraph"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * //editor是编辑器实例"," * editor.execCommand( 'insertparagraph' );"," * ```"," */","","UE.commands['insertparagraph'] = {"," execCommand : function( cmdName,front) {"," var me = this,"," range = me.selection.getRange(),"," start = range.startContainer,tmpNode;"," while(start ){"," if(domUtils.isBody(start)){"," break;"," }"," tmpNode = start;"," start = start.parentNode;"," }"," if(tmpNode){"," var p = me.document.createElement('p');"," if(front){"," tmpNode.parentNode.insertBefore(p,tmpNode)"," }else{"," tmpNode.parentNode.insertBefore(p,tmpNode.nextSibling)"," }"," domUtils.fillNode(me.document,p);"," range.setStart(p,0).setCursor(false,true);"," }"," }","};",""]; +_$jscoverage['plugins/insertparagraph.js'][20]++; +UE.commands.insertparagraph = {execCommand: (function (cmdName, front) { + _$jscoverage['plugins/insertparagraph.js'][22]++; + var me = this, range = me.selection.getRange(), start = range.startContainer, tmpNode; + _$jscoverage['plugins/insertparagraph.js'][25]++; + while (start) { + _$jscoverage['plugins/insertparagraph.js'][26]++; + if (domUtils.isBody(start)) { + _$jscoverage['plugins/insertparagraph.js'][27]++; + break; + } + _$jscoverage['plugins/insertparagraph.js'][29]++; + tmpNode = start; + _$jscoverage['plugins/insertparagraph.js'][30]++; + start = start.parentNode; +} + _$jscoverage['plugins/insertparagraph.js'][32]++; + if (tmpNode) { + _$jscoverage['plugins/insertparagraph.js'][33]++; + var p = me.document.createElement("p"); + _$jscoverage['plugins/insertparagraph.js'][34]++; + if (front) { + _$jscoverage['plugins/insertparagraph.js'][35]++; + tmpNode.parentNode.insertBefore(p, tmpNode); + } + else { + _$jscoverage['plugins/insertparagraph.js'][37]++; + tmpNode.parentNode.insertBefore(p, tmpNode.nextSibling); + } + _$jscoverage['plugins/insertparagraph.js'][39]++; + domUtils.fillNode(me.document, p); + _$jscoverage['plugins/insertparagraph.js'][40]++; + range.setStart(p, 0).setCursor(false, true); + } +})}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/justify.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/justify.js new file mode 100644 index 000000000..ebe5ef7f1 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/justify.js @@ -0,0 +1,186 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/justify.js']) { + _$jscoverage['plugins/justify.js'] = []; + _$jscoverage['plugins/justify.js'][40] = 0; + _$jscoverage['plugins/justify.js'][41] = 0; + _$jscoverage['plugins/justify.js'][50] = 0; + _$jscoverage['plugins/justify.js'][52] = 0; + _$jscoverage['plugins/justify.js'][55] = 0; + _$jscoverage['plugins/justify.js'][56] = 0; + _$jscoverage['plugins/justify.js'][60] = 0; + _$jscoverage['plugins/justify.js'][61] = 0; + _$jscoverage['plugins/justify.js'][62] = 0; + _$jscoverage['plugins/justify.js'][63] = 0; + _$jscoverage['plugins/justify.js'][64] = 0; + _$jscoverage['plugins/justify.js'][65] = 0; + _$jscoverage['plugins/justify.js'][66] = 0; + _$jscoverage['plugins/justify.js'][69] = 0; + _$jscoverage['plugins/justify.js'][70] = 0; + _$jscoverage['plugins/justify.js'][71] = 0; + _$jscoverage['plugins/justify.js'][72] = 0; + _$jscoverage['plugins/justify.js'][73] = 0; + _$jscoverage['plugins/justify.js'][75] = 0; + _$jscoverage['plugins/justify.js'][76] = 0; + _$jscoverage['plugins/justify.js'][77] = 0; + _$jscoverage['plugins/justify.js'][78] = 0; + _$jscoverage['plugins/justify.js'][79] = 0; + _$jscoverage['plugins/justify.js'][80] = 0; + _$jscoverage['plugins/justify.js'][82] = 0; + _$jscoverage['plugins/justify.js'][84] = 0; + _$jscoverage['plugins/justify.js'][87] = 0; + _$jscoverage['plugins/justify.js'][90] = 0; + _$jscoverage['plugins/justify.js'][92] = 0; + _$jscoverage['plugins/justify.js'][96] = 0; + _$jscoverage['plugins/justify.js'][97] = 0; + _$jscoverage['plugins/justify.js'][98] = 0; + _$jscoverage['plugins/justify.js'][100] = 0; + _$jscoverage['plugins/justify.js'][101] = 0; + _$jscoverage['plugins/justify.js'][102] = 0; + _$jscoverage['plugins/justify.js'][103] = 0; + _$jscoverage['plugins/justify.js'][106] = 0; + _$jscoverage['plugins/justify.js'][109] = 0; + _$jscoverage['plugins/justify.js'][112] = 0; + _$jscoverage['plugins/justify.js'][114] = 0; + _$jscoverage['plugins/justify.js'][117] = 0; + _$jscoverage['plugins/justify.js'][120] = 0; +} +_$jscoverage['plugins/justify.js'].source = ["/**"," * 段落格式"," * @file"," * @since 1.2.6.1"," */","","/**"," * 对段落居左,居右,居中,两端对齐"," * @command justify"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param { String } align 对齐方式:left居左,right居右,center居中,justify两端对齐"," * @example"," * ```javascript"," * editor.execCommand( 'justify', 'center' );"," * ```"," */","/**"," * 如果选区所在位置是段落区域,返回当前段落对齐方式"," * @command justify"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { String } 返回图片对齐方式"," * @example"," * ```javascript"," * editor.queryCommandValue( 'justify' );"," * ```"," */","/**"," * 返回当前选区位置是否是图片"," * @command justify"," * @method queryCommandState"," * @param { String } cmd 命令字符串"," * @return { Int } 0为是,-1为不是"," * @example"," * ```javascript"," * editor.queryCommandState( 'justify' );"," * ```"," */","UE.plugins['justify']=function(){"," var me=this,"," block = domUtils.isBlockElm,"," defaultValue = {"," left:1,"," right:1,"," center:1,"," justify:1"," },"," doJustify = function (range, style) {"," var bookmark = range.createBookmark(),"," filterFn = function (node) {"," return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' && !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace(node);"," };",""," range.enlarge(true);"," var bookmark2 = range.createBookmark(),"," current = domUtils.getNextDomNode(bookmark2.start, false, filterFn),"," tmpRange = range.cloneRange(),"," tmpNode;"," while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {"," if (current.nodeType == 3 || !block(current)) {"," tmpRange.setStartBefore(current);"," while (current && current !== bookmark2.end && !block(current)) {"," tmpNode = current;"," current = domUtils.getNextDomNode(current, false, null, function (node) {"," return !block(node);"," });"," }"," tmpRange.setEndAfter(tmpNode);"," var common = tmpRange.getCommonAncestor();"," if (!domUtils.isBody(common) && block(common)) {"," domUtils.setStyles(common, utils.isString(style) ? {'text-align':style} : style);"," current = common;"," } else {"," var p = range.document.createElement('p');"," domUtils.setStyles(p, utils.isString(style) ? {'text-align':style} : style);"," var frag = tmpRange.extractContents();"," p.appendChild(frag);"," tmpRange.insertNode(p);"," current = p;"," }"," current = domUtils.getNextDomNode(current, false, filterFn);"," } else {"," current = domUtils.getNextDomNode(current, true, filterFn);"," }"," }"," return range.moveToBookmark(bookmark2).moveToBookmark(bookmark);"," };",""," UE.commands['justify'] = {"," execCommand:function (cmdName, align) {"," var range = this.selection.getRange(),"," txt;",""," //闭合时单独处理"," if (range.collapsed) {"," txt = this.document.createTextNode('p');"," range.insertNode(txt);"," }"," doJustify(range, align);"," if (txt) {"," range.setStartBefore(txt).collapse(true);"," domUtils.remove(txt);"," }",""," range.select();","",""," return true;"," },"," queryCommandValue:function () {"," var startNode = this.selection.getStart(),"," value = domUtils.getComputedStyle(startNode, 'text-align');"," return defaultValue[value] ? value : 'left';"," },"," queryCommandState:function () {"," var start = this.selection.getStart(),"," cell = start && domUtils.findParentByTagName(start, [\"td\", \"th\",\"caption\"], true);",""," return cell? -1:0;"," }",""," };","};"]; +_$jscoverage['plugins/justify.js'][40]++; +UE.plugins.justify = (function () { + _$jscoverage['plugins/justify.js'][41]++; + var me = this, block = domUtils.isBlockElm, defaultValue = {left: 1, right: 1, center: 1, justify: 1}, doJustify = (function (range, style) { + _$jscoverage['plugins/justify.js'][50]++; + var bookmark = range.createBookmark(), filterFn = (function (node) { + _$jscoverage['plugins/justify.js'][52]++; + return ((node.nodeType == 1)? ((node.tagName.toLowerCase() != "br") && (! domUtils.isBookmarkNode(node))): (! domUtils.isWhitespace(node))); +}); + _$jscoverage['plugins/justify.js'][55]++; + range.enlarge(true); + _$jscoverage['plugins/justify.js'][56]++; + var bookmark2 = range.createBookmark(), current = domUtils.getNextDomNode(bookmark2.start, false, filterFn), tmpRange = range.cloneRange(), tmpNode; + _$jscoverage['plugins/justify.js'][60]++; + while ((current && (! (domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)))) { + _$jscoverage['plugins/justify.js'][61]++; + if (((current.nodeType == 3) || (! block(current)))) { + _$jscoverage['plugins/justify.js'][62]++; + tmpRange.setStartBefore(current); + _$jscoverage['plugins/justify.js'][63]++; + while ((current && (current !== bookmark2.end) && (! block(current)))) { + _$jscoverage['plugins/justify.js'][64]++; + tmpNode = current; + _$jscoverage['plugins/justify.js'][65]++; + current = domUtils.getNextDomNode(current, false, null, (function (node) { + _$jscoverage['plugins/justify.js'][66]++; + return (! block(node)); +})); +} + _$jscoverage['plugins/justify.js'][69]++; + tmpRange.setEndAfter(tmpNode); + _$jscoverage['plugins/justify.js'][70]++; + var common = tmpRange.getCommonAncestor(); + _$jscoverage['plugins/justify.js'][71]++; + if (((! domUtils.isBody(common)) && block(common))) { + _$jscoverage['plugins/justify.js'][72]++; + domUtils.setStyles(common, (utils.isString(style)? {"text-align": style}: style)); + _$jscoverage['plugins/justify.js'][73]++; + current = common; + } + else { + _$jscoverage['plugins/justify.js'][75]++; + var p = range.document.createElement("p"); + _$jscoverage['plugins/justify.js'][76]++; + domUtils.setStyles(p, (utils.isString(style)? {"text-align": style}: style)); + _$jscoverage['plugins/justify.js'][77]++; + var frag = tmpRange.extractContents(); + _$jscoverage['plugins/justify.js'][78]++; + p.appendChild(frag); + _$jscoverage['plugins/justify.js'][79]++; + tmpRange.insertNode(p); + _$jscoverage['plugins/justify.js'][80]++; + current = p; + } + _$jscoverage['plugins/justify.js'][82]++; + current = domUtils.getNextDomNode(current, false, filterFn); + } + else { + _$jscoverage['plugins/justify.js'][84]++; + current = domUtils.getNextDomNode(current, true, filterFn); + } +} + _$jscoverage['plugins/justify.js'][87]++; + return range.moveToBookmark(bookmark2).moveToBookmark(bookmark); +}); + _$jscoverage['plugins/justify.js'][90]++; + UE.commands.justify = {execCommand: (function (cmdName, align) { + _$jscoverage['plugins/justify.js'][92]++; + var range = this.selection.getRange(), txt; + _$jscoverage['plugins/justify.js'][96]++; + if (range.collapsed) { + _$jscoverage['plugins/justify.js'][97]++; + txt = this.document.createTextNode("p"); + _$jscoverage['plugins/justify.js'][98]++; + range.insertNode(txt); + } + _$jscoverage['plugins/justify.js'][100]++; + doJustify(range, align); + _$jscoverage['plugins/justify.js'][101]++; + if (txt) { + _$jscoverage['plugins/justify.js'][102]++; + range.setStartBefore(txt).collapse(true); + _$jscoverage['plugins/justify.js'][103]++; + domUtils.remove(txt); + } + _$jscoverage['plugins/justify.js'][106]++; + range.select(); + _$jscoverage['plugins/justify.js'][109]++; + return true; +}), queryCommandValue: (function () { + _$jscoverage['plugins/justify.js'][112]++; + var startNode = this.selection.getStart(), value = domUtils.getComputedStyle(startNode, "text-align"); + _$jscoverage['plugins/justify.js'][114]++; + return (defaultValue[value]? value: "left"); +}), queryCommandState: (function () { + _$jscoverage['plugins/justify.js'][117]++; + var start = this.selection.getStart(), cell = (start && domUtils.findParentByTagName(start, ["td", "th", "caption"], true)); + _$jscoverage['plugins/justify.js'][120]++; + return (cell? -1: 0); +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/keystrokes.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/keystrokes.js new file mode 100644 index 000000000..6be9a96d8 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/keystrokes.js @@ -0,0 +1,465 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/keystrokes.js']) { + _$jscoverage['plugins/keystrokes.js'] = []; + _$jscoverage['plugins/keystrokes.js'][4] = 0; + _$jscoverage['plugins/keystrokes.js'][5] = 0; + _$jscoverage['plugins/keystrokes.js'][6] = 0; + _$jscoverage['plugins/keystrokes.js'][7] = 0; + _$jscoverage['plugins/keystrokes.js'][8] = 0; + _$jscoverage['plugins/keystrokes.js'][12] = 0; + _$jscoverage['plugins/keystrokes.js'][21] = 0; + _$jscoverage['plugins/keystrokes.js'][22] = 0; + _$jscoverage['plugins/keystrokes.js'][23] = 0; + _$jscoverage['plugins/keystrokes.js'][25] = 0; + _$jscoverage['plugins/keystrokes.js'][26] = 0; + _$jscoverage['plugins/keystrokes.js'][27] = 0; + _$jscoverage['plugins/keystrokes.js'][29] = 0; + _$jscoverage['plugins/keystrokes.js'][32] = 0; + _$jscoverage['plugins/keystrokes.js'][33] = 0; + _$jscoverage['plugins/keystrokes.js'][34] = 0; + _$jscoverage['plugins/keystrokes.js'][35] = 0; + _$jscoverage['plugins/keystrokes.js'][38] = 0; + _$jscoverage['plugins/keystrokes.js'][39] = 0; + _$jscoverage['plugins/keystrokes.js'][40] = 0; + _$jscoverage['plugins/keystrokes.js'][41] = 0; + _$jscoverage['plugins/keystrokes.js'][42] = 0; + _$jscoverage['plugins/keystrokes.js'][43] = 0; + _$jscoverage['plugins/keystrokes.js'][44] = 0; + _$jscoverage['plugins/keystrokes.js'][45] = 0; + _$jscoverage['plugins/keystrokes.js'][46] = 0; + _$jscoverage['plugins/keystrokes.js'][47] = 0; + _$jscoverage['plugins/keystrokes.js'][54] = 0; + _$jscoverage['plugins/keystrokes.js'][55] = 0; + _$jscoverage['plugins/keystrokes.js'][56] = 0; + _$jscoverage['plugins/keystrokes.js'][57] = 0; + _$jscoverage['plugins/keystrokes.js'][58] = 0; + _$jscoverage['plugins/keystrokes.js'][60] = 0; + _$jscoverage['plugins/keystrokes.js'][62] = 0; + _$jscoverage['plugins/keystrokes.js'][63] = 0; + _$jscoverage['plugins/keystrokes.js'][65] = 0; + _$jscoverage['plugins/keystrokes.js'][66] = 0; + _$jscoverage['plugins/keystrokes.js'][67] = 0; + _$jscoverage['plugins/keystrokes.js'][69] = 0; + _$jscoverage['plugins/keystrokes.js'][70] = 0; + _$jscoverage['plugins/keystrokes.js'][71] = 0; + _$jscoverage['plugins/keystrokes.js'][76] = 0; + _$jscoverage['plugins/keystrokes.js'][77] = 0; + _$jscoverage['plugins/keystrokes.js'][78] = 0; + _$jscoverage['plugins/keystrokes.js'][79] = 0; + _$jscoverage['plugins/keystrokes.js'][80] = 0; + _$jscoverage['plugins/keystrokes.js'][81] = 0; + _$jscoverage['plugins/keystrokes.js'][82] = 0; + _$jscoverage['plugins/keystrokes.js'][83] = 0; + _$jscoverage['plugins/keystrokes.js'][86] = 0; + _$jscoverage['plugins/keystrokes.js'][87] = 0; + _$jscoverage['plugins/keystrokes.js'][88] = 0; + _$jscoverage['plugins/keystrokes.js'][89] = 0; + _$jscoverage['plugins/keystrokes.js'][90] = 0; + _$jscoverage['plugins/keystrokes.js'][91] = 0; + _$jscoverage['plugins/keystrokes.js'][97] = 0; + _$jscoverage['plugins/keystrokes.js'][99] = 0; + _$jscoverage['plugins/keystrokes.js'][105] = 0; + _$jscoverage['plugins/keystrokes.js'][106] = 0; + _$jscoverage['plugins/keystrokes.js'][107] = 0; + _$jscoverage['plugins/keystrokes.js'][109] = 0; + _$jscoverage['plugins/keystrokes.js'][110] = 0; + _$jscoverage['plugins/keystrokes.js'][111] = 0; + _$jscoverage['plugins/keystrokes.js'][112] = 0; + _$jscoverage['plugins/keystrokes.js'][114] = 0; + _$jscoverage['plugins/keystrokes.js'][115] = 0; + _$jscoverage['plugins/keystrokes.js'][116] = 0; + _$jscoverage['plugins/keystrokes.js'][117] = 0; + _$jscoverage['plugins/keystrokes.js'][120] = 0; + _$jscoverage['plugins/keystrokes.js'][121] = 0; + _$jscoverage['plugins/keystrokes.js'][122] = 0; + _$jscoverage['plugins/keystrokes.js'][123] = 0; + _$jscoverage['plugins/keystrokes.js'][124] = 0; + _$jscoverage['plugins/keystrokes.js'][126] = 0; + _$jscoverage['plugins/keystrokes.js'][128] = 0; + _$jscoverage['plugins/keystrokes.js'][131] = 0; + _$jscoverage['plugins/keystrokes.js'][132] = 0; + _$jscoverage['plugins/keystrokes.js'][134] = 0; + _$jscoverage['plugins/keystrokes.js'][135] = 0; + _$jscoverage['plugins/keystrokes.js'][136] = 0; + _$jscoverage['plugins/keystrokes.js'][138] = 0; + _$jscoverage['plugins/keystrokes.js'][141] = 0; + _$jscoverage['plugins/keystrokes.js'][145] = 0; + _$jscoverage['plugins/keystrokes.js'][146] = 0; + _$jscoverage['plugins/keystrokes.js'][147] = 0; + _$jscoverage['plugins/keystrokes.js'][148] = 0; + _$jscoverage['plugins/keystrokes.js'][149] = 0; + _$jscoverage['plugins/keystrokes.js'][150] = 0; + _$jscoverage['plugins/keystrokes.js'][151] = 0; + _$jscoverage['plugins/keystrokes.js'][152] = 0; + _$jscoverage['plugins/keystrokes.js'][153] = 0; + _$jscoverage['plugins/keystrokes.js'][155] = 0; + _$jscoverage['plugins/keystrokes.js'][156] = 0; + _$jscoverage['plugins/keystrokes.js'][157] = 0; + _$jscoverage['plugins/keystrokes.js'][162] = 0; + _$jscoverage['plugins/keystrokes.js'][163] = 0; + _$jscoverage['plugins/keystrokes.js'][165] = 0; + _$jscoverage['plugins/keystrokes.js'][166] = 0; + _$jscoverage['plugins/keystrokes.js'][167] = 0; + _$jscoverage['plugins/keystrokes.js'][169] = 0; + _$jscoverage['plugins/keystrokes.js'][170] = 0; + _$jscoverage['plugins/keystrokes.js'][171] = 0; + _$jscoverage['plugins/keystrokes.js'][173] = 0; + _$jscoverage['plugins/keystrokes.js'][174] = 0; + _$jscoverage['plugins/keystrokes.js'][175] = 0; + _$jscoverage['plugins/keystrokes.js'][176] = 0; + _$jscoverage['plugins/keystrokes.js'][177] = 0; + _$jscoverage['plugins/keystrokes.js'][178] = 0; + _$jscoverage['plugins/keystrokes.js'][179] = 0; + _$jscoverage['plugins/keystrokes.js'][181] = 0; + _$jscoverage['plugins/keystrokes.js'][182] = 0; + _$jscoverage['plugins/keystrokes.js'][183] = 0; + _$jscoverage['plugins/keystrokes.js'][184] = 0; + _$jscoverage['plugins/keystrokes.js'][185] = 0; + _$jscoverage['plugins/keystrokes.js'][191] = 0; + _$jscoverage['plugins/keystrokes.js'][192] = 0; + _$jscoverage['plugins/keystrokes.js'][195] = 0; + _$jscoverage['plugins/keystrokes.js'][201] = 0; + _$jscoverage['plugins/keystrokes.js'][202] = 0; + _$jscoverage['plugins/keystrokes.js'][203] = 0; + _$jscoverage['plugins/keystrokes.js'][204] = 0; + _$jscoverage['plugins/keystrokes.js'][205] = 0; + _$jscoverage['plugins/keystrokes.js'][206] = 0; + _$jscoverage['plugins/keystrokes.js'][208] = 0; +} +_$jscoverage['plugins/keystrokes.js'].source = ["/*"," * 处理特殊键的兼容性问题"," */","UE.plugins['keystrokes'] = function() {"," var me = this;"," var collapsed = true;"," me.addListener('keydown', function(type, evt) {"," var keyCode = evt.keyCode || evt.which,"," rng = me.selection.getRange();",""," //处理全选的情况"," if(!rng.collapsed && !(evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) && (keyCode >= 65 && keyCode <=90"," || keyCode >= 48 && keyCode <= 57 ||"," keyCode >= 96 && keyCode <= 111 || {"," 13:1,"," 8:1,"," 46:1"," }[keyCode])"," ){",""," var tmpNode = rng.startContainer;"," if(domUtils.isFillChar(tmpNode)){"," rng.setStartBefore(tmpNode)"," }"," tmpNode = rng.endContainer;"," if(domUtils.isFillChar(tmpNode)){"," rng.setEndAfter(tmpNode)"," }"," rng.txtToElmBoundary();"," //结束边界可能放到了br的前边,要把br包含进来"," // x[xxx]<br/>"," if(rng.endContainer && rng.endContainer.nodeType == 1){"," tmpNode = rng.endContainer.childNodes[rng.endOffset];"," if(tmpNode && domUtils.isBr(tmpNode)){"," rng.setEndAfter(tmpNode);"," }"," }"," if(rng.startOffset == 0){"," tmpNode = rng.startContainer;"," if(domUtils.isBoundaryNode(tmpNode,'firstChild') ){"," tmpNode = rng.endContainer;"," if(rng.endOffset == (tmpNode.nodeType == 3 ? tmpNode.nodeValue.length : tmpNode.childNodes.length) && domUtils.isBoundaryNode(tmpNode,'lastChild')){"," me.fireEvent('saveScene');"," me.body.innerHTML = '<p>'+(browser.ie ? '' : '<br/>')+'</p>';"," rng.setStart(me.body.firstChild,0).setCursor(false,true);"," me._selectionChange();"," return;"," }"," }"," }"," }",""," //处理backspace"," if (keyCode == 8) {"," rng = me.selection.getRange();"," collapsed = rng.collapsed;"," if(me.fireEvent('delkeydown',evt)){"," return;"," }"," var start,end;"," //避免按两次删除才能生效的问题"," if(rng.collapsed && rng.inFillChar()){"," start = rng.startContainer;",""," if(domUtils.isFillChar(start)){"," rng.setStartBefore(start).shrinkBoundary(true).collapse(true);"," domUtils.remove(start)"," }else{"," start.nodeValue = start.nodeValue.replace(new RegExp('^' + domUtils.fillChar ),'');"," rng.startOffset--;"," rng.collapse(true).select(true)"," }"," }",""," //解决选中control元素不能删除的问题"," if (start = rng.getClosedNode()) {"," me.fireEvent('saveScene');"," rng.setStartBefore(start);"," domUtils.remove(start);"," rng.setCursor();"," me.fireEvent('saveScene');"," domUtils.preventDefault(evt);"," return;"," }"," //阻止在table上的删除"," if (!browser.ie) {"," start = domUtils.findParentByTagName(rng.startContainer, 'table', true);"," end = domUtils.findParentByTagName(rng.endContainer, 'table', true);"," if (start && !end || !start && end || start !== end) {"," evt.preventDefault();"," return;"," }"," }",""," }"," //处理tab键的逻辑"," if (keyCode == 9) {"," //不处理以下标签"," var excludeTagNameForTabKey = {"," 'ol' : 1,"," 'ul' : 1,"," 'table':1"," };"," //处理组件里的tab按下事件"," if(me.fireEvent('tabkeydown',evt)){"," domUtils.preventDefault(evt);"," return;"," }"," var range = me.selection.getRange();"," me.fireEvent('saveScene');"," for (var i = 0,txt = '',tabSize = me.options.tabSize|| 4,tabNode = me.options.tabNode || '&nbsp;'; i < tabSize; i++) {"," txt += tabNode;"," }"," var span = me.document.createElement('span');"," span.innerHTML = txt + domUtils.fillChar;"," if (range.collapsed) {"," range.insertNode(span.cloneNode(true).firstChild).setCursor(true);"," } else {"," //普通的情况"," start = domUtils.findParent(range.startContainer, filterFn);"," end = domUtils.findParent(range.endContainer, filterFn);"," if (start && end && start === end) {"," range.deleteContents();"," range.insertNode(span.cloneNode(true).firstChild).setCursor(true);"," } else {"," var bookmark = range.createBookmark(),"," filterFn = function(node) {"," return domUtils.isBlockElm(node) && !excludeTagNameForTabKey[node.tagName.toLowerCase()]",""," };"," range.enlarge(true);"," var bookmark2 = range.createBookmark(),"," current = domUtils.getNextDomNode(bookmark2.start, false, filterFn);"," while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {"," current.insertBefore(span.cloneNode(true).firstChild, current.firstChild);"," current = domUtils.getNextDomNode(current, false, filterFn);"," }"," range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select();"," }"," }"," domUtils.preventDefault(evt)"," }"," //trace:1634"," //ff的del键在容器空的时候,也会删除"," if(browser.gecko && keyCode == 46){"," range = me.selection.getRange();"," if(range.collapsed){"," start = range.startContainer;"," if(domUtils.isEmptyBlock(start)){"," var parent = start.parentNode;"," while(domUtils.getChildCount(parent) == 1 && !domUtils.isBody(parent)){"," start = parent;"," parent = parent.parentNode;"," }"," if(start === parent.lastChild)"," evt.preventDefault();"," return;"," }"," }"," }"," });"," me.addListener('keyup', function(type, evt) {"," var keyCode = evt.keyCode || evt.which,"," rng,me = this;"," if(keyCode == 8){"," if(me.fireEvent('delkeyup')){"," return;"," }"," rng = me.selection.getRange();"," if(rng.collapsed){"," var tmpNode,"," autoClearTagName = ['h1','h2','h3','h4','h5','h6'];"," if(tmpNode = domUtils.findParentByTagName(rng.startContainer,autoClearTagName,true)){"," if(domUtils.isEmptyBlock(tmpNode)){"," var pre = tmpNode.previousSibling;"," if(pre && pre.nodeName != 'TABLE'){"," domUtils.remove(tmpNode);"," rng.setStartAtLast(pre).setCursor(false,true);"," return;"," }else{"," var next = tmpNode.nextSibling;"," if(next && next.nodeName != 'TABLE'){"," domUtils.remove(tmpNode);"," rng.setStartAtFirst(next).setCursor(false,true);"," return;"," }"," }"," }"," }"," //处理当删除到body时,要重新给p标签展位"," if(domUtils.isBody(rng.startContainer)){"," var tmpNode = domUtils.createElement(me.document,'p',{"," 'innerHTML' : browser.ie ? domUtils.fillChar : '<br/>'"," });"," rng.insertNode(tmpNode).setStart(tmpNode,0).setCursor(false,true);"," }"," }","",""," //chrome下如果删除了inline标签,浏览器会有记忆,在输入文字还是会套上刚才删除的标签,所以这里再选一次就不会了"," if( !collapsed && (rng.startContainer.nodeType == 3 || rng.startContainer.nodeType == 1 && domUtils.isEmptyBlock(rng.startContainer))){"," if(browser.ie){"," var span = rng.document.createElement('span');"," rng.insertNode(span).setStartBefore(span).collapse(true);"," rng.select();"," domUtils.remove(span)"," }else{"," rng.select()"," }",""," }"," }",""," })","};"]; +_$jscoverage['plugins/keystrokes.js'][4]++; +UE.plugins.keystrokes = (function () { + _$jscoverage['plugins/keystrokes.js'][5]++; + var me = this; + _$jscoverage['plugins/keystrokes.js'][6]++; + var collapsed = true; + _$jscoverage['plugins/keystrokes.js'][7]++; + me.addListener("keydown", (function (type, evt) { + _$jscoverage['plugins/keystrokes.js'][8]++; + var keyCode = (evt.keyCode || evt.which), rng = me.selection.getRange(); + _$jscoverage['plugins/keystrokes.js'][12]++; + if (((! rng.collapsed) && (! (evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey)) && (((keyCode >= 65) && (keyCode <= 90)) || ((keyCode >= 48) && (keyCode <= 57)) || ((keyCode >= 96) && (keyCode <= 111)) || {13: 1, 8: 1, 46: 1}[keyCode]))) { + _$jscoverage['plugins/keystrokes.js'][21]++; + var tmpNode = rng.startContainer; + _$jscoverage['plugins/keystrokes.js'][22]++; + if (domUtils.isFillChar(tmpNode)) { + _$jscoverage['plugins/keystrokes.js'][23]++; + rng.setStartBefore(tmpNode); + } + _$jscoverage['plugins/keystrokes.js'][25]++; + tmpNode = rng.endContainer; + _$jscoverage['plugins/keystrokes.js'][26]++; + if (domUtils.isFillChar(tmpNode)) { + _$jscoverage['plugins/keystrokes.js'][27]++; + rng.setEndAfter(tmpNode); + } + _$jscoverage['plugins/keystrokes.js'][29]++; + rng.txtToElmBoundary(); + _$jscoverage['plugins/keystrokes.js'][32]++; + if ((rng.endContainer && (rng.endContainer.nodeType == 1))) { + _$jscoverage['plugins/keystrokes.js'][33]++; + tmpNode = rng.endContainer.childNodes[rng.endOffset]; + _$jscoverage['plugins/keystrokes.js'][34]++; + if ((tmpNode && domUtils.isBr(tmpNode))) { + _$jscoverage['plugins/keystrokes.js'][35]++; + rng.setEndAfter(tmpNode); + } + } + _$jscoverage['plugins/keystrokes.js'][38]++; + if ((rng.startOffset == 0)) { + _$jscoverage['plugins/keystrokes.js'][39]++; + tmpNode = rng.startContainer; + _$jscoverage['plugins/keystrokes.js'][40]++; + if (domUtils.isBoundaryNode(tmpNode, "firstChild")) { + _$jscoverage['plugins/keystrokes.js'][41]++; + tmpNode = rng.endContainer; + _$jscoverage['plugins/keystrokes.js'][42]++; + if (((rng.endOffset == ((tmpNode.nodeType == 3)? tmpNode.nodeValue.length: tmpNode.childNodes.length)) && domUtils.isBoundaryNode(tmpNode, "lastChild"))) { + _$jscoverage['plugins/keystrokes.js'][43]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/keystrokes.js'][44]++; + me.body.innerHTML = ("

    " + (browser.ie? "": "
    ") + "

    "); + _$jscoverage['plugins/keystrokes.js'][45]++; + rng.setStart(me.body.firstChild, 0).setCursor(false, true); + _$jscoverage['plugins/keystrokes.js'][46]++; + me._selectionChange(); + _$jscoverage['plugins/keystrokes.js'][47]++; + return; + } + } + } + } + _$jscoverage['plugins/keystrokes.js'][54]++; + if ((keyCode == 8)) { + _$jscoverage['plugins/keystrokes.js'][55]++; + rng = me.selection.getRange(); + _$jscoverage['plugins/keystrokes.js'][56]++; + collapsed = rng.collapsed; + _$jscoverage['plugins/keystrokes.js'][57]++; + if (me.fireEvent("delkeydown", evt)) { + _$jscoverage['plugins/keystrokes.js'][58]++; + return; + } + _$jscoverage['plugins/keystrokes.js'][60]++; + var start, end; + _$jscoverage['plugins/keystrokes.js'][62]++; + if ((rng.collapsed && rng.inFillChar())) { + _$jscoverage['plugins/keystrokes.js'][63]++; + start = rng.startContainer; + _$jscoverage['plugins/keystrokes.js'][65]++; + if (domUtils.isFillChar(start)) { + _$jscoverage['plugins/keystrokes.js'][66]++; + rng.setStartBefore(start).shrinkBoundary(true).collapse(true); + _$jscoverage['plugins/keystrokes.js'][67]++; + domUtils.remove(start); + } + else { + _$jscoverage['plugins/keystrokes.js'][69]++; + start.nodeValue = start.nodeValue.replace(new RegExp(("^" + domUtils.fillChar)), ""); + _$jscoverage['plugins/keystrokes.js'][70]++; + (rng.startOffset--); + _$jscoverage['plugins/keystrokes.js'][71]++; + rng.collapse(true).select(true); + } + } + _$jscoverage['plugins/keystrokes.js'][76]++; + if ((start = rng.getClosedNode())) { + _$jscoverage['plugins/keystrokes.js'][77]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/keystrokes.js'][78]++; + rng.setStartBefore(start); + _$jscoverage['plugins/keystrokes.js'][79]++; + domUtils.remove(start); + _$jscoverage['plugins/keystrokes.js'][80]++; + rng.setCursor(); + _$jscoverage['plugins/keystrokes.js'][81]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/keystrokes.js'][82]++; + domUtils.preventDefault(evt); + _$jscoverage['plugins/keystrokes.js'][83]++; + return; + } + _$jscoverage['plugins/keystrokes.js'][86]++; + if ((! browser.ie)) { + _$jscoverage['plugins/keystrokes.js'][87]++; + start = domUtils.findParentByTagName(rng.startContainer, "table", true); + _$jscoverage['plugins/keystrokes.js'][88]++; + end = domUtils.findParentByTagName(rng.endContainer, "table", true); + _$jscoverage['plugins/keystrokes.js'][89]++; + if (((start && (! end)) || ((! start) && end) || (start !== end))) { + _$jscoverage['plugins/keystrokes.js'][90]++; + evt.preventDefault(); + _$jscoverage['plugins/keystrokes.js'][91]++; + return; + } + } + } + _$jscoverage['plugins/keystrokes.js'][97]++; + if ((keyCode == 9)) { + _$jscoverage['plugins/keystrokes.js'][99]++; + var excludeTagNameForTabKey = {"ol": 1, "ul": 1, "table": 1}; + _$jscoverage['plugins/keystrokes.js'][105]++; + if (me.fireEvent("tabkeydown", evt)) { + _$jscoverage['plugins/keystrokes.js'][106]++; + domUtils.preventDefault(evt); + _$jscoverage['plugins/keystrokes.js'][107]++; + return; + } + _$jscoverage['plugins/keystrokes.js'][109]++; + var range = me.selection.getRange(); + _$jscoverage['plugins/keystrokes.js'][110]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/keystrokes.js'][111]++; + for (var i = 0, txt = "", tabSize = (me.options.tabSize || 4), tabNode = (me.options.tabNode || " "); (i < tabSize); (i++)) { + _$jscoverage['plugins/keystrokes.js'][112]++; + txt += tabNode; +} + _$jscoverage['plugins/keystrokes.js'][114]++; + var span = me.document.createElement("span"); + _$jscoverage['plugins/keystrokes.js'][115]++; + span.innerHTML = (txt + domUtils.fillChar); + _$jscoverage['plugins/keystrokes.js'][116]++; + if (range.collapsed) { + _$jscoverage['plugins/keystrokes.js'][117]++; + range.insertNode(span.cloneNode(true).firstChild).setCursor(true); + } + else { + _$jscoverage['plugins/keystrokes.js'][120]++; + start = domUtils.findParent(range.startContainer, filterFn); + _$jscoverage['plugins/keystrokes.js'][121]++; + end = domUtils.findParent(range.endContainer, filterFn); + _$jscoverage['plugins/keystrokes.js'][122]++; + if ((start && end && (start === end))) { + _$jscoverage['plugins/keystrokes.js'][123]++; + range.deleteContents(); + _$jscoverage['plugins/keystrokes.js'][124]++; + range.insertNode(span.cloneNode(true).firstChild).setCursor(true); + } + else { + _$jscoverage['plugins/keystrokes.js'][126]++; + var bookmark = range.createBookmark(), filterFn = (function (node) { + _$jscoverage['plugins/keystrokes.js'][128]++; + return (domUtils.isBlockElm(node) && (! excludeTagNameForTabKey[node.tagName.toLowerCase()])); +}); + _$jscoverage['plugins/keystrokes.js'][131]++; + range.enlarge(true); + _$jscoverage['plugins/keystrokes.js'][132]++; + var bookmark2 = range.createBookmark(), current = domUtils.getNextDomNode(bookmark2.start, false, filterFn); + _$jscoverage['plugins/keystrokes.js'][134]++; + while ((current && (! (domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)))) { + _$jscoverage['plugins/keystrokes.js'][135]++; + current.insertBefore(span.cloneNode(true).firstChild, current.firstChild); + _$jscoverage['plugins/keystrokes.js'][136]++; + current = domUtils.getNextDomNode(current, false, filterFn); +} + _$jscoverage['plugins/keystrokes.js'][138]++; + range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select(); + } + } + _$jscoverage['plugins/keystrokes.js'][141]++; + domUtils.preventDefault(evt); + } + _$jscoverage['plugins/keystrokes.js'][145]++; + if ((browser.gecko && (keyCode == 46))) { + _$jscoverage['plugins/keystrokes.js'][146]++; + range = me.selection.getRange(); + _$jscoverage['plugins/keystrokes.js'][147]++; + if (range.collapsed) { + _$jscoverage['plugins/keystrokes.js'][148]++; + start = range.startContainer; + _$jscoverage['plugins/keystrokes.js'][149]++; + if (domUtils.isEmptyBlock(start)) { + _$jscoverage['plugins/keystrokes.js'][150]++; + var parent = start.parentNode; + _$jscoverage['plugins/keystrokes.js'][151]++; + while (((domUtils.getChildCount(parent) == 1) && (! domUtils.isBody(parent)))) { + _$jscoverage['plugins/keystrokes.js'][152]++; + start = parent; + _$jscoverage['plugins/keystrokes.js'][153]++; + parent = parent.parentNode; +} + _$jscoverage['plugins/keystrokes.js'][155]++; + if ((start === parent.lastChild)) { + _$jscoverage['plugins/keystrokes.js'][156]++; + evt.preventDefault(); + } + _$jscoverage['plugins/keystrokes.js'][157]++; + return; + } + } + } +})); + _$jscoverage['plugins/keystrokes.js'][162]++; + me.addListener("keyup", (function (type, evt) { + _$jscoverage['plugins/keystrokes.js'][163]++; + var keyCode = (evt.keyCode || evt.which), rng, me = this; + _$jscoverage['plugins/keystrokes.js'][165]++; + if ((keyCode == 8)) { + _$jscoverage['plugins/keystrokes.js'][166]++; + if (me.fireEvent("delkeyup")) { + _$jscoverage['plugins/keystrokes.js'][167]++; + return; + } + _$jscoverage['plugins/keystrokes.js'][169]++; + rng = me.selection.getRange(); + _$jscoverage['plugins/keystrokes.js'][170]++; + if (rng.collapsed) { + _$jscoverage['plugins/keystrokes.js'][171]++; + var tmpNode, autoClearTagName = ["h1", "h2", "h3", "h4", "h5", "h6"]; + _$jscoverage['plugins/keystrokes.js'][173]++; + if ((tmpNode = domUtils.findParentByTagName(rng.startContainer, autoClearTagName, true))) { + _$jscoverage['plugins/keystrokes.js'][174]++; + if (domUtils.isEmptyBlock(tmpNode)) { + _$jscoverage['plugins/keystrokes.js'][175]++; + var pre = tmpNode.previousSibling; + _$jscoverage['plugins/keystrokes.js'][176]++; + if ((pre && (pre.nodeName != "TABLE"))) { + _$jscoverage['plugins/keystrokes.js'][177]++; + domUtils.remove(tmpNode); + _$jscoverage['plugins/keystrokes.js'][178]++; + rng.setStartAtLast(pre).setCursor(false, true); + _$jscoverage['plugins/keystrokes.js'][179]++; + return; + } + else { + _$jscoverage['plugins/keystrokes.js'][181]++; + var next = tmpNode.nextSibling; + _$jscoverage['plugins/keystrokes.js'][182]++; + if ((next && (next.nodeName != "TABLE"))) { + _$jscoverage['plugins/keystrokes.js'][183]++; + domUtils.remove(tmpNode); + _$jscoverage['plugins/keystrokes.js'][184]++; + rng.setStartAtFirst(next).setCursor(false, true); + _$jscoverage['plugins/keystrokes.js'][185]++; + return; + } + } + } + } + _$jscoverage['plugins/keystrokes.js'][191]++; + if (domUtils.isBody(rng.startContainer)) { + _$jscoverage['plugins/keystrokes.js'][192]++; + var tmpNode = domUtils.createElement(me.document, "p", {"innerHTML": (browser.ie? domUtils.fillChar: "
    ")}); + _$jscoverage['plugins/keystrokes.js'][195]++; + rng.insertNode(tmpNode).setStart(tmpNode, 0).setCursor(false, true); + } + } + _$jscoverage['plugins/keystrokes.js'][201]++; + if (((! collapsed) && ((rng.startContainer.nodeType == 3) || ((rng.startContainer.nodeType == 1) && domUtils.isEmptyBlock(rng.startContainer))))) { + _$jscoverage['plugins/keystrokes.js'][202]++; + if (browser.ie) { + _$jscoverage['plugins/keystrokes.js'][203]++; + var span = rng.document.createElement("span"); + _$jscoverage['plugins/keystrokes.js'][204]++; + rng.insertNode(span).setStartBefore(span).collapse(true); + _$jscoverage['plugins/keystrokes.js'][205]++; + rng.select(); + _$jscoverage['plugins/keystrokes.js'][206]++; + domUtils.remove(span); + } + else { + _$jscoverage['plugins/keystrokes.js'][208]++; + rng.select(); + } + } + } +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/lineheight.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/lineheight.js new file mode 100644 index 000000000..7c9d13c2f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/lineheight.js @@ -0,0 +1,80 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/lineheight.js']) { + _$jscoverage['plugins/lineheight.js'] = []; + _$jscoverage['plugins/lineheight.js'][7] = 0; + _$jscoverage['plugins/lineheight.js'][8] = 0; + _$jscoverage['plugins/lineheight.js'][9] = 0; + _$jscoverage['plugins/lineheight.js'][33] = 0; + _$jscoverage['plugins/lineheight.js'][35] = 0; + _$jscoverage['plugins/lineheight.js'][36] = 0; + _$jscoverage['plugins/lineheight.js'][39] = 0; + _$jscoverage['plugins/lineheight.js'][40] = 0; + _$jscoverage['plugins/lineheight.js'][41] = 0; + _$jscoverage['plugins/lineheight.js'][42] = 0; +} +_$jscoverage['plugins/lineheight.js'].source = ["/**"," * 设置行内间距"," * @file"," * @since 1.2.6.1"," */","","UE.plugins['lineheight'] = function(){"," var me = this;"," me.setOpt({'lineheight':['1', '1.5','1.75','2', '3', '4', '5']});",""," /**"," * 设置选区的行高"," * @command lineheight"," * @method execCommand"," * @param { String } cmdName 命令字符串"," * @param { String } value 传入的行高大小"," * @example"," * ```javascript"," * editor.execCommand( 'lineheight', '1');"," * ```"," */"," /**"," * 查询当前选区内容的行高大小"," * @command lineheight"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { String } 返回当前行高大小"," * @example"," * ```javascript"," * editor.queryCommandValue( 'lineheight' );"," * ```"," */"," me.commands['lineheight'] = {"," execCommand : function( cmdName,value ) {"," this.execCommand('paragraph','p',{style:'line-height:'+ (value == \"1\" ? \"normal\" : value + 'em') });"," return true;"," },"," queryCommandValue : function() {"," var pN = domUtils.filterNodeList(this.selection.getStartElementPath(),function(node){return domUtils.isBlockElm(node)});"," if(pN){"," var value = domUtils.getComputedStyle(pN,'line-height');"," return value == 'normal' ? 1 : value.replace(/[^\\d.]*/ig,\"\");"," }"," }"," };","};","",""]; +_$jscoverage['plugins/lineheight.js'][7]++; +UE.plugins.lineheight = (function () { + _$jscoverage['plugins/lineheight.js'][8]++; + var me = this; + _$jscoverage['plugins/lineheight.js'][9]++; + me.setOpt({"lineheight": ["1", "1.5", "1.75", "2", "3", "4", "5"]}); + _$jscoverage['plugins/lineheight.js'][33]++; + me.commands.lineheight = {execCommand: (function (cmdName, value) { + _$jscoverage['plugins/lineheight.js'][35]++; + this.execCommand("paragraph", "p", {style: ("line-height:" + ((value == "1")? "normal": (value + "em")))}); + _$jscoverage['plugins/lineheight.js'][36]++; + return true; +}), queryCommandValue: (function () { + _$jscoverage['plugins/lineheight.js'][39]++; + var pN = domUtils.filterNodeList(this.selection.getStartElementPath(), (function (node) { + _$jscoverage['plugins/lineheight.js'][39]++; + return domUtils.isBlockElm(node); +})); + _$jscoverage['plugins/lineheight.js'][40]++; + if (pN) { + _$jscoverage['plugins/lineheight.js'][41]++; + var value = domUtils.getComputedStyle(pN, "line-height"); + _$jscoverage['plugins/lineheight.js'][42]++; + return ((value == "normal")? 1: value.replace(/[^\d.]*/gi, "")); + } +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/link.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/link.js new file mode 100644 index 000000000..eeedea7ab --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/link.js @@ -0,0 +1,266 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/link.js']) { + _$jscoverage['plugins/link.js'] = []; + _$jscoverage['plugins/link.js'][66] = 0; + _$jscoverage['plugins/link.js'][67] = 0; + _$jscoverage['plugins/link.js'][68] = 0; + _$jscoverage['plugins/link.js'][70] = 0; + _$jscoverage['plugins/link.js'][71] = 0; + _$jscoverage['plugins/link.js'][73] = 0; + _$jscoverage['plugins/link.js'][74] = 0; + _$jscoverage['plugins/link.js'][79] = 0; + _$jscoverage['plugins/link.js'][81] = 0; + _$jscoverage['plugins/link.js'][83] = 0; + _$jscoverage['plugins/link.js'][84] = 0; + _$jscoverage['plugins/link.js'][86] = 0; + _$jscoverage['plugins/link.js'][87] = 0; + _$jscoverage['plugins/link.js'][88] = 0; + _$jscoverage['plugins/link.js'][91] = 0; + _$jscoverage['plugins/link.js'][95] = 0; + _$jscoverage['plugins/link.js'][96] = 0; + _$jscoverage['plugins/link.js'][98] = 0; + _$jscoverage['plugins/link.js'][99] = 0; + _$jscoverage['plugins/link.js'][100] = 0; + _$jscoverage['plugins/link.js'][101] = 0; + _$jscoverage['plugins/link.js'][102] = 0; + _$jscoverage['plugins/link.js'][103] = 0; + _$jscoverage['plugins/link.js'][107] = 0; + _$jscoverage['plugins/link.js'][108] = 0; + _$jscoverage['plugins/link.js'][109] = 0; + _$jscoverage['plugins/link.js'][112] = 0; + _$jscoverage['plugins/link.js'][113] = 0; + _$jscoverage['plugins/link.js'][115] = 0; + _$jscoverage['plugins/link.js'][117] = 0; + _$jscoverage['plugins/link.js'][118] = 0; + _$jscoverage['plugins/link.js'][120] = 0; + _$jscoverage['plugins/link.js'][123] = 0; + _$jscoverage['plugins/link.js'][124] = 0; + _$jscoverage['plugins/link.js'][125] = 0; + _$jscoverage['plugins/link.js'][126] = 0; + _$jscoverage['plugins/link.js'][129] = 0; + _$jscoverage['plugins/link.js'][130] = 0; + _$jscoverage['plugins/link.js'][132] = 0; + _$jscoverage['plugins/link.js'][136] = 0; + _$jscoverage['plugins/link.js'][138] = 0; + _$jscoverage['plugins/link.js'][139] = 0; + _$jscoverage['plugins/link.js'][140] = 0; + _$jscoverage['plugins/link.js'][141] = 0; + _$jscoverage['plugins/link.js'][142] = 0; + _$jscoverage['plugins/link.js'][144] = 0; + _$jscoverage['plugins/link.js'][148] = 0; + _$jscoverage['plugins/link.js'][150] = 0; + _$jscoverage['plugins/link.js'][153] = 0; + _$jscoverage['plugins/link.js'][154] = 0; + _$jscoverage['plugins/link.js'][156] = 0; + _$jscoverage['plugins/link.js'][158] = 0; + _$jscoverage['plugins/link.js'][162] = 0; + _$jscoverage['plugins/link.js'][163] = 0; + _$jscoverage['plugins/link.js'][166] = 0; + _$jscoverage['plugins/link.js'][167] = 0; + _$jscoverage['plugins/link.js'][169] = 0; + _$jscoverage['plugins/link.js'][172] = 0; + _$jscoverage['plugins/link.js'][173] = 0; + _$jscoverage['plugins/link.js'][174] = 0; + _$jscoverage['plugins/link.js'][178] = 0; + _$jscoverage['plugins/link.js'][179] = 0; + _$jscoverage['plugins/link.js'][183] = 0; + _$jscoverage['plugins/link.js'][190] = 0; + _$jscoverage['plugins/link.js'][192] = 0; +} +_$jscoverage['plugins/link.js'].source = ["/**"," * 超链接"," * @file"," * @since 1.2.6.1"," */","","/**"," * 插入超链接"," * @command link"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param { Object } options url地址,title标题,target是否打开新页"," * @example"," * ```javascript"," * editor.execCommand( 'link', '{"," * url:'ueditor.baidu.com',"," * title:'ueditor官网',"," * target:'_blank'"," * }' );"," * ```"," */","/**"," * 如果选区所在位置是区域,返回当前超链接节点"," * @command link"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { Element } 超链接节点"," * @example"," * ```javascript"," * editor.queryCommandValue( 'link' );"," * ```"," */","/**"," * 返回当前选区位置是否是超链接"," * @command link"," * @method queryCommandState"," * @param { String } cmd 命令字符串"," * @return { Int } 0为是,-1为不是"," * @example"," * ```javascript"," * editor.queryCommandState( 'link' );"," * ```"," */","","/**"," * 根据当前选区取消超链接"," * @command unlink"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'unlink');"," * ```"," */","/**"," * 返回当前选区位置是否是超链接"," * @command unlink"," * @method queryCommandState"," * @param { String } cmd 命令字符串"," * @return { Int } 0为是,-1为不是"," * @example"," * ```javascript"," * editor.queryCommandState( 'unlink' );"," * ```"," */","UE.plugins['link'] = function(){"," function optimize( range ) {"," var start = range.startContainer,end = range.endContainer;",""," if ( start = domUtils.findParentByTagName( start, 'a', true ) ) {"," range.setStartBefore( start );"," }"," if ( end = domUtils.findParentByTagName( end, 'a', true ) ) {"," range.setEndAfter( end );"," }"," }","",""," UE.commands['unlink'] = {"," execCommand : function() {"," var range = this.selection.getRange(),"," bookmark;"," if(range.collapsed && !domUtils.findParentByTagName( range.startContainer, 'a', true )){"," return;"," }"," bookmark = range.createBookmark();"," optimize( range );"," range.removeInlineStyle( 'a' ).moveToBookmark( bookmark ).select();"," },"," queryCommandState : function(){"," return !this.highlight && this.queryCommandValue('link') ? 0 : -1;"," }",""," };"," function doLink(range,opt,me){"," var rngClone = range.cloneRange(),"," link = me.queryCommandValue('link');"," optimize( range = range.adjustmentBoundary() );"," var start = range.startContainer;"," if(start.nodeType == 1 && link){"," start = start.childNodes[range.startOffset];"," if(start && start.nodeType == 1 && start.tagName == 'A' && /^(?:https?|ftp|file)\\s*:\\s*\\/\\//.test(start[browser.ie?'innerText':'textContent'])){"," start[browser.ie ? 'innerText' : 'textContent'] = utils.html(opt.textValue||opt.href);",""," }"," }"," if( !rngClone.collapsed || link){"," range.removeInlineStyle( 'a' );"," rngClone = range.cloneRange();"," }",""," if ( rngClone.collapsed ) {"," var a = range.document.createElement( 'a'),"," text = '';"," if(opt.textValue){",""," text = utils.html(opt.textValue);"," delete opt.textValue;"," }else{"," text = utils.html(opt.href);",""," }"," domUtils.setAttributes( a, opt );"," start = domUtils.findParentByTagName( rngClone.startContainer, 'a', true );"," if(start && domUtils.isInNodeEndBoundary(rngClone,start)){"," range.setStartAfter(start).collapse(true);",""," }"," a[browser.ie ? 'innerText' : 'textContent'] = text;"," range.insertNode(a).selectNode( a );"," } else {"," range.applyInlineStyle( 'a', opt );",""," }"," }"," UE.commands['link'] = {"," execCommand : function( cmdName, opt ) {"," var range;"," opt._href && (opt._href = utils.unhtml(opt._href,/[<\">]/g));"," opt.href && (opt.href = utils.unhtml(opt.href,/[<\">]/g));"," opt.textValue && (opt.textValue = utils.unhtml(opt.textValue,/[<\">]/g));"," doLink(range=this.selection.getRange(),opt,this);"," //闭合都不加占位符,如果加了会在a后边多个占位符节点,导致a是图片背景组成的列表,出现空白问题"," range.collapse().select(true);",""," },"," queryCommandValue : function() {"," var range = this.selection.getRange(),"," node;"," if ( range.collapsed ) {","// node = this.selection.getStart();"," //在ie下getstart()取值偏上了"," node = range.startContainer;"," node = node.nodeType == 1 ? node : node.parentNode;",""," if ( node && (node = domUtils.findParentByTagName( node, 'a', true )) && ! domUtils.isInNodeEndBoundary(range,node)) {",""," return node;"," }"," } else {"," //trace:1111 如果是<p><a>xx</a></p> startContainer是p就会找不到a"," range.shrinkBoundary();"," var start = range.startContainer.nodeType == 3 || !range.startContainer.childNodes[range.startOffset] ? range.startContainer : range.startContainer.childNodes[range.startOffset],"," end = range.endContainer.nodeType == 3 || range.endOffset == 0 ? range.endContainer : range.endContainer.childNodes[range.endOffset-1],"," common = range.getCommonAncestor();"," node = domUtils.findParentByTagName( common, 'a', true );"," if ( !node && common.nodeType == 1){",""," var as = common.getElementsByTagName( 'a' ),"," ps,pe;",""," for ( var i = 0,ci; ci = as[i++]; ) {"," ps = domUtils.getPosition( ci, start ),pe = domUtils.getPosition( ci,end);"," if ( (ps & domUtils.POSITION_FOLLOWING || ps & domUtils.POSITION_CONTAINS)"," &&"," (pe & domUtils.POSITION_PRECEDING || pe & domUtils.POSITION_CONTAINS)"," ) {"," node = ci;"," break;"," }"," }"," }"," return node;"," }",""," },"," queryCommandState : function() {"," //判断如果是视频的话连接不可用"," //fix 853"," var img = this.selection.getRange().getClosedNode(),"," flag = img && (img.className == \"edui-faked-video\");"," return flag ? -1 : 0;"," }"," };","};"]; +_$jscoverage['plugins/link.js'][66]++; +UE.plugins.link = (function () { + _$jscoverage['plugins/link.js'][67]++; + function optimize(range) { + _$jscoverage['plugins/link.js'][68]++; + var start = range.startContainer, end = range.endContainer; + _$jscoverage['plugins/link.js'][70]++; + if ((start = domUtils.findParentByTagName(start, "a", true))) { + _$jscoverage['plugins/link.js'][71]++; + range.setStartBefore(start); + } + _$jscoverage['plugins/link.js'][73]++; + if ((end = domUtils.findParentByTagName(end, "a", true))) { + _$jscoverage['plugins/link.js'][74]++; + range.setEndAfter(end); + } +} + _$jscoverage['plugins/link.js'][79]++; + UE.commands.unlink = {execCommand: (function () { + _$jscoverage['plugins/link.js'][81]++; + var range = this.selection.getRange(), bookmark; + _$jscoverage['plugins/link.js'][83]++; + if ((range.collapsed && (! domUtils.findParentByTagName(range.startContainer, "a", true)))) { + _$jscoverage['plugins/link.js'][84]++; + return; + } + _$jscoverage['plugins/link.js'][86]++; + bookmark = range.createBookmark(); + _$jscoverage['plugins/link.js'][87]++; + optimize(range); + _$jscoverage['plugins/link.js'][88]++; + range.removeInlineStyle("a").moveToBookmark(bookmark).select(); +}), queryCommandState: (function () { + _$jscoverage['plugins/link.js'][91]++; + return (((! this.highlight) && this.queryCommandValue("link"))? 0: -1); +})}; + _$jscoverage['plugins/link.js'][95]++; + function doLink(range, opt, me) { + _$jscoverage['plugins/link.js'][96]++; + var rngClone = range.cloneRange(), link = me.queryCommandValue("link"); + _$jscoverage['plugins/link.js'][98]++; + optimize((range = range.adjustmentBoundary())); + _$jscoverage['plugins/link.js'][99]++; + var start = range.startContainer; + _$jscoverage['plugins/link.js'][100]++; + if (((start.nodeType == 1) && link)) { + _$jscoverage['plugins/link.js'][101]++; + start = start.childNodes[range.startOffset]; + _$jscoverage['plugins/link.js'][102]++; + if ((start && (start.nodeType == 1) && (start.tagName == "A") && /^(?:https?|ftp|file)\s*:\s*\/\//.test(start[(browser.ie? "innerText": "textContent")]))) { + _$jscoverage['plugins/link.js'][103]++; + start[(browser.ie? "innerText": "textContent")] = utils.html((opt.textValue || opt.href)); + } + } + _$jscoverage['plugins/link.js'][107]++; + if (((! rngClone.collapsed) || link)) { + _$jscoverage['plugins/link.js'][108]++; + range.removeInlineStyle("a"); + _$jscoverage['plugins/link.js'][109]++; + rngClone = range.cloneRange(); + } + _$jscoverage['plugins/link.js'][112]++; + if (rngClone.collapsed) { + _$jscoverage['plugins/link.js'][113]++; + var a = range.document.createElement("a"), text = ""; + _$jscoverage['plugins/link.js'][115]++; + if (opt.textValue) { + _$jscoverage['plugins/link.js'][117]++; + text = utils.html(opt.textValue); + _$jscoverage['plugins/link.js'][118]++; + (delete opt.textValue); + } + else { + _$jscoverage['plugins/link.js'][120]++; + text = utils.html(opt.href); + } + _$jscoverage['plugins/link.js'][123]++; + domUtils.setAttributes(a, opt); + _$jscoverage['plugins/link.js'][124]++; + start = domUtils.findParentByTagName(rngClone.startContainer, "a", true); + _$jscoverage['plugins/link.js'][125]++; + if ((start && domUtils.isInNodeEndBoundary(rngClone, start))) { + _$jscoverage['plugins/link.js'][126]++; + range.setStartAfter(start).collapse(true); + } + _$jscoverage['plugins/link.js'][129]++; + a[(browser.ie? "innerText": "textContent")] = text; + _$jscoverage['plugins/link.js'][130]++; + range.insertNode(a).selectNode(a); + } + else { + _$jscoverage['plugins/link.js'][132]++; + range.applyInlineStyle("a", opt); + } +} + _$jscoverage['plugins/link.js'][136]++; + UE.commands.link = {execCommand: (function (cmdName, opt) { + _$jscoverage['plugins/link.js'][138]++; + var range; + _$jscoverage['plugins/link.js'][139]++; + (opt._href && (opt._href = utils.unhtml(opt._href, /[<">]/g))); + _$jscoverage['plugins/link.js'][140]++; + (opt.href && (opt.href = utils.unhtml(opt.href, /[<">]/g))); + _$jscoverage['plugins/link.js'][141]++; + (opt.textValue && (opt.textValue = utils.unhtml(opt.textValue, /[<">]/g))); + _$jscoverage['plugins/link.js'][142]++; + doLink((range = this.selection.getRange()), opt, this); + _$jscoverage['plugins/link.js'][144]++; + range.collapse().select(true); +}), queryCommandValue: (function () { + _$jscoverage['plugins/link.js'][148]++; + var range = this.selection.getRange(), node; + _$jscoverage['plugins/link.js'][150]++; + if (range.collapsed) { + _$jscoverage['plugins/link.js'][153]++; + node = range.startContainer; + _$jscoverage['plugins/link.js'][154]++; + node = ((node.nodeType == 1)? node: node.parentNode); + _$jscoverage['plugins/link.js'][156]++; + if ((node && (node = domUtils.findParentByTagName(node, "a", true)) && (! domUtils.isInNodeEndBoundary(range, node)))) { + _$jscoverage['plugins/link.js'][158]++; + return node; + } + } + else { + _$jscoverage['plugins/link.js'][162]++; + range.shrinkBoundary(); + _$jscoverage['plugins/link.js'][163]++; + var start = (((range.startContainer.nodeType == 3) || (! range.startContainer.childNodes[range.startOffset]))? range.startContainer: range.startContainer.childNodes[range.startOffset]), end = (((range.endContainer.nodeType == 3) || (range.endOffset == 0))? range.endContainer: range.endContainer.childNodes[(range.endOffset - 1)]), common = range.getCommonAncestor(); + _$jscoverage['plugins/link.js'][166]++; + node = domUtils.findParentByTagName(common, "a", true); + _$jscoverage['plugins/link.js'][167]++; + if (((! node) && (common.nodeType == 1))) { + _$jscoverage['plugins/link.js'][169]++; + var as = common.getElementsByTagName("a"), ps, pe; + _$jscoverage['plugins/link.js'][172]++; + for (var i = 0, ci; (ci = as[(i++)]);) { + _$jscoverage['plugins/link.js'][173]++; + ((ps = domUtils.getPosition(ci, start)), (pe = domUtils.getPosition(ci, end))); + _$jscoverage['plugins/link.js'][174]++; + if ((((ps & domUtils.POSITION_FOLLOWING) || (ps & domUtils.POSITION_CONTAINS)) && ((pe & domUtils.POSITION_PRECEDING) || (pe & domUtils.POSITION_CONTAINS)))) { + _$jscoverage['plugins/link.js'][178]++; + node = ci; + _$jscoverage['plugins/link.js'][179]++; + break; + } +} + } + _$jscoverage['plugins/link.js'][183]++; + return node; + } +}), queryCommandState: (function () { + _$jscoverage['plugins/link.js'][190]++; + var img = this.selection.getRange().getClosedNode(), flag = (img && (img.className == "edui-faked-video")); + _$jscoverage['plugins/link.js'][192]++; + return (flag? -1: 0); +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/list.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/list.js new file mode 100644 index 000000000..3b18180e6 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/list.js @@ -0,0 +1,2337 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/list.js']) { + _$jscoverage['plugins/list.js'] = []; + _$jscoverage['plugins/list.js'][7] = 0; + _$jscoverage['plugins/list.js'][8] = 0; + _$jscoverage['plugins/list.js'][14] = 0; + _$jscoverage['plugins/list.js'][25] = 0; + _$jscoverage['plugins/list.js'][50] = 0; + _$jscoverage['plugins/list.js'][51] = 0; + _$jscoverage['plugins/list.js'][52] = 0; + _$jscoverage['plugins/list.js'][53] = 0; + _$jscoverage['plugins/list.js'][55] = 0; + _$jscoverage['plugins/list.js'][57] = 0; + _$jscoverage['plugins/list.js'][61] = 0; + _$jscoverage['plugins/list.js'][64] = 0; + _$jscoverage['plugins/list.js'][65] = 0; + _$jscoverage['plugins/list.js'][66] = 0; + _$jscoverage['plugins/list.js'][70] = 0; + _$jscoverage['plugins/list.js'][71] = 0; + _$jscoverage['plugins/list.js'][72] = 0; + _$jscoverage['plugins/list.js'][73] = 0; + _$jscoverage['plugins/list.js'][74] = 0; + _$jscoverage['plugins/list.js'][75] = 0; + _$jscoverage['plugins/list.js'][77] = 0; + _$jscoverage['plugins/list.js'][78] = 0; + _$jscoverage['plugins/list.js'][80] = 0; + _$jscoverage['plugins/list.js'][82] = 0; + _$jscoverage['plugins/list.js'][84] = 0; + _$jscoverage['plugins/list.js'][85] = 0; + _$jscoverage['plugins/list.js'][86] = 0; + _$jscoverage['plugins/list.js'][87] = 0; + _$jscoverage['plugins/list.js'][89] = 0; + _$jscoverage['plugins/list.js'][90] = 0; + _$jscoverage['plugins/list.js'][91] = 0; + _$jscoverage['plugins/list.js'][92] = 0; + _$jscoverage['plugins/list.js'][94] = 0; + _$jscoverage['plugins/list.js'][95] = 0; + _$jscoverage['plugins/list.js'][96] = 0; + _$jscoverage['plugins/list.js'][97] = 0; + _$jscoverage['plugins/list.js'][100] = 0; + _$jscoverage['plugins/list.js'][101] = 0; + _$jscoverage['plugins/list.js'][103] = 0; + _$jscoverage['plugins/list.js'][104] = 0; + _$jscoverage['plugins/list.js'][105] = 0; + _$jscoverage['plugins/list.js'][107] = 0; + _$jscoverage['plugins/list.js'][108] = 0; + _$jscoverage['plugins/list.js'][110] = 0; + _$jscoverage['plugins/list.js'][113] = 0; + _$jscoverage['plugins/list.js'][114] = 0; + _$jscoverage['plugins/list.js'][115] = 0; + _$jscoverage['plugins/list.js'][117] = 0; + _$jscoverage['plugins/list.js'][120] = 0; + _$jscoverage['plugins/list.js'][121] = 0; + _$jscoverage['plugins/list.js'][122] = 0; + _$jscoverage['plugins/list.js'][123] = 0; + _$jscoverage['plugins/list.js'][125] = 0; + _$jscoverage['plugins/list.js'][126] = 0; + _$jscoverage['plugins/list.js'][127] = 0; + _$jscoverage['plugins/list.js'][128] = 0; + _$jscoverage['plugins/list.js'][129] = 0; + _$jscoverage['plugins/list.js'][130] = 0; + _$jscoverage['plugins/list.js'][131] = 0; + _$jscoverage['plugins/list.js'][132] = 0; + _$jscoverage['plugins/list.js'][133] = 0; + _$jscoverage['plugins/list.js'][134] = 0; + _$jscoverage['plugins/list.js'][135] = 0; + _$jscoverage['plugins/list.js'][136] = 0; + _$jscoverage['plugins/list.js'][138] = 0; + _$jscoverage['plugins/list.js'][139] = 0; + _$jscoverage['plugins/list.js'][140] = 0; + _$jscoverage['plugins/list.js'][141] = 0; + _$jscoverage['plugins/list.js'][142] = 0; + _$jscoverage['plugins/list.js'][143] = 0; + _$jscoverage['plugins/list.js'][153] = 0; + _$jscoverage['plugins/list.js'][154] = 0; + _$jscoverage['plugins/list.js'][155] = 0; + _$jscoverage['plugins/list.js'][156] = 0; + _$jscoverage['plugins/list.js'][158] = 0; + _$jscoverage['plugins/list.js'][162] = 0; + _$jscoverage['plugins/list.js'][163] = 0; + _$jscoverage['plugins/list.js'][165] = 0; + _$jscoverage['plugins/list.js'][166] = 0; + _$jscoverage['plugins/list.js'][167] = 0; + _$jscoverage['plugins/list.js'][168] = 0; + _$jscoverage['plugins/list.js'][169] = 0; + _$jscoverage['plugins/list.js'][170] = 0; + _$jscoverage['plugins/list.js'][171] = 0; + _$jscoverage['plugins/list.js'][172] = 0; + _$jscoverage['plugins/list.js'][174] = 0; + _$jscoverage['plugins/list.js'][175] = 0; + _$jscoverage['plugins/list.js'][176] = 0; + _$jscoverage['plugins/list.js'][178] = 0; + _$jscoverage['plugins/list.js'][180] = 0; + _$jscoverage['plugins/list.js'][181] = 0; + _$jscoverage['plugins/list.js'][184] = 0; + _$jscoverage['plugins/list.js'][185] = 0; + _$jscoverage['plugins/list.js'][186] = 0; + _$jscoverage['plugins/list.js'][187] = 0; + _$jscoverage['plugins/list.js'][188] = 0; + _$jscoverage['plugins/list.js'][189] = 0; + _$jscoverage['plugins/list.js'][192] = 0; + _$jscoverage['plugins/list.js'][198] = 0; + _$jscoverage['plugins/list.js'][201] = 0; + _$jscoverage['plugins/list.js'][202] = 0; + _$jscoverage['plugins/list.js'][203] = 0; + _$jscoverage['plugins/list.js'][204] = 0; + _$jscoverage['plugins/list.js'][205] = 0; + _$jscoverage['plugins/list.js'][206] = 0; + _$jscoverage['plugins/list.js'][208] = 0; + _$jscoverage['plugins/list.js'][209] = 0; + _$jscoverage['plugins/list.js'][210] = 0; + _$jscoverage['plugins/list.js'][211] = 0; + _$jscoverage['plugins/list.js'][213] = 0; + _$jscoverage['plugins/list.js'][218] = 0; + _$jscoverage['plugins/list.js'][219] = 0; + _$jscoverage['plugins/list.js'][223] = 0; + _$jscoverage['plugins/list.js'][224] = 0; + _$jscoverage['plugins/list.js'][227] = 0; + _$jscoverage['plugins/list.js'][228] = 0; + _$jscoverage['plugins/list.js'][229] = 0; + _$jscoverage['plugins/list.js'][230] = 0; + _$jscoverage['plugins/list.js'][233] = 0; + _$jscoverage['plugins/list.js'][244] = 0; + _$jscoverage['plugins/list.js'][245] = 0; + _$jscoverage['plugins/list.js'][246] = 0; + _$jscoverage['plugins/list.js'][247] = 0; + _$jscoverage['plugins/list.js'][248] = 0; + _$jscoverage['plugins/list.js'][249] = 0; + _$jscoverage['plugins/list.js'][252] = 0; + _$jscoverage['plugins/list.js'][254] = 0; + _$jscoverage['plugins/list.js'][255] = 0; + _$jscoverage['plugins/list.js'][256] = 0; + _$jscoverage['plugins/list.js'][261] = 0; + _$jscoverage['plugins/list.js'][262] = 0; + _$jscoverage['plugins/list.js'][263] = 0; + _$jscoverage['plugins/list.js'][267] = 0; + _$jscoverage['plugins/list.js'][268] = 0; + _$jscoverage['plugins/list.js'][269] = 0; + _$jscoverage['plugins/list.js'][271] = 0; + _$jscoverage['plugins/list.js'][272] = 0; + _$jscoverage['plugins/list.js'][273] = 0; + _$jscoverage['plugins/list.js'][274] = 0; + _$jscoverage['plugins/list.js'][275] = 0; + _$jscoverage['plugins/list.js'][276] = 0; + _$jscoverage['plugins/list.js'][279] = 0; + _$jscoverage['plugins/list.js'][282] = 0; + _$jscoverage['plugins/list.js'][285] = 0; + _$jscoverage['plugins/list.js'][286] = 0; + _$jscoverage['plugins/list.js'][287] = 0; + _$jscoverage['plugins/list.js'][289] = 0; + _$jscoverage['plugins/list.js'][291] = 0; + _$jscoverage['plugins/list.js'][293] = 0; + _$jscoverage['plugins/list.js'][294] = 0; + _$jscoverage['plugins/list.js'][295] = 0; + _$jscoverage['plugins/list.js'][297] = 0; + _$jscoverage['plugins/list.js'][299] = 0; + _$jscoverage['plugins/list.js'][300] = 0; + _$jscoverage['plugins/list.js'][301] = 0; + _$jscoverage['plugins/list.js'][302] = 0; + _$jscoverage['plugins/list.js'][304] = 0; + _$jscoverage['plugins/list.js'][305] = 0; + _$jscoverage['plugins/list.js'][307] = 0; + _$jscoverage['plugins/list.js'][308] = 0; + _$jscoverage['plugins/list.js'][311] = 0; + _$jscoverage['plugins/list.js'][312] = 0; + _$jscoverage['plugins/list.js'][313] = 0; + _$jscoverage['plugins/list.js'][319] = 0; + _$jscoverage['plugins/list.js'][320] = 0; + _$jscoverage['plugins/list.js'][323] = 0; + _$jscoverage['plugins/list.js'][324] = 0; + _$jscoverage['plugins/list.js'][326] = 0; + _$jscoverage['plugins/list.js'][327] = 0; + _$jscoverage['plugins/list.js'][329] = 0; + _$jscoverage['plugins/list.js'][330] = 0; + _$jscoverage['plugins/list.js'][331] = 0; + _$jscoverage['plugins/list.js'][333] = 0; + _$jscoverage['plugins/list.js'][334] = 0; + _$jscoverage['plugins/list.js'][335] = 0; + _$jscoverage['plugins/list.js'][336] = 0; + _$jscoverage['plugins/list.js'][340] = 0; + _$jscoverage['plugins/list.js'][341] = 0; + _$jscoverage['plugins/list.js'][342] = 0; + _$jscoverage['plugins/list.js'][343] = 0; + _$jscoverage['plugins/list.js'][346] = 0; + _$jscoverage['plugins/list.js'][347] = 0; + _$jscoverage['plugins/list.js'][351] = 0; + _$jscoverage['plugins/list.js'][352] = 0; + _$jscoverage['plugins/list.js'][353] = 0; + _$jscoverage['plugins/list.js'][354] = 0; + _$jscoverage['plugins/list.js'][355] = 0; + _$jscoverage['plugins/list.js'][356] = 0; + _$jscoverage['plugins/list.js'][357] = 0; + _$jscoverage['plugins/list.js'][358] = 0; + _$jscoverage['plugins/list.js'][360] = 0; + _$jscoverage['plugins/list.js'][361] = 0; + _$jscoverage['plugins/list.js'][363] = 0; + _$jscoverage['plugins/list.js'][364] = 0; + _$jscoverage['plugins/list.js'][365] = 0; + _$jscoverage['plugins/list.js'][366] = 0; + _$jscoverage['plugins/list.js'][367] = 0; + _$jscoverage['plugins/list.js'][368] = 0; + _$jscoverage['plugins/list.js'][372] = 0; + _$jscoverage['plugins/list.js'][373] = 0; + _$jscoverage['plugins/list.js'][374] = 0; + _$jscoverage['plugins/list.js'][375] = 0; + _$jscoverage['plugins/list.js'][377] = 0; + _$jscoverage['plugins/list.js'][379] = 0; + _$jscoverage['plugins/list.js'][380] = 0; + _$jscoverage['plugins/list.js'][384] = 0; + _$jscoverage['plugins/list.js'][386] = 0; + _$jscoverage['plugins/list.js'][389] = 0; + _$jscoverage['plugins/list.js'][391] = 0; + _$jscoverage['plugins/list.js'][392] = 0; + _$jscoverage['plugins/list.js'][393] = 0; + _$jscoverage['plugins/list.js'][396] = 0; + _$jscoverage['plugins/list.js'][399] = 0; + _$jscoverage['plugins/list.js'][400] = 0; + _$jscoverage['plugins/list.js'][401] = 0; + _$jscoverage['plugins/list.js'][402] = 0; + _$jscoverage['plugins/list.js'][403] = 0; + _$jscoverage['plugins/list.js'][404] = 0; + _$jscoverage['plugins/list.js'][407] = 0; + _$jscoverage['plugins/list.js'][408] = 0; + _$jscoverage['plugins/list.js'][410] = 0; + _$jscoverage['plugins/list.js'][411] = 0; + _$jscoverage['plugins/list.js'][412] = 0; + _$jscoverage['plugins/list.js'][414] = 0; + _$jscoverage['plugins/list.js'][415] = 0; + _$jscoverage['plugins/list.js'][417] = 0; + _$jscoverage['plugins/list.js'][418] = 0; + _$jscoverage['plugins/list.js'][419] = 0; + _$jscoverage['plugins/list.js'][423] = 0; + _$jscoverage['plugins/list.js'][424] = 0; + _$jscoverage['plugins/list.js'][425] = 0; + _$jscoverage['plugins/list.js'][427] = 0; + _$jscoverage['plugins/list.js'][428] = 0; + _$jscoverage['plugins/list.js'][431] = 0; + _$jscoverage['plugins/list.js'][432] = 0; + _$jscoverage['plugins/list.js'][433] = 0; + _$jscoverage['plugins/list.js'][434] = 0; + _$jscoverage['plugins/list.js'][436] = 0; + _$jscoverage['plugins/list.js'][437] = 0; + _$jscoverage['plugins/list.js'][438] = 0; + _$jscoverage['plugins/list.js'][442] = 0; + _$jscoverage['plugins/list.js'][443] = 0; + _$jscoverage['plugins/list.js'][444] = 0; + _$jscoverage['plugins/list.js'][445] = 0; + _$jscoverage['plugins/list.js'][446] = 0; + _$jscoverage['plugins/list.js'][448] = 0; + _$jscoverage['plugins/list.js'][449] = 0; + _$jscoverage['plugins/list.js'][450] = 0; + _$jscoverage['plugins/list.js'][451] = 0; + _$jscoverage['plugins/list.js'][453] = 0; + _$jscoverage['plugins/list.js'][454] = 0; + _$jscoverage['plugins/list.js'][456] = 0; + _$jscoverage['plugins/list.js'][458] = 0; + _$jscoverage['plugins/list.js'][460] = 0; + _$jscoverage['plugins/list.js'][461] = 0; + _$jscoverage['plugins/list.js'][462] = 0; + _$jscoverage['plugins/list.js'][463] = 0; + _$jscoverage['plugins/list.js'][465] = 0; + _$jscoverage['plugins/list.js'][466] = 0; + _$jscoverage['plugins/list.js'][467] = 0; + _$jscoverage['plugins/list.js'][468] = 0; + _$jscoverage['plugins/list.js'][469] = 0; + _$jscoverage['plugins/list.js'][470] = 0; + _$jscoverage['plugins/list.js'][471] = 0; + _$jscoverage['plugins/list.js'][472] = 0; + _$jscoverage['plugins/list.js'][475] = 0; + _$jscoverage['plugins/list.js'][477] = 0; + _$jscoverage['plugins/list.js'][480] = 0; + _$jscoverage['plugins/list.js'][483] = 0; + _$jscoverage['plugins/list.js'][485] = 0; + _$jscoverage['plugins/list.js'][486] = 0; + _$jscoverage['plugins/list.js'][487] = 0; + _$jscoverage['plugins/list.js'][488] = 0; + _$jscoverage['plugins/list.js'][489] = 0; + _$jscoverage['plugins/list.js'][490] = 0; + _$jscoverage['plugins/list.js'][491] = 0; + _$jscoverage['plugins/list.js'][493] = 0; + _$jscoverage['plugins/list.js'][494] = 0; + _$jscoverage['plugins/list.js'][495] = 0; + _$jscoverage['plugins/list.js'][497] = 0; + _$jscoverage['plugins/list.js'][498] = 0; + _$jscoverage['plugins/list.js'][499] = 0; + _$jscoverage['plugins/list.js'][500] = 0; + _$jscoverage['plugins/list.js'][501] = 0; + _$jscoverage['plugins/list.js'][504] = 0; + _$jscoverage['plugins/list.js'][506] = 0; + _$jscoverage['plugins/list.js'][510] = 0; + _$jscoverage['plugins/list.js'][512] = 0; + _$jscoverage['plugins/list.js'][513] = 0; + _$jscoverage['plugins/list.js'][514] = 0; + _$jscoverage['plugins/list.js'][516] = 0; + _$jscoverage['plugins/list.js'][520] = 0; + _$jscoverage['plugins/list.js'][521] = 0; + _$jscoverage['plugins/list.js'][525] = 0; + _$jscoverage['plugins/list.js'][528] = 0; + _$jscoverage['plugins/list.js'][529] = 0; + _$jscoverage['plugins/list.js'][530] = 0; + _$jscoverage['plugins/list.js'][532] = 0; + _$jscoverage['plugins/list.js'][533] = 0; + _$jscoverage['plugins/list.js'][534] = 0; + _$jscoverage['plugins/list.js'][535] = 0; + _$jscoverage['plugins/list.js'][540] = 0; + _$jscoverage['plugins/list.js'][542] = 0; + _$jscoverage['plugins/list.js'][543] = 0; + _$jscoverage['plugins/list.js'][544] = 0; + _$jscoverage['plugins/list.js'][545] = 0; + _$jscoverage['plugins/list.js'][546] = 0; + _$jscoverage['plugins/list.js'][547] = 0; + _$jscoverage['plugins/list.js'][548] = 0; + _$jscoverage['plugins/list.js'][551] = 0; + _$jscoverage['plugins/list.js'][552] = 0; + _$jscoverage['plugins/list.js'][553] = 0; + _$jscoverage['plugins/list.js'][557] = 0; + _$jscoverage['plugins/list.js'][559] = 0; + _$jscoverage['plugins/list.js'][560] = 0; + _$jscoverage['plugins/list.js'][561] = 0; + _$jscoverage['plugins/list.js'][562] = 0; + _$jscoverage['plugins/list.js'][563] = 0; + _$jscoverage['plugins/list.js'][565] = 0; + _$jscoverage['plugins/list.js'][567] = 0; + _$jscoverage['plugins/list.js'][570] = 0; + _$jscoverage['plugins/list.js'][574] = 0; + _$jscoverage['plugins/list.js'][575] = 0; + _$jscoverage['plugins/list.js'][576] = 0; + _$jscoverage['plugins/list.js'][578] = 0; + _$jscoverage['plugins/list.js'][579] = 0; + _$jscoverage['plugins/list.js'][581] = 0; + _$jscoverage['plugins/list.js'][583] = 0; + _$jscoverage['plugins/list.js'][584] = 0; + _$jscoverage['plugins/list.js'][587] = 0; + _$jscoverage['plugins/list.js'][589] = 0; + _$jscoverage['plugins/list.js'][590] = 0; + _$jscoverage['plugins/list.js'][592] = 0; + _$jscoverage['plugins/list.js'][593] = 0; + _$jscoverage['plugins/list.js'][595] = 0; + _$jscoverage['plugins/list.js'][596] = 0; + _$jscoverage['plugins/list.js'][598] = 0; + _$jscoverage['plugins/list.js'][599] = 0; + _$jscoverage['plugins/list.js'][600] = 0; + _$jscoverage['plugins/list.js'][602] = 0; + _$jscoverage['plugins/list.js'][603] = 0; + _$jscoverage['plugins/list.js'][604] = 0; + _$jscoverage['plugins/list.js'][607] = 0; + _$jscoverage['plugins/list.js'][608] = 0; + _$jscoverage['plugins/list.js'][609] = 0; + _$jscoverage['plugins/list.js'][610] = 0; + _$jscoverage['plugins/list.js'][611] = 0; + _$jscoverage['plugins/list.js'][612] = 0; + _$jscoverage['plugins/list.js'][617] = 0; + _$jscoverage['plugins/list.js'][625] = 0; + _$jscoverage['plugins/list.js'][627] = 0; + _$jscoverage['plugins/list.js'][628] = 0; + _$jscoverage['plugins/list.js'][629] = 0; + _$jscoverage['plugins/list.js'][630] = 0; + _$jscoverage['plugins/list.js'][632] = 0; + _$jscoverage['plugins/list.js'][633] = 0; + _$jscoverage['plugins/list.js'][634] = 0; + _$jscoverage['plugins/list.js'][635] = 0; + _$jscoverage['plugins/list.js'][636] = 0; + _$jscoverage['plugins/list.js'][637] = 0; + _$jscoverage['plugins/list.js'][638] = 0; + _$jscoverage['plugins/list.js'][639] = 0; + _$jscoverage['plugins/list.js'][640] = 0; + _$jscoverage['plugins/list.js'][641] = 0; + _$jscoverage['plugins/list.js'][642] = 0; + _$jscoverage['plugins/list.js'][645] = 0; + _$jscoverage['plugins/list.js'][646] = 0; + _$jscoverage['plugins/list.js'][647] = 0; + _$jscoverage['plugins/list.js'][650] = 0; + _$jscoverage['plugins/list.js'][651] = 0; + _$jscoverage['plugins/list.js'][653] = 0; + _$jscoverage['plugins/list.js'][654] = 0; + _$jscoverage['plugins/list.js'][655] = 0; + _$jscoverage['plugins/list.js'][656] = 0; + _$jscoverage['plugins/list.js'][658] = 0; + _$jscoverage['plugins/list.js'][659] = 0; + _$jscoverage['plugins/list.js'][661] = 0; + _$jscoverage['plugins/list.js'][662] = 0; + _$jscoverage['plugins/list.js'][666] = 0; + _$jscoverage['plugins/list.js'][667] = 0; + _$jscoverage['plugins/list.js'][669] = 0; + _$jscoverage['plugins/list.js'][670] = 0; + _$jscoverage['plugins/list.js'][672] = 0; + _$jscoverage['plugins/list.js'][673] = 0; + _$jscoverage['plugins/list.js'][675] = 0; + _$jscoverage['plugins/list.js'][679] = 0; + _$jscoverage['plugins/list.js'][680] = 0; + _$jscoverage['plugins/list.js'][681] = 0; + _$jscoverage['plugins/list.js'][682] = 0; + _$jscoverage['plugins/list.js'][685] = 0; + _$jscoverage['plugins/list.js'][686] = 0; + _$jscoverage['plugins/list.js'][687] = 0; + _$jscoverage['plugins/list.js'][691] = 0; + _$jscoverage['plugins/list.js'][692] = 0; + _$jscoverage['plugins/list.js'][693] = 0; + _$jscoverage['plugins/list.js'][694] = 0; + _$jscoverage['plugins/list.js'][695] = 0; + _$jscoverage['plugins/list.js'][700] = 0; + _$jscoverage['plugins/list.js'][701] = 0; + _$jscoverage['plugins/list.js'][702] = 0; + _$jscoverage['plugins/list.js'][703] = 0; + _$jscoverage['plugins/list.js'][704] = 0; + _$jscoverage['plugins/list.js'][705] = 0; + _$jscoverage['plugins/list.js'][706] = 0; + _$jscoverage['plugins/list.js'][710] = 0; + _$jscoverage['plugins/list.js'][711] = 0; + _$jscoverage['plugins/list.js'][714] = 0; + _$jscoverage['plugins/list.js'][715] = 0; + _$jscoverage['plugins/list.js'][716] = 0; + _$jscoverage['plugins/list.js'][720] = 0; + _$jscoverage['plugins/list.js'][721] = 0; + _$jscoverage['plugins/list.js'][722] = 0; + _$jscoverage['plugins/list.js'][723] = 0; + _$jscoverage['plugins/list.js'][724] = 0; + _$jscoverage['plugins/list.js'][737] = 0; + _$jscoverage['plugins/list.js'][738] = 0; + _$jscoverage['plugins/list.js'][739] = 0; + _$jscoverage['plugins/list.js'][740] = 0; + _$jscoverage['plugins/list.js'][741] = 0; + _$jscoverage['plugins/list.js'][742] = 0; + _$jscoverage['plugins/list.js'][747] = 0; + _$jscoverage['plugins/list.js'][749] = 0; + _$jscoverage['plugins/list.js'][752] = 0; + _$jscoverage['plugins/list.js'][753] = 0; + _$jscoverage['plugins/list.js'][754] = 0; + _$jscoverage['plugins/list.js'][755] = 0; + _$jscoverage['plugins/list.js'][756] = 0; + _$jscoverage['plugins/list.js'][757] = 0; + _$jscoverage['plugins/list.js'][759] = 0; + _$jscoverage['plugins/list.js'][760] = 0; + _$jscoverage['plugins/list.js'][766] = 0; + _$jscoverage['plugins/list.js'][767] = 0; + _$jscoverage['plugins/list.js'][769] = 0; + _$jscoverage['plugins/list.js'][770] = 0; + _$jscoverage['plugins/list.js'][771] = 0; + _$jscoverage['plugins/list.js'][772] = 0; + _$jscoverage['plugins/list.js'][773] = 0; + _$jscoverage['plugins/list.js'][776] = 0; + _$jscoverage['plugins/list.js'][777] = 0; + _$jscoverage['plugins/list.js'][778] = 0; + _$jscoverage['plugins/list.js'][779] = 0; + _$jscoverage['plugins/list.js'][780] = 0; + _$jscoverage['plugins/list.js'][781] = 0; + _$jscoverage['plugins/list.js'][782] = 0; + _$jscoverage['plugins/list.js'][783] = 0; + _$jscoverage['plugins/list.js'][784] = 0; + _$jscoverage['plugins/list.js'][785] = 0; + _$jscoverage['plugins/list.js'][786] = 0; + _$jscoverage['plugins/list.js'][787] = 0; + _$jscoverage['plugins/list.js'][790] = 0; + _$jscoverage['plugins/list.js'][791] = 0; + _$jscoverage['plugins/list.js'][792] = 0; + _$jscoverage['plugins/list.js'][793] = 0; + _$jscoverage['plugins/list.js'][794] = 0; + _$jscoverage['plugins/list.js'][795] = 0; + _$jscoverage['plugins/list.js'][798] = 0; + _$jscoverage['plugins/list.js'][799] = 0; + _$jscoverage['plugins/list.js'][800] = 0; + _$jscoverage['plugins/list.js'][801] = 0; + _$jscoverage['plugins/list.js'][802] = 0; + _$jscoverage['plugins/list.js'][803] = 0; + _$jscoverage['plugins/list.js'][805] = 0; + _$jscoverage['plugins/list.js'][808] = 0; + _$jscoverage['plugins/list.js'][809] = 0; + _$jscoverage['plugins/list.js'][810] = 0; + _$jscoverage['plugins/list.js'][811] = 0; + _$jscoverage['plugins/list.js'][812] = 0; + _$jscoverage['plugins/list.js'][813] = 0; + _$jscoverage['plugins/list.js'][814] = 0; + _$jscoverage['plugins/list.js'][815] = 0; + _$jscoverage['plugins/list.js'][816] = 0; + _$jscoverage['plugins/list.js'][817] = 0; + _$jscoverage['plugins/list.js'][818] = 0; + _$jscoverage['plugins/list.js'][819] = 0; + _$jscoverage['plugins/list.js'][823] = 0; + _$jscoverage['plugins/list.js'][825] = 0; + _$jscoverage['plugins/list.js'][827] = 0; + _$jscoverage['plugins/list.js'][829] = 0; + _$jscoverage['plugins/list.js'][830] = 0; + _$jscoverage['plugins/list.js'][833] = 0; + _$jscoverage['plugins/list.js'][834] = 0; + _$jscoverage['plugins/list.js'][835] = 0; + _$jscoverage['plugins/list.js'][840] = 0; + _$jscoverage['plugins/list.js'][841] = 0; + _$jscoverage['plugins/list.js'][842] = 0; + _$jscoverage['plugins/list.js'][843] = 0; + _$jscoverage['plugins/list.js'][845] = 0; + _$jscoverage['plugins/list.js'][846] = 0; + _$jscoverage['plugins/list.js'][848] = 0; + _$jscoverage['plugins/list.js'][921] = 0; + _$jscoverage['plugins/list.js'][925] = 0; + _$jscoverage['plugins/list.js'][926] = 0; + _$jscoverage['plugins/list.js'][928] = 0; + _$jscoverage['plugins/list.js'][931] = 0; + _$jscoverage['plugins/list.js'][937] = 0; + _$jscoverage['plugins/list.js'][938] = 0; + _$jscoverage['plugins/list.js'][946] = 0; + _$jscoverage['plugins/list.js'][947] = 0; + _$jscoverage['plugins/list.js'][948] = 0; + _$jscoverage['plugins/list.js'][949] = 0; + _$jscoverage['plugins/list.js'][951] = 0; + _$jscoverage['plugins/list.js'][953] = 0; + _$jscoverage['plugins/list.js'][954] = 0; + _$jscoverage['plugins/list.js'][955] = 0; + _$jscoverage['plugins/list.js'][956] = 0; + _$jscoverage['plugins/list.js'][957] = 0; + _$jscoverage['plugins/list.js'][958] = 0; + _$jscoverage['plugins/list.js'][959] = 0; + _$jscoverage['plugins/list.js'][960] = 0; + _$jscoverage['plugins/list.js'][962] = 0; + _$jscoverage['plugins/list.js'][964] = 0; + _$jscoverage['plugins/list.js'][966] = 0; + _$jscoverage['plugins/list.js'][967] = 0; + _$jscoverage['plugins/list.js'][968] = 0; + _$jscoverage['plugins/list.js'][969] = 0; + _$jscoverage['plugins/list.js'][970] = 0; + _$jscoverage['plugins/list.js'][971] = 0; + _$jscoverage['plugins/list.js'][973] = 0; + _$jscoverage['plugins/list.js'][975] = 0; + _$jscoverage['plugins/list.js'][976] = 0; + _$jscoverage['plugins/list.js'][977] = 0; + _$jscoverage['plugins/list.js'][978] = 0; + _$jscoverage['plugins/list.js'][980] = 0; + _$jscoverage['plugins/list.js'][981] = 0; + _$jscoverage['plugins/list.js'][983] = 0; + _$jscoverage['plugins/list.js'][984] = 0; + _$jscoverage['plugins/list.js'][985] = 0; + _$jscoverage['plugins/list.js'][986] = 0; + _$jscoverage['plugins/list.js'][987] = 0; + _$jscoverage['plugins/list.js'][988] = 0; + _$jscoverage['plugins/list.js'][989] = 0; + _$jscoverage['plugins/list.js'][994] = 0; + _$jscoverage['plugins/list.js'][995] = 0; + _$jscoverage['plugins/list.js'][1000] = 0; + _$jscoverage['plugins/list.js'][1002] = 0; + _$jscoverage['plugins/list.js'][1003] = 0; + _$jscoverage['plugins/list.js'][1004] = 0; + _$jscoverage['plugins/list.js'][1005] = 0; + _$jscoverage['plugins/list.js'][1008] = 0; + _$jscoverage['plugins/list.js'][1009] = 0; + _$jscoverage['plugins/list.js'][1010] = 0; + _$jscoverage['plugins/list.js'][1011] = 0; + _$jscoverage['plugins/list.js'][1014] = 0; + _$jscoverage['plugins/list.js'][1015] = 0; + _$jscoverage['plugins/list.js'][1016] = 0; + _$jscoverage['plugins/list.js'][1017] = 0; + _$jscoverage['plugins/list.js'][1018] = 0; + _$jscoverage['plugins/list.js'][1020] = 0; + _$jscoverage['plugins/list.js'][1022] = 0; + _$jscoverage['plugins/list.js'][1023] = 0; + _$jscoverage['plugins/list.js'][1024] = 0; + _$jscoverage['plugins/list.js'][1026] = 0; + _$jscoverage['plugins/list.js'][1028] = 0; + _$jscoverage['plugins/list.js'][1029] = 0; + _$jscoverage['plugins/list.js'][1030] = 0; + _$jscoverage['plugins/list.js'][1031] = 0; + _$jscoverage['plugins/list.js'][1033] = 0; + _$jscoverage['plugins/list.js'][1035] = 0; + _$jscoverage['plugins/list.js'][1038] = 0; + _$jscoverage['plugins/list.js'][1040] = 0; + _$jscoverage['plugins/list.js'][1041] = 0; + _$jscoverage['plugins/list.js'][1042] = 0; + _$jscoverage['plugins/list.js'][1043] = 0; + _$jscoverage['plugins/list.js'][1045] = 0; + _$jscoverage['plugins/list.js'][1047] = 0; + _$jscoverage['plugins/list.js'][1050] = 0; + _$jscoverage['plugins/list.js'][1052] = 0; + _$jscoverage['plugins/list.js'][1053] = 0; + _$jscoverage['plugins/list.js'][1054] = 0; + _$jscoverage['plugins/list.js'][1055] = 0; + _$jscoverage['plugins/list.js'][1056] = 0; + _$jscoverage['plugins/list.js'][1058] = 0; + _$jscoverage['plugins/list.js'][1059] = 0; + _$jscoverage['plugins/list.js'][1060] = 0; + _$jscoverage['plugins/list.js'][1061] = 0; + _$jscoverage['plugins/list.js'][1062] = 0; + _$jscoverage['plugins/list.js'][1064] = 0; + _$jscoverage['plugins/list.js'][1066] = 0; + _$jscoverage['plugins/list.js'][1067] = 0; + _$jscoverage['plugins/list.js'][1068] = 0; + _$jscoverage['plugins/list.js'][1069] = 0; + _$jscoverage['plugins/list.js'][1071] = 0; + _$jscoverage['plugins/list.js'][1073] = 0; + _$jscoverage['plugins/list.js'][1075] = 0; + _$jscoverage['plugins/list.js'][1077] = 0; + _$jscoverage['plugins/list.js'][1080] = 0; + _$jscoverage['plugins/list.js'][1082] = 0; + _$jscoverage['plugins/list.js'][1083] = 0; + _$jscoverage['plugins/list.js'][1084] = 0; + _$jscoverage['plugins/list.js'][1085] = 0; + _$jscoverage['plugins/list.js'][1086] = 0; + _$jscoverage['plugins/list.js'][1087] = 0; + _$jscoverage['plugins/list.js'][1090] = 0; + _$jscoverage['plugins/list.js'][1096] = 0; + _$jscoverage['plugins/list.js'][1097] = 0; + _$jscoverage['plugins/list.js'][1099] = 0; + _$jscoverage['plugins/list.js'][1100] = 0; + _$jscoverage['plugins/list.js'][1102] = 0; + _$jscoverage['plugins/list.js'][1103] = 0; + _$jscoverage['plugins/list.js'][1106] = 0; + _$jscoverage['plugins/list.js'][1108] = 0; + _$jscoverage['plugins/list.js'][1114] = 0; + _$jscoverage['plugins/list.js'][1116] = 0; + _$jscoverage['plugins/list.js'][1117] = 0; + _$jscoverage['plugins/list.js'][1118] = 0; + _$jscoverage['plugins/list.js'][1119] = 0; + _$jscoverage['plugins/list.js'][1121] = 0; + _$jscoverage['plugins/list.js'][1122] = 0; + _$jscoverage['plugins/list.js'][1123] = 0; + _$jscoverage['plugins/list.js'][1124] = 0; + _$jscoverage['plugins/list.js'][1127] = 0; + _$jscoverage['plugins/list.js'][1128] = 0; + _$jscoverage['plugins/list.js'][1130] = 0; + _$jscoverage['plugins/list.js'][1131] = 0; + _$jscoverage['plugins/list.js'][1132] = 0; + _$jscoverage['plugins/list.js'][1133] = 0; + _$jscoverage['plugins/list.js'][1137] = 0; + _$jscoverage['plugins/list.js'][1138] = 0; + _$jscoverage['plugins/list.js'][1139] = 0; + _$jscoverage['plugins/list.js'][1140] = 0; + _$jscoverage['plugins/list.js'][1141] = 0; + _$jscoverage['plugins/list.js'][1144] = 0; + _$jscoverage['plugins/list.js'][1146] = 0; + _$jscoverage['plugins/list.js'][1148] = 0; + _$jscoverage['plugins/list.js'][1150] = 0; + _$jscoverage['plugins/list.js'][1151] = 0; + _$jscoverage['plugins/list.js'][1152] = 0; + _$jscoverage['plugins/list.js'][1153] = 0; + _$jscoverage['plugins/list.js'][1154] = 0; + _$jscoverage['plugins/list.js'][1156] = 0; + _$jscoverage['plugins/list.js'][1158] = 0; + _$jscoverage['plugins/list.js'][1160] = 0; + _$jscoverage['plugins/list.js'][1163] = 0; + _$jscoverage['plugins/list.js'][1164] = 0; + _$jscoverage['plugins/list.js'][1165] = 0; + _$jscoverage['plugins/list.js'][1166] = 0; + _$jscoverage['plugins/list.js'][1167] = 0; + _$jscoverage['plugins/list.js'][1169] = 0; + _$jscoverage['plugins/list.js'][1171] = 0; + _$jscoverage['plugins/list.js'][1172] = 0; + _$jscoverage['plugins/list.js'][1173] = 0; + _$jscoverage['plugins/list.js'][1176] = 0; + _$jscoverage['plugins/list.js'][1180] = 0; + _$jscoverage['plugins/list.js'][1181] = 0; + _$jscoverage['plugins/list.js'][1182] = 0; + _$jscoverage['plugins/list.js'][1183] = 0; + _$jscoverage['plugins/list.js'][1184] = 0; + _$jscoverage['plugins/list.js'][1186] = 0; + _$jscoverage['plugins/list.js'][1187] = 0; + _$jscoverage['plugins/list.js'][1188] = 0; + _$jscoverage['plugins/list.js'][1190] = 0; + _$jscoverage['plugins/list.js'][1194] = 0; + _$jscoverage['plugins/list.js'][1195] = 0; + _$jscoverage['plugins/list.js'][1197] = 0; + _$jscoverage['plugins/list.js'][1198] = 0; + _$jscoverage['plugins/list.js'][1199] = 0; + _$jscoverage['plugins/list.js'][1200] = 0; + _$jscoverage['plugins/list.js'][1202] = 0; + _$jscoverage['plugins/list.js'][1203] = 0; + _$jscoverage['plugins/list.js'][1204] = 0; + _$jscoverage['plugins/list.js'][1205] = 0; + _$jscoverage['plugins/list.js'][1207] = 0; +} +_$jscoverage['plugins/list.js'].source = ["/**"," * 有序列表,无序列表插件"," * @file"," * @since 1.2.6.1"," */","","UE.plugins['list'] = function () {"," var me = this,"," notExchange = {"," 'TD':1,"," 'PRE':1,"," 'BLOCKQUOTE':1"," };"," var customStyle = {"," 'cn' : 'cn-1-',"," 'cn1' : 'cn-2-',"," 'cn2' : 'cn-3-',"," 'num': 'num-1-',"," 'num1' : 'num-2-',"," 'num2' : 'num-3-',"," 'dash' : 'dash',"," 'dot':'dot'"," };",""," me.setOpt( {"," 'insertorderedlist':{"," 'num':'',"," 'num1':'',"," 'num2':'',"," 'cn':'',"," 'cn1':'',"," 'cn2':'',"," 'decimal':'',"," 'lower-alpha':'',"," 'lower-roman':'',"," 'upper-alpha':'',"," 'upper-roman':''"," },"," 'insertunorderedlist':{"," 'circle':'',"," 'disc':'',"," 'square':'',"," 'dash' : '',"," 'dot':''"," },"," listDefaultPaddingLeft : '30',"," listiconpath : 'http://bs.baidu.com/listicon/',"," maxListLevel : -1//-1不限制"," } );"," function listToArray(list){"," var arr = [];"," for(var p in list){"," arr.push(p)"," }"," return arr;"," }"," var listStyle = {"," 'OL':listToArray(me.options.insertorderedlist),"," 'UL':listToArray(me.options.insertunorderedlist)"," };"," var liiconpath = me.options.listiconpath;",""," //根据用户配置,调整customStyle"," for(var s in customStyle){"," if(!me.options.insertorderedlist.hasOwnProperty(s) && !me.options.insertunorderedlist.hasOwnProperty(s)){"," delete customStyle[s];"," }"," }",""," me.ready(function () {"," var customCss = [];"," for(var p in customStyle){"," if(p == 'dash' || p == 'dot'){"," customCss.push('li.list-' + customStyle[p] + '{background-image:url(' + liiconpath +customStyle[p]+'.gif)}');"," customCss.push('ul.custom_'+p+'{list-style:none;}ul.custom_'+p+' li{background-position:0 3px;background-repeat:no-repeat}');"," }else{"," for(var i= 0;i<99;i++){"," customCss.push('li.list-' + customStyle[p] + i + '{background-image:url(' + liiconpath + 'list-'+customStyle[p] + i + '.gif)}')"," }"," customCss.push('ol.custom_'+p+'{list-style:none;}ol.custom_'+p+' li{background-position:0 3px;background-repeat:no-repeat}');"," }"," switch(p){"," case 'cn':"," customCss.push('li.list-'+p+'-paddingleft-1{padding-left:25px}');"," customCss.push('li.list-'+p+'-paddingleft-2{padding-left:40px}');"," customCss.push('li.list-'+p+'-paddingleft-3{padding-left:55px}');"," break;"," case 'cn1':"," customCss.push('li.list-'+p+'-paddingleft-1{padding-left:30px}');"," customCss.push('li.list-'+p+'-paddingleft-2{padding-left:40px}');"," customCss.push('li.list-'+p+'-paddingleft-3{padding-left:55px}');"," break;"," case 'cn2':"," customCss.push('li.list-'+p+'-paddingleft-1{padding-left:40px}');"," customCss.push('li.list-'+p+'-paddingleft-2{padding-left:55px}');"," customCss.push('li.list-'+p+'-paddingleft-3{padding-left:68px}');"," break;"," case 'num':"," case 'num1':"," customCss.push('li.list-'+p+'-paddingleft-1{padding-left:25px}');"," break;"," case 'num2':"," customCss.push('li.list-'+p+'-paddingleft-1{padding-left:35px}');"," customCss.push('li.list-'+p+'-paddingleft-2{padding-left:40px}');"," break;"," case 'dash':"," customCss.push('li.list-'+p+'-paddingleft{padding-left:35px}');"," break;"," case 'dot':"," customCss.push('li.list-'+p+'-paddingleft{padding-left:20px}');"," }"," }"," customCss.push('.list-paddingleft-1{padding-left:0}');"," customCss.push('.list-paddingleft-2{padding-left:'+me.options.listDefaultPaddingLeft+'px}');"," customCss.push('.list-paddingleft-3{padding-left:'+me.options.listDefaultPaddingLeft*2+'px}');"," //如果不给宽度会在自定应样式里出现滚动条"," utils.cssRule('list', 'ol,ul{margin:0;pading:0;'+(browser.ie ? '' : 'width:95%')+'}li{clear:both;}'+customCss.join('\\n'), me.document);"," });"," //单独处理剪切的问题"," me.ready(function(){"," domUtils.on(me.body,'cut',function(){"," setTimeout(function(){"," var rng = me.selection.getRange(),li;"," //trace:3416"," if(!rng.collapsed){"," if(li = domUtils.findParentByTagName(rng.startContainer,'li',true)){"," if(!li.nextSibling && domUtils.isEmptyBlock(li)){"," var pn = li.parentNode,node;"," if(node = pn.previousSibling){"," domUtils.remove(pn);"," rng.setStartAtLast(node).collapse(true);"," rng.select(true);"," }else if(node = pn.nextSibling){"," domUtils.remove(pn);"," rng.setStartAtFirst(node).collapse(true);"," rng.select(true);"," }else{"," var tmpNode = me.document.createElement('p');"," domUtils.fillNode(me.document,tmpNode);"," pn.parentNode.insertBefore(tmpNode,pn);"," domUtils.remove(pn);"," rng.setStart(tmpNode,0).collapse(true);"," rng.select(true);"," }"," }"," }"," }",""," })"," })"," });",""," function getStyle(node){"," var cls = node.className;"," if(domUtils.hasClass(node,/custom_/)){"," return cls.match(/custom_(\\w+)/)[1]"," }"," return domUtils.getStyle(node, 'list-style-type')",""," }",""," me.addListener('beforepaste',function(type,html){"," var me = this,"," rng = me.selection.getRange(),li;"," var root = UE.htmlparser(html.html,true);"," if(li = domUtils.findParentByTagName(rng.startContainer,'li',true)){"," var list = li.parentNode,tagName = list.tagName == 'OL' ? 'ul':'ol';"," utils.each(root.getNodesByTagName(tagName),function(n){"," n.tagName = list.tagName;"," n.setAttr();"," if(n.parentNode === root){"," type = getStyle(list) || (list.tagName == 'OL' ? 'decimal' : 'disc')"," }else{"," var className = n.parentNode.getAttr('class');"," if(className && /custom_/.test(className)){"," type = className.match(/custom_(\\w+)/)[1]"," }else{"," type = n.parentNode.getStyle('list-style-type');"," }"," if(!type){"," type = list.tagName == 'OL' ? 'decimal' : 'disc';"," }"," }"," var index = utils.indexOf(listStyle[list.tagName], type);"," if(n.parentNode !== root)"," index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;"," var currentStyle = listStyle[list.tagName][index];"," if(customStyle[currentStyle]){"," n.setAttr('class', 'custom_' + currentStyle)",""," }else{"," n.setStyle('list-style-type',currentStyle)"," }"," })",""," }",""," html.html = root.toHtml();"," });"," //进入编辑器的li要套p标签"," me.addInputRule(function(root){"," utils.each(root.getNodesByTagName('li'),function(li){"," var tmpP = UE.uNode.createElement('p');"," for(var i= 0,ci;ci=li.children[i];){"," if(ci.type == 'text' || dtd.p[ci.tagName]){"," tmpP.appendChild(ci);"," }else{"," if(tmpP.firstChild()){"," li.insertBefore(tmpP,ci);"," tmpP = UE.uNode.createElement('p');"," i = i + 2;"," }else{"," i++;"," }",""," }"," }"," if(tmpP.firstChild() && !tmpP.parentNode || !li.firstChild()){"," li.appendChild(tmpP);"," }"," //trace:3357"," //p不能为空"," if (!tmpP.firstChild()) {"," tmpP.innerHTML(browser.ie ? '&nbsp;' : '<br/>')"," }"," //去掉末尾的空白"," var p = li.firstChild();"," var lastChild = p.lastChild();"," if(lastChild && lastChild.type == 'text' && /^\\s*$/.test(lastChild.data)){"," p.removeChild(lastChild)"," }"," });"," var orderlisttype = {"," 'num1':/^\\d+\\)/,"," 'decimal':/^\\d+\\./,"," 'lower-alpha':/^[a-z]+\\)/,"," 'upper-alpha':/^[A-Z]+\\./,"," 'cn':/^[\\u4E00\\u4E8C\\u4E09\\u56DB\\u516d\\u4e94\\u4e03\\u516b\\u4e5d]+[\\u3001]/,"," 'cn2':/^\\([\\u4E00\\u4E8C\\u4E09\\u56DB\\u516d\\u4e94\\u4e03\\u516b\\u4e5d]+\\)/"," },"," unorderlisttype = {"," 'square':'n'"," };"," function checkListType(content,container){"," var span = container.firstChild();"," if(span && span.type == 'element' && span.tagName == 'span' && /Wingdings|Symbol/.test(span.getStyle('font-family'))){"," for(var p in unorderlisttype){"," if(unorderlisttype[p] == span.data){"," return p"," }"," }"," return 'disc'"," }"," for(var p in orderlisttype){"," if(orderlisttype[p].test(content)){"," return p;"," }"," }",""," }"," utils.each(root.getNodesByTagName('p'),function(node){"," if(node.getAttr('class') != 'MsoListParagraph'){"," return"," }",""," //word粘贴过来的会带有margin要去掉,但这样也可能会误命中一些央视"," node.setStyle('margin','');"," node.setStyle('margin-left','');"," node.setAttr('class','');",""," function appendLi(list,p,type){"," if(list.tagName == 'ol'){"," if(browser.ie){"," var first = p.firstChild();"," if(first.type =='element' && first.tagName == 'span' && orderlisttype[type].test(first.innerText())){"," p.removeChild(first);"," }"," }else{"," p.innerHTML(p.innerHTML().replace(orderlisttype[type],''));"," }"," }else{"," p.removeChild(p.firstChild())"," }",""," var li = UE.uNode.createElement('li');"," li.appendChild(p);"," list.appendChild(li);"," }"," var tmp = node,type,cacheNode = node;",""," if(node.parentNode.tagName != 'li' && (type = checkListType(node.innerText(),node))){",""," var list = UE.uNode.createElement(me.options.insertorderedlist.hasOwnProperty(type) ? 'ol' : 'ul');"," if(customStyle[type]){"," list.setAttr('class','custom_'+type)"," }else{"," list.setStyle('list-style-type',type)"," }"," while(node && node.parentNode.tagName != 'li' && checkListType(node.innerText(),node)){"," tmp = node.nextSibling();"," if(!tmp){"," node.parentNode.insertBefore(list,node)"," }"," appendLi(list,node,type);"," node = tmp;"," }"," if(!list.parentNode && node && node.parentNode){"," node.parentNode.insertBefore(list,node)"," }"," }"," var span = cacheNode.firstChild();"," if(span && span.type == 'element' && span.tagName == 'span' && /^\\s*(&nbsp;)+\\s*$/.test(span.innerText())){"," span.parentNode.removeChild(span)"," }"," })"," });",""," //调整索引标签"," me.addListener('contentchange',function(){"," adjustListStyle(me.document)"," });",""," function adjustListStyle(doc,ignore){"," utils.each(domUtils.getElementsByTagName(doc,'ol ul'),function(node){",""," if(!domUtils.inDoc(node,doc))"," return;",""," var parent = node.parentNode;"," if(parent.tagName == node.tagName){"," var nodeStyleType = getStyle(node) || (node.tagName == 'OL' ? 'decimal' : 'disc'),"," parentStyleType = getStyle(parent) || (parent.tagName == 'OL' ? 'decimal' : 'disc');"," if(nodeStyleType == parentStyleType){"," var styleIndex = utils.indexOf(listStyle[node.tagName], nodeStyleType);"," styleIndex = styleIndex + 1 == listStyle[node.tagName].length ? 0 : styleIndex + 1;"," setListStyle(node,listStyle[node.tagName][styleIndex])"," }",""," }"," var index = 0,type = 2;"," if( domUtils.hasClass(node,/custom_/)){"," if(!(/[ou]l/i.test(parent.tagName) && domUtils.hasClass(parent,/custom_/))){"," type = 1;"," }"," }else{"," if(/[ou]l/i.test(parent.tagName) && domUtils.hasClass(parent,/custom_/)){"," type = 3;"," }"," }",""," var style = domUtils.getStyle(node, 'list-style-type');"," style && (node.style.cssText = 'list-style-type:' + style);"," node.className = utils.trim(node.className.replace(/list-paddingleft-\\w+/,'')) + ' list-paddingleft-' + type;"," utils.each(domUtils.getElementsByTagName(node,'li'),function(li){"," li.style.cssText && (li.style.cssText = '');"," if(!li.firstChild){"," domUtils.remove(li);"," return;"," }"," if(li.parentNode !== node){"," return;"," }"," index++;"," if(domUtils.hasClass(node,/custom_/) ){"," var paddingLeft = 1,currentStyle = getStyle(node);"," if(node.tagName == 'OL'){"," if(currentStyle){"," switch(currentStyle){"," case 'cn' :"," case 'cn1':"," case 'cn2':"," if(index > 10 && (index % 10 == 0 || index > 10 && index < 20)){"," paddingLeft = 2"," }else if(index > 20){"," paddingLeft = 3"," }"," break;"," case 'num2' :"," if(index > 9){"," paddingLeft = 2"," }"," }"," }"," li.className = 'list-'+customStyle[currentStyle]+ index + ' ' + 'list-'+currentStyle+'-paddingleft-' + paddingLeft;"," }else{"," li.className = 'list-'+customStyle[currentStyle] + ' ' + 'list-'+currentStyle+'-paddingleft';"," }"," }else{"," li.className = li.className.replace(/list-[\\w\\-]+/gi,'');"," }"," var className = li.getAttribute('class');"," if(className !== null && !className.replace(/\\s/g,'')){"," domUtils.removeAttributes(li,'class')"," }"," });"," !ignore && adjustList(node,node.tagName.toLowerCase(),getStyle(node)||domUtils.getStyle(node, 'list-style-type'),true);"," })"," }"," function adjustList(list, tag, style,ignoreEmpty) {"," var nextList = list.nextSibling;"," if (nextList && nextList.nodeType == 1 && nextList.tagName.toLowerCase() == tag && (getStyle(nextList) || domUtils.getStyle(nextList, 'list-style-type') || (tag == 'ol' ? 'decimal' : 'disc')) == style) {"," domUtils.moveChild(nextList, list);"," if (nextList.childNodes.length == 0) {"," domUtils.remove(nextList);"," }"," }"," if(nextList && domUtils.isFillChar(nextList)){"," domUtils.remove(nextList);"," }"," var preList = list.previousSibling;"," if (preList && preList.nodeType == 1 && preList.tagName.toLowerCase() == tag && (getStyle(preList) || domUtils.getStyle(preList, 'list-style-type') || (tag == 'ol' ? 'decimal' : 'disc')) == style) {"," domUtils.moveChild(list, preList);"," }"," if(preList && domUtils.isFillChar(preList)){"," domUtils.remove(preList);"," }"," !ignoreEmpty && domUtils.isEmptyBlock(list) && domUtils.remove(list);"," if(getStyle(list)){"," adjustListStyle(list.ownerDocument,true)"," }"," }",""," function setListStyle(list,style){"," if(customStyle[style]){"," list.className = 'custom_' + style;"," }"," try{"," domUtils.setStyle(list, 'list-style-type', style);"," }catch(e){}"," }"," function clearEmptySibling(node) {"," var tmpNode = node.previousSibling;"," if (tmpNode && domUtils.isEmptyBlock(tmpNode)) {"," domUtils.remove(tmpNode);"," }"," tmpNode = node.nextSibling;"," if (tmpNode && domUtils.isEmptyBlock(tmpNode)) {"," domUtils.remove(tmpNode);"," }"," }",""," me.addListener('keydown', function (type, evt) {"," function preventAndSave() {"," evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);"," me.fireEvent('contentchange');"," me.undoManger && me.undoManger.save();"," }"," function findList(node,filterFn){"," while(node && !domUtils.isBody(node)){"," if(filterFn(node)){"," return null"," }"," if(node.nodeType == 1 && /[ou]l/i.test(node.tagName)){"," return node;"," }"," node = node.parentNode;"," }"," return null;"," }"," var keyCode = evt.keyCode || evt.which;"," if (keyCode == 13 && !evt.shiftKey) {//回车"," var rng = me.selection.getRange(),"," parent = domUtils.findParent(rng.startContainer,function(node){return domUtils.isBlockElm(node)},true),"," li = domUtils.findParentByTagName(rng.startContainer,'li',true);"," if(parent && parent.tagName != 'PRE' && !li){"," var html = parent.innerHTML.replace(new RegExp(domUtils.fillChar, 'g'),'');"," if(/^\\s*1\\s*\\.[^\\d]/.test(html)){"," parent.innerHTML = html.replace(/^\\s*1\\s*\\./,'');"," rng.setStartAtLast(parent).collapse(true).select();"," me.__hasEnterExecCommand = true;"," me.execCommand('insertorderedlist');"," me.__hasEnterExecCommand = false;"," }"," }"," var range = me.selection.getRange(),"," start = findList(range.startContainer,function (node) {"," return node.tagName == 'TABLE';"," }),"," end = range.collapsed ? start : findList(range.endContainer,function (node) {"," return node.tagName == 'TABLE';"," });",""," if (start && end && start === end) {",""," if (!range.collapsed) {"," start = domUtils.findParentByTagName(range.startContainer, 'li', true);"," end = domUtils.findParentByTagName(range.endContainer, 'li', true);"," if (start && end && start === end) {"," range.deleteContents();"," li = domUtils.findParentByTagName(range.startContainer, 'li', true);"," if (li && domUtils.isEmptyBlock(li)) {",""," pre = li.previousSibling;"," next = li.nextSibling;"," p = me.document.createElement('p');",""," domUtils.fillNode(me.document, p);"," parentList = li.parentNode;"," if (pre && next) {"," range.setStart(next, 0).collapse(true).select(true);"," domUtils.remove(li);",""," } else {"," if (!pre && !next || !pre) {",""," parentList.parentNode.insertBefore(p, parentList);","",""," } else {"," li.parentNode.parentNode.insertBefore(p, parentList.nextSibling);"," }"," domUtils.remove(li);"," if (!parentList.firstChild) {"," domUtils.remove(parentList);"," }"," range.setStart(p, 0).setCursor();","",""," }"," preventAndSave();"," return;",""," }"," } else {"," var tmpRange = range.cloneRange(),"," bk = tmpRange.collapse(false).createBookmark();",""," range.deleteContents();"," tmpRange.moveToBookmark(bk);"," var li = domUtils.findParentByTagName(tmpRange.startContainer, 'li', true);",""," clearEmptySibling(li);"," tmpRange.select();"," preventAndSave();"," return;"," }"," }","",""," li = domUtils.findParentByTagName(range.startContainer, 'li', true);",""," if (li) {"," if (domUtils.isEmptyBlock(li)) {"," bk = range.createBookmark();"," var parentList = li.parentNode;"," if (li !== parentList.lastChild) {"," domUtils.breakParent(li, parentList);"," clearEmptySibling(li);"," } else {",""," parentList.parentNode.insertBefore(li, parentList.nextSibling);"," if (domUtils.isEmptyNode(parentList)) {"," domUtils.remove(parentList);"," }"," }"," //嵌套不处理"," if (!dtd.$list[li.parentNode.tagName]) {",""," if (!domUtils.isBlockElm(li.firstChild)) {"," p = me.document.createElement('p');"," li.parentNode.insertBefore(p, li);"," while (li.firstChild) {"," p.appendChild(li.firstChild);"," }"," domUtils.remove(li);"," } else {"," domUtils.remove(li, true);"," }"," }"," range.moveToBookmark(bk).select();","",""," } else {"," var first = li.firstChild;"," if (!first || !domUtils.isBlockElm(first)) {"," var p = me.document.createElement('p');",""," !li.firstChild && domUtils.fillNode(me.document, p);"," while (li.firstChild) {",""," p.appendChild(li.firstChild);"," }"," li.appendChild(p);"," first = p;"," }",""," var span = me.document.createElement('span');",""," range.insertNode(span);"," domUtils.breakParent(span, li);",""," var nextLi = span.nextSibling;"," first = nextLi.firstChild;",""," if (!first) {"," p = me.document.createElement('p');",""," domUtils.fillNode(me.document, p);"," nextLi.appendChild(p);"," first = p;"," }"," if (domUtils.isEmptyNode(first)) {"," first.innerHTML = '';"," domUtils.fillNode(me.document, first);"," }",""," range.setStart(first, 0).collapse(true).shrinkBoundary().select();"," domUtils.remove(span);"," var pre = nextLi.previousSibling;"," if (pre && domUtils.isEmptyBlock(pre)) {"," pre.innerHTML = '<p></p>';"," domUtils.fillNode(me.document, pre.firstChild);"," }",""," }","// }"," preventAndSave();"," }","",""," }","",""," }"," if (keyCode == 8) {"," //修中ie中li下的问题"," range = me.selection.getRange();"," if (range.collapsed && domUtils.isStartInblock(range)) {"," tmpRange = range.cloneRange().trimBoundary();"," li = domUtils.findParentByTagName(range.startContainer, 'li', true);"," //要在li的最左边,才能处理"," if (li && domUtils.isStartInblock(tmpRange)) {"," start = domUtils.findParentByTagName(range.startContainer, 'p', true);"," if (start && start !== li.firstChild) {"," var parentList = domUtils.findParentByTagName(start,['ol','ul']);"," domUtils.breakParent(start,parentList);"," clearEmptySibling(start);"," me.fireEvent('contentchange');"," range.setStart(start,0).setCursor(false,true);"," me.fireEvent('saveScene');"," domUtils.preventDefault(evt);"," return;"," }",""," if (li && (pre = li.previousSibling)) {"," if (keyCode == 46 && li.childNodes.length) {"," return;"," }"," //有可能上边的兄弟节点是个2级菜单,要追加到2级菜单的最后的li"," if (dtd.$list[pre.tagName]) {"," pre = pre.lastChild;"," }"," me.undoManger && me.undoManger.save();"," first = li.firstChild;"," if (domUtils.isBlockElm(first)) {"," if (domUtils.isEmptyNode(first)) {","// range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true);"," pre.appendChild(first);"," range.setStart(first, 0).setCursor(false, true);"," //first不是唯一的节点"," while (li.firstChild) {"," pre.appendChild(li.firstChild);"," }"," } else {",""," span = me.document.createElement('span');"," range.insertNode(span);"," //判断pre是否是空的节点,如果是<p><br/></p>类型的空节点,干掉p标签防止它占位"," if (domUtils.isEmptyBlock(pre)) {"," pre.innerHTML = '';"," }"," domUtils.moveChild(li, pre);"," range.setStartBefore(span).collapse(true).select(true);",""," domUtils.remove(span);",""," }"," } else {"," if (domUtils.isEmptyNode(li)) {"," var p = me.document.createElement('p');"," pre.appendChild(p);"," range.setStart(p, 0).setCursor();","// range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true);"," } else {"," range.setEnd(pre, pre.childNodes.length).collapse().select(true);"," while (li.firstChild) {"," pre.appendChild(li.firstChild);"," }"," }"," }"," domUtils.remove(li);"," me.fireEvent('contentchange');"," me.fireEvent('saveScene');"," domUtils.preventDefault(evt);"," return;",""," }"," //trace:980",""," if (li && !li.previousSibling) {"," var parentList = li.parentNode;"," var bk = range.createBookmark();"," if(domUtils.isTagNode(parentList.parentNode,'ol ul')){"," parentList.parentNode.insertBefore(li,parentList);"," if(domUtils.isEmptyNode(parentList)){"," domUtils.remove(parentList)"," }"," }else{",""," while(li.firstChild){"," parentList.parentNode.insertBefore(li.firstChild,parentList);"," }",""," domUtils.remove(li);"," if(domUtils.isEmptyNode(parentList)){"," domUtils.remove(parentList)"," }",""," }"," range.moveToBookmark(bk).setCursor(false,true);"," me.fireEvent('contentchange');"," me.fireEvent('saveScene');"," domUtils.preventDefault(evt);"," return;",""," }","",""," }","",""," }",""," }"," });",""," me.addListener('keyup',function(type, evt){"," var keyCode = evt.keyCode || evt.which;"," if (keyCode == 8) {"," var rng = me.selection.getRange(),list;"," if(list = domUtils.findParentByTagName(rng.startContainer,['ol', 'ul'],true)){"," adjustList(list,list.tagName.toLowerCase(),getStyle(list)||domUtils.getComputedStyle(list,'list-style-type'),true)"," }"," }"," });"," //处理tab键"," me.addListener('tabkeydown',function(){",""," var range = me.selection.getRange();",""," //控制级数"," function checkLevel(li){"," if(me.options.maxListLevel != -1){"," var level = li.parentNode,levelNum = 0;"," while(/[ou]l/i.test(level.tagName)){"," levelNum++;"," level = level.parentNode;"," }"," if(levelNum >= me.options.maxListLevel){"," return true;"," }"," }"," }"," //只以开始为准"," //todo 后续改进"," var li = domUtils.findParentByTagName(range.startContainer, 'li', true);"," if(li){",""," var bk;"," if(range.collapsed){"," if(checkLevel(li))"," return true;"," var parentLi = li.parentNode,"," list = me.document.createElement(parentLi.tagName),"," index = utils.indexOf(listStyle[list.tagName], getStyle(parentLi)||domUtils.getComputedStyle(parentLi, 'list-style-type'));"," index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;"," var currentStyle = listStyle[list.tagName][index];"," setListStyle(list,currentStyle);"," if(domUtils.isStartInblock(range)){"," me.fireEvent('saveScene');"," bk = range.createBookmark();"," parentLi.insertBefore(list, li);"," list.appendChild(li);"," adjustList(list,list.tagName.toLowerCase(),currentStyle);"," me.fireEvent('contentchange');"," range.moveToBookmark(bk).select(true);"," return true;"," }"," }else{"," me.fireEvent('saveScene');"," bk = range.createBookmark();"," for(var i= 0,closeList,parents = domUtils.findParents(li),ci;ci=parents[i++];){"," if(domUtils.isTagNode(ci,'ol ul')){"," closeList = ci;"," break;"," }"," }"," var current = li;"," if(bk.end){"," while(current && !(domUtils.getPosition(current, bk.end) & domUtils.POSITION_FOLLOWING)){"," if(checkLevel(current)){"," current = domUtils.getNextDomNode(current,false,null,function(node){return node !== closeList});"," continue;"," }"," var parentLi = current.parentNode,"," list = me.document.createElement(parentLi.tagName),"," index = utils.indexOf(listStyle[list.tagName], getStyle(parentLi)||domUtils.getComputedStyle(parentLi, 'list-style-type'));"," var currentIndex = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;"," var currentStyle = listStyle[list.tagName][currentIndex];"," setListStyle(list,currentStyle);"," parentLi.insertBefore(list, current);"," while(current && !(domUtils.getPosition(current, bk.end) & domUtils.POSITION_FOLLOWING)){"," li = current.nextSibling;"," list.appendChild(current);"," if(!li || domUtils.isTagNode(li,'ol ul')){"," if(li){"," while(li = li.firstChild){"," if(li.tagName == 'LI'){"," break;"," }"," }"," }else{"," li = domUtils.getNextDomNode(current,false,null,function(node){return node !== closeList});"," }"," break;"," }"," current = li;"," }"," adjustList(list,list.tagName.toLowerCase(),currentStyle);"," current = li;"," }"," }"," me.fireEvent('contentchange');"," range.moveToBookmark(bk).select();"," return true;"," }"," }",""," });"," function getLi(start){"," while(start && !domUtils.isBody(start)){"," if(start.nodeName == 'TABLE'){"," return null;"," }"," if(start.nodeName == 'LI'){"," return start"," }"," start = start.parentNode;"," }"," }","",""," /**"," * 运行有序列表命令"," * @command insertorderedlist"," * @method execCommand"," * @param { String } command 命令字符串"," * @param { String } style 插入的有序列表类型,值为:decimal,lower-alpha,lower-roman,upper-alpha,upper-roman"," * @example"," * ```javascript"," * editor.execCommand( 'insertunorderedlist','decimal');"," * ```"," */"," /**"," * 查询当前选区内容是否有序列表"," * @command insertorderedlist"," * @method queryCommandState"," * @param { String } cmd 命令字符串"," * @return { int } 如果当前选区是有序列表返回1,否则返回0"," * @example"," * ```javascript"," * editor.queryCommandState( 'insertorderedlist' );"," * ```"," */"," /**"," * 查询当前选区内容是否有序列表"," * @command insertorderedlist"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { String } 返回当前有序列表的类型,值为null或decimal,lower-alpha,lower-roman,upper-alpha,upper-roman"," * @example"," * ```javascript"," * editor.queryCommandValue( 'insertorderedlist' );"," * ```"," */",""," /**"," * 运行无序列表命令"," * @command insertunorderedlist"," * @method execCommand"," * @param { String } command 命令字符串"," * @param { String } style 插入的无序列表类型,值为:circle,disc,square"," * @example"," * ```javascript"," * editor.execCommand( 'insertunorderedlist','circle');"," * ```"," */"," /**"," * 查询当前是否有word文档粘贴进来的图片"," * @command insertunorderedlist"," * @method insertunorderedlist"," * @param { String } command 命令字符串"," * @return { int } 如果当前选区是无序列表返回1,否则返回0"," * @example"," * ```javascript"," * editor.queryCommandState( 'insertunorderedlist' );"," * ```"," */"," /**"," * 查询当前选区内容是否有序列表"," * @command insertunorderedlist"," * @method queryCommandValue"," * @param { String } command 命令字符串"," * @return { String } 返回当前无序列表的类型,值为null或circle,disc,square"," * @example"," * ```javascript"," * editor.queryCommandValue( 'insertunorderedlist' );"," * ```"," */",""," me.commands['insertorderedlist'] ="," me.commands['insertunorderedlist'] = {"," execCommand:function (command, style) {",""," if (!style) {"," style = command.toLowerCase() == 'insertorderedlist' ? 'decimal' : 'disc';"," }"," var me = this,"," range = this.selection.getRange(),"," filterFn = function (node) {"," return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' : !domUtils.isWhitespace(node);"," },"," tag = command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul',"," frag = me.document.createDocumentFragment();"," //去掉是因为会出现选到末尾,导致adjustmentBoundary缩到ol/ul的位置"," //range.shrinkBoundary();//.adjustmentBoundary();"," range.adjustmentBoundary().shrinkBoundary();"," var bko = range.createBookmark(true),"," start = getLi(me.document.getElementById(bko.start)),"," modifyStart = 0,"," end = getLi(me.document.getElementById(bko.end)),"," modifyEnd = 0,"," startParent, endParent,"," list, tmp;",""," if (start || end) {"," start && (startParent = start.parentNode);"," if (!bko.end) {"," end = start;"," }"," end && (endParent = end.parentNode);",""," if (startParent === endParent) {"," while (start !== end) {"," tmp = start;"," start = start.nextSibling;"," if (!domUtils.isBlockElm(tmp.firstChild)) {"," var p = me.document.createElement('p');"," while (tmp.firstChild) {"," p.appendChild(tmp.firstChild);"," }"," tmp.appendChild(p);"," }"," frag.appendChild(tmp);"," }"," tmp = me.document.createElement('span');"," startParent.insertBefore(tmp, end);"," if (!domUtils.isBlockElm(end.firstChild)) {"," p = me.document.createElement('p');"," while (end.firstChild) {"," p.appendChild(end.firstChild);"," }"," end.appendChild(p);"," }"," frag.appendChild(end);"," domUtils.breakParent(tmp, startParent);"," if (domUtils.isEmptyNode(tmp.previousSibling)) {"," domUtils.remove(tmp.previousSibling);"," }"," if (domUtils.isEmptyNode(tmp.nextSibling)) {"," domUtils.remove(tmp.nextSibling)"," }"," var nodeStyle = getStyle(startParent) || domUtils.getComputedStyle(startParent, 'list-style-type') || (command.toLowerCase() == 'insertorderedlist' ? 'decimal' : 'disc');"," if (startParent.tagName.toLowerCase() == tag && nodeStyle == style) {"," for (var i = 0, ci, tmpFrag = me.document.createDocumentFragment(); ci = frag.childNodes[i++];) {"," if(domUtils.isTagNode(ci,'ol ul')){"," utils.each(domUtils.getElementsByTagName(ci,'li'),function(li){"," while(li.firstChild){"," tmpFrag.appendChild(li.firstChild);"," }",""," });"," }else{"," while (ci.firstChild) {"," tmpFrag.appendChild(ci.firstChild);"," }"," }",""," }"," tmp.parentNode.insertBefore(tmpFrag, tmp);"," } else {"," list = me.document.createElement(tag);"," setListStyle(list,style);"," list.appendChild(frag);"," tmp.parentNode.insertBefore(list, tmp);"," }",""," domUtils.remove(tmp);"," list && adjustList(list, tag, style);"," range.moveToBookmark(bko).select();"," return;"," }"," //开始"," if (start) {"," while (start) {"," tmp = start.nextSibling;"," if (domUtils.isTagNode(start, 'ol ul')) {"," frag.appendChild(start);"," } else {"," var tmpfrag = me.document.createDocumentFragment(),"," hasBlock = 0;"," while (start.firstChild) {"," if (domUtils.isBlockElm(start.firstChild)) {"," hasBlock = 1;"," }"," tmpfrag.appendChild(start.firstChild);"," }"," if (!hasBlock) {"," var tmpP = me.document.createElement('p');"," tmpP.appendChild(tmpfrag);"," frag.appendChild(tmpP);"," } else {"," frag.appendChild(tmpfrag);"," }"," domUtils.remove(start);"," }",""," start = tmp;"," }"," startParent.parentNode.insertBefore(frag, startParent.nextSibling);"," if (domUtils.isEmptyNode(startParent)) {"," range.setStartBefore(startParent);"," domUtils.remove(startParent);"," } else {"," range.setStartAfter(startParent);"," }"," modifyStart = 1;"," }",""," if (end && domUtils.inDoc(endParent, me.document)) {"," //结束"," start = endParent.firstChild;"," while (start && start !== end) {"," tmp = start.nextSibling;"," if (domUtils.isTagNode(start, 'ol ul')) {"," frag.appendChild(start);"," } else {"," tmpfrag = me.document.createDocumentFragment();"," hasBlock = 0;"," while (start.firstChild) {"," if (domUtils.isBlockElm(start.firstChild)) {"," hasBlock = 1;"," }"," tmpfrag.appendChild(start.firstChild);"," }"," if (!hasBlock) {"," tmpP = me.document.createElement('p');"," tmpP.appendChild(tmpfrag);"," frag.appendChild(tmpP);"," } else {"," frag.appendChild(tmpfrag);"," }"," domUtils.remove(start);"," }"," start = tmp;"," }"," var tmpDiv = domUtils.createElement(me.document, 'div', {"," 'tmpDiv':1"," });"," domUtils.moveChild(end, tmpDiv);",""," frag.appendChild(tmpDiv);"," domUtils.remove(end);"," endParent.parentNode.insertBefore(frag, endParent);"," range.setEndBefore(endParent);"," if (domUtils.isEmptyNode(endParent)) {"," domUtils.remove(endParent);"," }",""," modifyEnd = 1;"," }","",""," }",""," if (!modifyStart) {"," range.setStartBefore(me.document.getElementById(bko.start));"," }"," if (bko.end && !modifyEnd) {"," range.setEndAfter(me.document.getElementById(bko.end));"," }"," range.enlarge(true, function (node) {"," return notExchange[node.tagName];"," });",""," frag = me.document.createDocumentFragment();",""," var bk = range.createBookmark(),"," current = domUtils.getNextDomNode(bk.start, false, filterFn),"," tmpRange = range.cloneRange(),"," tmpNode,"," block = domUtils.isBlockElm;",""," while (current && current !== bk.end && (domUtils.getPosition(current, bk.end) & domUtils.POSITION_PRECEDING)) {",""," if (current.nodeType == 3 || dtd.li[current.tagName]) {"," if (current.nodeType == 1 && dtd.$list[current.tagName]) {"," while (current.firstChild) {"," frag.appendChild(current.firstChild);"," }"," tmpNode = domUtils.getNextDomNode(current, false, filterFn);"," domUtils.remove(current);"," current = tmpNode;"," continue;",""," }"," tmpNode = current;"," tmpRange.setStartBefore(current);",""," while (current && current !== bk.end && (!block(current) || domUtils.isBookmarkNode(current) )) {"," tmpNode = current;"," current = domUtils.getNextDomNode(current, false, null, function (node) {"," return !notExchange[node.tagName];"," });"," }",""," if (current && block(current)) {"," tmp = domUtils.getNextDomNode(tmpNode, false, filterFn);"," if (tmp && domUtils.isBookmarkNode(tmp)) {"," current = domUtils.getNextDomNode(tmp, false, filterFn);"," tmpNode = tmp;"," }"," }"," tmpRange.setEndAfter(tmpNode);",""," current = domUtils.getNextDomNode(tmpNode, false, filterFn);",""," var li = range.document.createElement('li');",""," li.appendChild(tmpRange.extractContents());"," if(domUtils.isEmptyNode(li)){"," var tmpNode = range.document.createElement('p');"," while(li.firstChild){"," tmpNode.appendChild(li.firstChild)"," }"," li.appendChild(tmpNode);"," }"," frag.appendChild(li);"," } else {"," current = domUtils.getNextDomNode(current, true, filterFn);"," }"," }"," range.moveToBookmark(bk).collapse(true);"," list = me.document.createElement(tag);"," setListStyle(list,style);"," list.appendChild(frag);"," range.insertNode(list);"," //当前list上下看能否合并"," adjustList(list, tag, style);"," //去掉冗余的tmpDiv"," for (var i = 0, ci, tmpDivs = domUtils.getElementsByTagName(list, 'div'); ci = tmpDivs[i++];) {"," if (ci.getAttribute('tmpDiv')) {"," domUtils.remove(ci, true)"," }"," }"," range.moveToBookmark(bko).select();",""," },"," queryCommandState:function (command) {"," var tag = command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul';"," var path = this.selection.getStartElementPath();"," for(var i= 0,ci;ci = path[i++];){"," if(ci.nodeName == 'TABLE'){"," return 0"," }"," if(tag == ci.nodeName.toLowerCase()){"," return 1"," };"," }"," return 0;",""," },"," queryCommandValue:function (command) {"," var tag = command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul';"," var path = this.selection.getStartElementPath(),"," node;"," for(var i= 0,ci;ci = path[i++];){"," if(ci.nodeName == 'TABLE'){"," node = null;"," break;"," }"," if(tag == ci.nodeName.toLowerCase()){"," node = ci;"," break;"," };"," }"," return node ? getStyle(node) || domUtils.getComputedStyle(node, 'list-style-type') : null;"," }"," };","};",""]; +_$jscoverage['plugins/list.js'][7]++; +UE.plugins.list = (function () { + _$jscoverage['plugins/list.js'][8]++; + var me = this, notExchange = {"TD": 1, "PRE": 1, "BLOCKQUOTE": 1}; + _$jscoverage['plugins/list.js'][14]++; + var customStyle = {"cn": "cn-1-", "cn1": "cn-2-", "cn2": "cn-3-", "num": "num-1-", "num1": "num-2-", "num2": "num-3-", "dash": "dash", "dot": "dot"}; + _$jscoverage['plugins/list.js'][25]++; + me.setOpt({"insertorderedlist": {"num": "", "num1": "", "num2": "", "cn": "", "cn1": "", "cn2": "", "decimal": "", "lower-alpha": "", "lower-roman": "", "upper-alpha": "", "upper-roman": ""}, "insertunorderedlist": {"circle": "", "disc": "", "square": "", "dash": "", "dot": ""}, listDefaultPaddingLeft: "30", listiconpath: "http://bs.baidu.com/listicon/", maxListLevel: -1}); + _$jscoverage['plugins/list.js'][50]++; + function listToArray(list) { + _$jscoverage['plugins/list.js'][51]++; + var arr = []; + _$jscoverage['plugins/list.js'][52]++; + for (var p in list) { + _$jscoverage['plugins/list.js'][53]++; + arr.push(p); +} + _$jscoverage['plugins/list.js'][55]++; + return arr; +} + _$jscoverage['plugins/list.js'][57]++; + var listStyle = {"OL": listToArray(me.options.insertorderedlist), "UL": listToArray(me.options.insertunorderedlist)}; + _$jscoverage['plugins/list.js'][61]++; + var liiconpath = me.options.listiconpath; + _$jscoverage['plugins/list.js'][64]++; + for (var s in customStyle) { + _$jscoverage['plugins/list.js'][65]++; + if (((! me.options.insertorderedlist.hasOwnProperty(s)) && (! me.options.insertunorderedlist.hasOwnProperty(s)))) { + _$jscoverage['plugins/list.js'][66]++; + (delete customStyle[s]); + } +} + _$jscoverage['plugins/list.js'][70]++; + me.ready((function () { + _$jscoverage['plugins/list.js'][71]++; + var customCss = []; + _$jscoverage['plugins/list.js'][72]++; + for (var p in customStyle) { + _$jscoverage['plugins/list.js'][73]++; + if (((p == "dash") || (p == "dot"))) { + _$jscoverage['plugins/list.js'][74]++; + customCss.push(("li.list-" + customStyle[p] + "{background-image:url(" + liiconpath + customStyle[p] + ".gif)}")); + _$jscoverage['plugins/list.js'][75]++; + customCss.push(("ul.custom_" + p + "{list-style:none;}ul.custom_" + p + " li{background-position:0 3px;background-repeat:no-repeat}")); + } + else { + _$jscoverage['plugins/list.js'][77]++; + for (var i = 0; (i < 99); (i++)) { + _$jscoverage['plugins/list.js'][78]++; + customCss.push(("li.list-" + customStyle[p] + i + "{background-image:url(" + liiconpath + "list-" + customStyle[p] + i + ".gif)}")); +} + _$jscoverage['plugins/list.js'][80]++; + customCss.push(("ol.custom_" + p + "{list-style:none;}ol.custom_" + p + " li{background-position:0 3px;background-repeat:no-repeat}")); + } + _$jscoverage['plugins/list.js'][82]++; + switch (p) { + case "cn": + _$jscoverage['plugins/list.js'][84]++; + customCss.push(("li.list-" + p + "-paddingleft-1{padding-left:25px}")); + _$jscoverage['plugins/list.js'][85]++; + customCss.push(("li.list-" + p + "-paddingleft-2{padding-left:40px}")); + _$jscoverage['plugins/list.js'][86]++; + customCss.push(("li.list-" + p + "-paddingleft-3{padding-left:55px}")); + _$jscoverage['plugins/list.js'][87]++; + break; + case "cn1": + _$jscoverage['plugins/list.js'][89]++; + customCss.push(("li.list-" + p + "-paddingleft-1{padding-left:30px}")); + _$jscoverage['plugins/list.js'][90]++; + customCss.push(("li.list-" + p + "-paddingleft-2{padding-left:40px}")); + _$jscoverage['plugins/list.js'][91]++; + customCss.push(("li.list-" + p + "-paddingleft-3{padding-left:55px}")); + _$jscoverage['plugins/list.js'][92]++; + break; + case "cn2": + _$jscoverage['plugins/list.js'][94]++; + customCss.push(("li.list-" + p + "-paddingleft-1{padding-left:40px}")); + _$jscoverage['plugins/list.js'][95]++; + customCss.push(("li.list-" + p + "-paddingleft-2{padding-left:55px}")); + _$jscoverage['plugins/list.js'][96]++; + customCss.push(("li.list-" + p + "-paddingleft-3{padding-left:68px}")); + _$jscoverage['plugins/list.js'][97]++; + break; + case "num": + case "num1": + _$jscoverage['plugins/list.js'][100]++; + customCss.push(("li.list-" + p + "-paddingleft-1{padding-left:25px}")); + _$jscoverage['plugins/list.js'][101]++; + break; + case "num2": + _$jscoverage['plugins/list.js'][103]++; + customCss.push(("li.list-" + p + "-paddingleft-1{padding-left:35px}")); + _$jscoverage['plugins/list.js'][104]++; + customCss.push(("li.list-" + p + "-paddingleft-2{padding-left:40px}")); + _$jscoverage['plugins/list.js'][105]++; + break; + case "dash": + _$jscoverage['plugins/list.js'][107]++; + customCss.push(("li.list-" + p + "-paddingleft{padding-left:35px}")); + _$jscoverage['plugins/list.js'][108]++; + break; + case "dot": + _$jscoverage['plugins/list.js'][110]++; + customCss.push(("li.list-" + p + "-paddingleft{padding-left:20px}")); + } +} + _$jscoverage['plugins/list.js'][113]++; + customCss.push(".list-paddingleft-1{padding-left:0}"); + _$jscoverage['plugins/list.js'][114]++; + customCss.push((".list-paddingleft-2{padding-left:" + me.options.listDefaultPaddingLeft + "px}")); + _$jscoverage['plugins/list.js'][115]++; + customCss.push((".list-paddingleft-3{padding-left:" + (me.options.listDefaultPaddingLeft * 2) + "px}")); + _$jscoverage['plugins/list.js'][117]++; + utils.cssRule("list", ("ol,ul{margin:0;pading:0;" + (browser.ie? "": "width:95%") + "}li{clear:both;}" + customCss.join("\n")), me.document); +})); + _$jscoverage['plugins/list.js'][120]++; + me.ready((function () { + _$jscoverage['plugins/list.js'][121]++; + domUtils.on(me.body, "cut", (function () { + _$jscoverage['plugins/list.js'][122]++; + setTimeout((function () { + _$jscoverage['plugins/list.js'][123]++; + var rng = me.selection.getRange(), li; + _$jscoverage['plugins/list.js'][125]++; + if ((! rng.collapsed)) { + _$jscoverage['plugins/list.js'][126]++; + if ((li = domUtils.findParentByTagName(rng.startContainer, "li", true))) { + _$jscoverage['plugins/list.js'][127]++; + if (((! li.nextSibling) && domUtils.isEmptyBlock(li))) { + _$jscoverage['plugins/list.js'][128]++; + var pn = li.parentNode, node; + _$jscoverage['plugins/list.js'][129]++; + if ((node = pn.previousSibling)) { + _$jscoverage['plugins/list.js'][130]++; + domUtils.remove(pn); + _$jscoverage['plugins/list.js'][131]++; + rng.setStartAtLast(node).collapse(true); + _$jscoverage['plugins/list.js'][132]++; + rng.select(true); + } + else { + _$jscoverage['plugins/list.js'][133]++; + if ((node = pn.nextSibling)) { + _$jscoverage['plugins/list.js'][134]++; + domUtils.remove(pn); + _$jscoverage['plugins/list.js'][135]++; + rng.setStartAtFirst(node).collapse(true); + _$jscoverage['plugins/list.js'][136]++; + rng.select(true); + } + else { + _$jscoverage['plugins/list.js'][138]++; + var tmpNode = me.document.createElement("p"); + _$jscoverage['plugins/list.js'][139]++; + domUtils.fillNode(me.document, tmpNode); + _$jscoverage['plugins/list.js'][140]++; + pn.parentNode.insertBefore(tmpNode, pn); + _$jscoverage['plugins/list.js'][141]++; + domUtils.remove(pn); + _$jscoverage['plugins/list.js'][142]++; + rng.setStart(tmpNode, 0).collapse(true); + _$jscoverage['plugins/list.js'][143]++; + rng.select(true); + } + } + } + } + } +})); +})); +})); + _$jscoverage['plugins/list.js'][153]++; + function getStyle(node) { + _$jscoverage['plugins/list.js'][154]++; + var cls = node.className; + _$jscoverage['plugins/list.js'][155]++; + if (domUtils.hasClass(node, /custom_/)) { + _$jscoverage['plugins/list.js'][156]++; + return cls.match(/custom_(\w+)/)[1]; + } + _$jscoverage['plugins/list.js'][158]++; + return domUtils.getStyle(node, "list-style-type"); +} + _$jscoverage['plugins/list.js'][162]++; + me.addListener("beforepaste", (function (type, html) { + _$jscoverage['plugins/list.js'][163]++; + var me = this, rng = me.selection.getRange(), li; + _$jscoverage['plugins/list.js'][165]++; + var root = UE.htmlparser(html.html, true); + _$jscoverage['plugins/list.js'][166]++; + if ((li = domUtils.findParentByTagName(rng.startContainer, "li", true))) { + _$jscoverage['plugins/list.js'][167]++; + var list = li.parentNode, tagName = ((list.tagName == "OL")? "ul": "ol"); + _$jscoverage['plugins/list.js'][168]++; + utils.each(root.getNodesByTagName(tagName), (function (n) { + _$jscoverage['plugins/list.js'][169]++; + n.tagName = list.tagName; + _$jscoverage['plugins/list.js'][170]++; + n.setAttr(); + _$jscoverage['plugins/list.js'][171]++; + if ((n.parentNode === root)) { + _$jscoverage['plugins/list.js'][172]++; + type = (getStyle(list) || ((list.tagName == "OL")? "decimal": "disc")); + } + else { + _$jscoverage['plugins/list.js'][174]++; + var className = n.parentNode.getAttr("class"); + _$jscoverage['plugins/list.js'][175]++; + if ((className && /custom_/.test(className))) { + _$jscoverage['plugins/list.js'][176]++; + type = className.match(/custom_(\w+)/)[1]; + } + else { + _$jscoverage['plugins/list.js'][178]++; + type = n.parentNode.getStyle("list-style-type"); + } + _$jscoverage['plugins/list.js'][180]++; + if ((! type)) { + _$jscoverage['plugins/list.js'][181]++; + type = ((list.tagName == "OL")? "decimal": "disc"); + } + } + _$jscoverage['plugins/list.js'][184]++; + var index = utils.indexOf(listStyle[list.tagName], type); + _$jscoverage['plugins/list.js'][185]++; + if ((n.parentNode !== root)) { + _$jscoverage['plugins/list.js'][186]++; + index = (((index + 1) == listStyle[list.tagName].length)? 0: (index + 1)); + } + _$jscoverage['plugins/list.js'][187]++; + var currentStyle = listStyle[list.tagName][index]; + _$jscoverage['plugins/list.js'][188]++; + if (customStyle[currentStyle]) { + _$jscoverage['plugins/list.js'][189]++; + n.setAttr("class", ("custom_" + currentStyle)); + } + else { + _$jscoverage['plugins/list.js'][192]++; + n.setStyle("list-style-type", currentStyle); + } +})); + } + _$jscoverage['plugins/list.js'][198]++; + html.html = root.toHtml(); +})); + _$jscoverage['plugins/list.js'][201]++; + me.addInputRule((function (root) { + _$jscoverage['plugins/list.js'][202]++; + utils.each(root.getNodesByTagName("li"), (function (li) { + _$jscoverage['plugins/list.js'][203]++; + var tmpP = UE.uNode.createElement("p"); + _$jscoverage['plugins/list.js'][204]++; + for (var i = 0, ci; (ci = li.children[i]);) { + _$jscoverage['plugins/list.js'][205]++; + if (((ci.type == "text") || dtd.p[ci.tagName])) { + _$jscoverage['plugins/list.js'][206]++; + tmpP.appendChild(ci); + } + else { + _$jscoverage['plugins/list.js'][208]++; + if (tmpP.firstChild()) { + _$jscoverage['plugins/list.js'][209]++; + li.insertBefore(tmpP, ci); + _$jscoverage['plugins/list.js'][210]++; + tmpP = UE.uNode.createElement("p"); + _$jscoverage['plugins/list.js'][211]++; + i = (i + 2); + } + else { + _$jscoverage['plugins/list.js'][213]++; + (i++); + } + } +} + _$jscoverage['plugins/list.js'][218]++; + if (((tmpP.firstChild() && (! tmpP.parentNode)) || (! li.firstChild()))) { + _$jscoverage['plugins/list.js'][219]++; + li.appendChild(tmpP); + } + _$jscoverage['plugins/list.js'][223]++; + if ((! tmpP.firstChild())) { + _$jscoverage['plugins/list.js'][224]++; + tmpP.innerHTML((browser.ie? " ": "
    ")); + } + _$jscoverage['plugins/list.js'][227]++; + var p = li.firstChild(); + _$jscoverage['plugins/list.js'][228]++; + var lastChild = p.lastChild(); + _$jscoverage['plugins/list.js'][229]++; + if ((lastChild && (lastChild.type == "text") && /^\s*$/.test(lastChild.data))) { + _$jscoverage['plugins/list.js'][230]++; + p.removeChild(lastChild); + } +})); + _$jscoverage['plugins/list.js'][233]++; + var orderlisttype = {"num1": /^\d+\)/, "decimal": /^\d+\./, "lower-alpha": /^[a-z]+\)/, "upper-alpha": /^[A-Z]+\./, "cn": /^[\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+[\u3001]/, "cn2": /^\([\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+\)/}, unorderlisttype = {"square": "n"}; + _$jscoverage['plugins/list.js'][244]++; + function checkListType(content, container) { + _$jscoverage['plugins/list.js'][245]++; + var span = container.firstChild(); + _$jscoverage['plugins/list.js'][246]++; + if ((span && (span.type == "element") && (span.tagName == "span") && /Wingdings|Symbol/.test(span.getStyle("font-family")))) { + _$jscoverage['plugins/list.js'][247]++; + for (var p in unorderlisttype) { + _$jscoverage['plugins/list.js'][248]++; + if ((unorderlisttype[p] == span.data)) { + _$jscoverage['plugins/list.js'][249]++; + return p; + } +} + _$jscoverage['plugins/list.js'][252]++; + return "disc"; + } + _$jscoverage['plugins/list.js'][254]++; + for (var p = p in orderlisttype) { + _$jscoverage['plugins/list.js'][255]++; + if (orderlisttype[p].test(content)) { + _$jscoverage['plugins/list.js'][256]++; + return p; + } +} +} + _$jscoverage['plugins/list.js'][261]++; + utils.each(root.getNodesByTagName("p"), (function (node) { + _$jscoverage['plugins/list.js'][262]++; + if ((node.getAttr("class") != "MsoListParagraph")) { + _$jscoverage['plugins/list.js'][263]++; + return; + } + _$jscoverage['plugins/list.js'][267]++; + node.setStyle("margin", ""); + _$jscoverage['plugins/list.js'][268]++; + node.setStyle("margin-left", ""); + _$jscoverage['plugins/list.js'][269]++; + node.setAttr("class", ""); + _$jscoverage['plugins/list.js'][271]++; + function appendLi(list, p, type) { + _$jscoverage['plugins/list.js'][272]++; + if ((list.tagName == "ol")) { + _$jscoverage['plugins/list.js'][273]++; + if (browser.ie) { + _$jscoverage['plugins/list.js'][274]++; + var first = p.firstChild(); + _$jscoverage['plugins/list.js'][275]++; + if (((first.type == "element") && (first.tagName == "span") && orderlisttype[type].test(first.innerText()))) { + _$jscoverage['plugins/list.js'][276]++; + p.removeChild(first); + } + } + else { + _$jscoverage['plugins/list.js'][279]++; + p.innerHTML(p.innerHTML().replace(orderlisttype[type], "")); + } + } + else { + _$jscoverage['plugins/list.js'][282]++; + p.removeChild(p.firstChild()); + } + _$jscoverage['plugins/list.js'][285]++; + var li = UE.uNode.createElement("li"); + _$jscoverage['plugins/list.js'][286]++; + li.appendChild(p); + _$jscoverage['plugins/list.js'][287]++; + list.appendChild(li); +} + _$jscoverage['plugins/list.js'][289]++; + var tmp = node, type, cacheNode = node; + _$jscoverage['plugins/list.js'][291]++; + if (((node.parentNode.tagName != "li") && (type = checkListType(node.innerText(), node)))) { + _$jscoverage['plugins/list.js'][293]++; + var list = UE.uNode.createElement((me.options.insertorderedlist.hasOwnProperty(type)? "ol": "ul")); + _$jscoverage['plugins/list.js'][294]++; + if (customStyle[type]) { + _$jscoverage['plugins/list.js'][295]++; + list.setAttr("class", ("custom_" + type)); + } + else { + _$jscoverage['plugins/list.js'][297]++; + list.setStyle("list-style-type", type); + } + _$jscoverage['plugins/list.js'][299]++; + while ((node && (node.parentNode.tagName != "li") && checkListType(node.innerText(), node))) { + _$jscoverage['plugins/list.js'][300]++; + tmp = node.nextSibling(); + _$jscoverage['plugins/list.js'][301]++; + if ((! tmp)) { + _$jscoverage['plugins/list.js'][302]++; + node.parentNode.insertBefore(list, node); + } + _$jscoverage['plugins/list.js'][304]++; + appendLi(list, node, type); + _$jscoverage['plugins/list.js'][305]++; + node = tmp; +} + _$jscoverage['plugins/list.js'][307]++; + if (((! list.parentNode) && node && node.parentNode)) { + _$jscoverage['plugins/list.js'][308]++; + node.parentNode.insertBefore(list, node); + } + } + _$jscoverage['plugins/list.js'][311]++; + var span = cacheNode.firstChild(); + _$jscoverage['plugins/list.js'][312]++; + if ((span && (span.type == "element") && (span.tagName == "span") && /^\s*( )+\s*$/.test(span.innerText()))) { + _$jscoverage['plugins/list.js'][313]++; + span.parentNode.removeChild(span); + } +})); +})); + _$jscoverage['plugins/list.js'][319]++; + me.addListener("contentchange", (function () { + _$jscoverage['plugins/list.js'][320]++; + adjustListStyle(me.document); +})); + _$jscoverage['plugins/list.js'][323]++; + function adjustListStyle(doc, ignore) { + _$jscoverage['plugins/list.js'][324]++; + utils.each(domUtils.getElementsByTagName(doc, "ol ul"), (function (node) { + _$jscoverage['plugins/list.js'][326]++; + if ((! domUtils.inDoc(node, doc))) { + _$jscoverage['plugins/list.js'][327]++; + return; + } + _$jscoverage['plugins/list.js'][329]++; + var parent = node.parentNode; + _$jscoverage['plugins/list.js'][330]++; + if ((parent.tagName == node.tagName)) { + _$jscoverage['plugins/list.js'][331]++; + var nodeStyleType = (getStyle(node) || ((node.tagName == "OL")? "decimal": "disc")), parentStyleType = (getStyle(parent) || ((parent.tagName == "OL")? "decimal": "disc")); + _$jscoverage['plugins/list.js'][333]++; + if ((nodeStyleType == parentStyleType)) { + _$jscoverage['plugins/list.js'][334]++; + var styleIndex = utils.indexOf(listStyle[node.tagName], nodeStyleType); + _$jscoverage['plugins/list.js'][335]++; + styleIndex = (((styleIndex + 1) == listStyle[node.tagName].length)? 0: (styleIndex + 1)); + _$jscoverage['plugins/list.js'][336]++; + setListStyle(node, listStyle[node.tagName][styleIndex]); + } + } + _$jscoverage['plugins/list.js'][340]++; + var index = 0, type = 2; + _$jscoverage['plugins/list.js'][341]++; + if (domUtils.hasClass(node, /custom_/)) { + _$jscoverage['plugins/list.js'][342]++; + if ((! (/[ou]l/i.test(parent.tagName) && domUtils.hasClass(parent, /custom_/)))) { + _$jscoverage['plugins/list.js'][343]++; + type = 1; + } + } + else { + _$jscoverage['plugins/list.js'][346]++; + if ((/[ou]l/i.test(parent.tagName) && domUtils.hasClass(parent, /custom_/))) { + _$jscoverage['plugins/list.js'][347]++; + type = 3; + } + } + _$jscoverage['plugins/list.js'][351]++; + var style = domUtils.getStyle(node, "list-style-type"); + _$jscoverage['plugins/list.js'][352]++; + (style && (node.style.cssText = ("list-style-type:" + style))); + _$jscoverage['plugins/list.js'][353]++; + node.className = (utils.trim(node.className.replace(/list-paddingleft-\w+/, "")) + " list-paddingleft-" + type); + _$jscoverage['plugins/list.js'][354]++; + utils.each(domUtils.getElementsByTagName(node, "li"), (function (li) { + _$jscoverage['plugins/list.js'][355]++; + (li.style.cssText && (li.style.cssText = "")); + _$jscoverage['plugins/list.js'][356]++; + if ((! li.firstChild)) { + _$jscoverage['plugins/list.js'][357]++; + domUtils.remove(li); + _$jscoverage['plugins/list.js'][358]++; + return; + } + _$jscoverage['plugins/list.js'][360]++; + if ((li.parentNode !== node)) { + _$jscoverage['plugins/list.js'][361]++; + return; + } + _$jscoverage['plugins/list.js'][363]++; + (index++); + _$jscoverage['plugins/list.js'][364]++; + if (domUtils.hasClass(node, /custom_/)) { + _$jscoverage['plugins/list.js'][365]++; + var paddingLeft = 1, currentStyle = getStyle(node); + _$jscoverage['plugins/list.js'][366]++; + if ((node.tagName == "OL")) { + _$jscoverage['plugins/list.js'][367]++; + if (currentStyle) { + _$jscoverage['plugins/list.js'][368]++; + switch (currentStyle) { + case "cn": + case "cn1": + case "cn2": + _$jscoverage['plugins/list.js'][372]++; + if (((index > 10) && (((index % 10) == 0) || ((index > 10) && (index < 20))))) { + _$jscoverage['plugins/list.js'][373]++; + paddingLeft = 2; + } + else { + _$jscoverage['plugins/list.js'][374]++; + if ((index > 20)) { + _$jscoverage['plugins/list.js'][375]++; + paddingLeft = 3; + } + } + _$jscoverage['plugins/list.js'][377]++; + break; + case "num2": + _$jscoverage['plugins/list.js'][379]++; + if ((index > 9)) { + _$jscoverage['plugins/list.js'][380]++; + paddingLeft = 2; + } + } + } + _$jscoverage['plugins/list.js'][384]++; + li.className = ("list-" + customStyle[currentStyle] + index + " " + "list-" + currentStyle + "-paddingleft-" + paddingLeft); + } + else { + _$jscoverage['plugins/list.js'][386]++; + li.className = ("list-" + customStyle[currentStyle] + " " + "list-" + currentStyle + "-paddingleft"); + } + } + else { + _$jscoverage['plugins/list.js'][389]++; + li.className = li.className.replace(/list-[\w\-]+/gi, ""); + } + _$jscoverage['plugins/list.js'][391]++; + var className = li.getAttribute("class"); + _$jscoverage['plugins/list.js'][392]++; + if (((className !== null) && (! className.replace(/\s/g, "")))) { + _$jscoverage['plugins/list.js'][393]++; + domUtils.removeAttributes(li, "class"); + } +})); + _$jscoverage['plugins/list.js'][396]++; + ((! ignore) && adjustList(node, node.tagName.toLowerCase(), (getStyle(node) || domUtils.getStyle(node, "list-style-type")), true)); +})); +} + _$jscoverage['plugins/list.js'][399]++; + function adjustList(list, tag, style, ignoreEmpty) { + _$jscoverage['plugins/list.js'][400]++; + var nextList = list.nextSibling; + _$jscoverage['plugins/list.js'][401]++; + if ((nextList && (nextList.nodeType == 1) && (nextList.tagName.toLowerCase() == tag) && ((getStyle(nextList) || domUtils.getStyle(nextList, "list-style-type") || ((tag == "ol")? "decimal": "disc")) == style))) { + _$jscoverage['plugins/list.js'][402]++; + domUtils.moveChild(nextList, list); + _$jscoverage['plugins/list.js'][403]++; + if ((nextList.childNodes.length == 0)) { + _$jscoverage['plugins/list.js'][404]++; + domUtils.remove(nextList); + } + } + _$jscoverage['plugins/list.js'][407]++; + if ((nextList && domUtils.isFillChar(nextList))) { + _$jscoverage['plugins/list.js'][408]++; + domUtils.remove(nextList); + } + _$jscoverage['plugins/list.js'][410]++; + var preList = list.previousSibling; + _$jscoverage['plugins/list.js'][411]++; + if ((preList && (preList.nodeType == 1) && (preList.tagName.toLowerCase() == tag) && ((getStyle(preList) || domUtils.getStyle(preList, "list-style-type") || ((tag == "ol")? "decimal": "disc")) == style))) { + _$jscoverage['plugins/list.js'][412]++; + domUtils.moveChild(list, preList); + } + _$jscoverage['plugins/list.js'][414]++; + if ((preList && domUtils.isFillChar(preList))) { + _$jscoverage['plugins/list.js'][415]++; + domUtils.remove(preList); + } + _$jscoverage['plugins/list.js'][417]++; + ((! ignoreEmpty) && domUtils.isEmptyBlock(list) && domUtils.remove(list)); + _$jscoverage['plugins/list.js'][418]++; + if (getStyle(list)) { + _$jscoverage['plugins/list.js'][419]++; + adjustListStyle(list.ownerDocument, true); + } +} + _$jscoverage['plugins/list.js'][423]++; + function setListStyle(list, style) { + _$jscoverage['plugins/list.js'][424]++; + if (customStyle[style]) { + _$jscoverage['plugins/list.js'][425]++; + list.className = ("custom_" + style); + } + _$jscoverage['plugins/list.js'][427]++; + try { + _$jscoverage['plugins/list.js'][428]++; + domUtils.setStyle(list, "list-style-type", style); + } + catch (e) { + } +} + _$jscoverage['plugins/list.js'][431]++; + function clearEmptySibling(node) { + _$jscoverage['plugins/list.js'][432]++; + var tmpNode = node.previousSibling; + _$jscoverage['plugins/list.js'][433]++; + if ((tmpNode && domUtils.isEmptyBlock(tmpNode))) { + _$jscoverage['plugins/list.js'][434]++; + domUtils.remove(tmpNode); + } + _$jscoverage['plugins/list.js'][436]++; + tmpNode = node.nextSibling; + _$jscoverage['plugins/list.js'][437]++; + if ((tmpNode && domUtils.isEmptyBlock(tmpNode))) { + _$jscoverage['plugins/list.js'][438]++; + domUtils.remove(tmpNode); + } +} + _$jscoverage['plugins/list.js'][442]++; + me.addListener("keydown", (function (type, evt) { + _$jscoverage['plugins/list.js'][443]++; + function preventAndSave() { + _$jscoverage['plugins/list.js'][444]++; + (evt.preventDefault? evt.preventDefault(): (evt.returnValue = false)); + _$jscoverage['plugins/list.js'][445]++; + me.fireEvent("contentchange"); + _$jscoverage['plugins/list.js'][446]++; + (me.undoManger && me.undoManger.save()); +} + _$jscoverage['plugins/list.js'][448]++; + function findList(node, filterFn) { + _$jscoverage['plugins/list.js'][449]++; + while ((node && (! domUtils.isBody(node)))) { + _$jscoverage['plugins/list.js'][450]++; + if (filterFn(node)) { + _$jscoverage['plugins/list.js'][451]++; + return null; + } + _$jscoverage['plugins/list.js'][453]++; + if (((node.nodeType == 1) && /[ou]l/i.test(node.tagName))) { + _$jscoverage['plugins/list.js'][454]++; + return node; + } + _$jscoverage['plugins/list.js'][456]++; + node = node.parentNode; +} + _$jscoverage['plugins/list.js'][458]++; + return null; +} + _$jscoverage['plugins/list.js'][460]++; + var keyCode = (evt.keyCode || evt.which); + _$jscoverage['plugins/list.js'][461]++; + if (((keyCode == 13) && (! evt.shiftKey))) { + _$jscoverage['plugins/list.js'][462]++; + var rng = me.selection.getRange(), parent = domUtils.findParent(rng.startContainer, (function (node) { + _$jscoverage['plugins/list.js'][463]++; + return domUtils.isBlockElm(node); +}), true), li = domUtils.findParentByTagName(rng.startContainer, "li", true); + _$jscoverage['plugins/list.js'][465]++; + if ((parent && (parent.tagName != "PRE") && (! li))) { + _$jscoverage['plugins/list.js'][466]++; + var html = parent.innerHTML.replace(new RegExp(domUtils.fillChar, "g"), ""); + _$jscoverage['plugins/list.js'][467]++; + if (/^\s*1\s*\.[^\d]/.test(html)) { + _$jscoverage['plugins/list.js'][468]++; + parent.innerHTML = html.replace(/^\s*1\s*\./, ""); + _$jscoverage['plugins/list.js'][469]++; + rng.setStartAtLast(parent).collapse(true).select(); + _$jscoverage['plugins/list.js'][470]++; + me.__hasEnterExecCommand = true; + _$jscoverage['plugins/list.js'][471]++; + me.execCommand("insertorderedlist"); + _$jscoverage['plugins/list.js'][472]++; + me.__hasEnterExecCommand = false; + } + } + _$jscoverage['plugins/list.js'][475]++; + var range = me.selection.getRange(), start = findList(range.startContainer, (function (node) { + _$jscoverage['plugins/list.js'][477]++; + return (node.tagName == "TABLE"); +})), end = (range.collapsed? start: findList(range.endContainer, (function (node) { + _$jscoverage['plugins/list.js'][480]++; + return (node.tagName == "TABLE"); +}))); + _$jscoverage['plugins/list.js'][483]++; + if ((start && end && (start === end))) { + _$jscoverage['plugins/list.js'][485]++; + if ((! range.collapsed)) { + _$jscoverage['plugins/list.js'][486]++; + start = domUtils.findParentByTagName(range.startContainer, "li", true); + _$jscoverage['plugins/list.js'][487]++; + end = domUtils.findParentByTagName(range.endContainer, "li", true); + _$jscoverage['plugins/list.js'][488]++; + if ((start && end && (start === end))) { + _$jscoverage['plugins/list.js'][489]++; + range.deleteContents(); + _$jscoverage['plugins/list.js'][490]++; + li = domUtils.findParentByTagName(range.startContainer, "li", true); + _$jscoverage['plugins/list.js'][491]++; + if ((li && domUtils.isEmptyBlock(li))) { + _$jscoverage['plugins/list.js'][493]++; + pre = li.previousSibling; + _$jscoverage['plugins/list.js'][494]++; + next = li.nextSibling; + _$jscoverage['plugins/list.js'][495]++; + p = me.document.createElement("p"); + _$jscoverage['plugins/list.js'][497]++; + domUtils.fillNode(me.document, p); + _$jscoverage['plugins/list.js'][498]++; + parentList = li.parentNode; + _$jscoverage['plugins/list.js'][499]++; + if ((pre && next)) { + _$jscoverage['plugins/list.js'][500]++; + range.setStart(next, 0).collapse(true).select(true); + _$jscoverage['plugins/list.js'][501]++; + domUtils.remove(li); + } + else { + _$jscoverage['plugins/list.js'][504]++; + if ((((! pre) && (! next)) || (! pre))) { + _$jscoverage['plugins/list.js'][506]++; + parentList.parentNode.insertBefore(p, parentList); + } + else { + _$jscoverage['plugins/list.js'][510]++; + li.parentNode.parentNode.insertBefore(p, parentList.nextSibling); + } + _$jscoverage['plugins/list.js'][512]++; + domUtils.remove(li); + _$jscoverage['plugins/list.js'][513]++; + if ((! parentList.firstChild)) { + _$jscoverage['plugins/list.js'][514]++; + domUtils.remove(parentList); + } + _$jscoverage['plugins/list.js'][516]++; + range.setStart(p, 0).setCursor(); + } + _$jscoverage['plugins/list.js'][520]++; + preventAndSave(); + _$jscoverage['plugins/list.js'][521]++; + return; + } + } + else { + _$jscoverage['plugins/list.js'][525]++; + var tmpRange = range.cloneRange(), bk = tmpRange.collapse(false).createBookmark(); + _$jscoverage['plugins/list.js'][528]++; + range.deleteContents(); + _$jscoverage['plugins/list.js'][529]++; + tmpRange.moveToBookmark(bk); + _$jscoverage['plugins/list.js'][530]++; + var li = domUtils.findParentByTagName(tmpRange.startContainer, "li", true); + _$jscoverage['plugins/list.js'][532]++; + clearEmptySibling(li); + _$jscoverage['plugins/list.js'][533]++; + tmpRange.select(); + _$jscoverage['plugins/list.js'][534]++; + preventAndSave(); + _$jscoverage['plugins/list.js'][535]++; + return; + } + } + _$jscoverage['plugins/list.js'][540]++; + li = domUtils.findParentByTagName(range.startContainer, "li", true); + _$jscoverage['plugins/list.js'][542]++; + if (li) { + _$jscoverage['plugins/list.js'][543]++; + if (domUtils.isEmptyBlock(li)) { + _$jscoverage['plugins/list.js'][544]++; + bk = range.createBookmark(); + _$jscoverage['plugins/list.js'][545]++; + var parentList = li.parentNode; + _$jscoverage['plugins/list.js'][546]++; + if ((li !== parentList.lastChild)) { + _$jscoverage['plugins/list.js'][547]++; + domUtils.breakParent(li, parentList); + _$jscoverage['plugins/list.js'][548]++; + clearEmptySibling(li); + } + else { + _$jscoverage['plugins/list.js'][551]++; + parentList.parentNode.insertBefore(li, parentList.nextSibling); + _$jscoverage['plugins/list.js'][552]++; + if (domUtils.isEmptyNode(parentList)) { + _$jscoverage['plugins/list.js'][553]++; + domUtils.remove(parentList); + } + } + _$jscoverage['plugins/list.js'][557]++; + if ((! dtd.$list[li.parentNode.tagName])) { + _$jscoverage['plugins/list.js'][559]++; + if ((! domUtils.isBlockElm(li.firstChild))) { + _$jscoverage['plugins/list.js'][560]++; + p = me.document.createElement("p"); + _$jscoverage['plugins/list.js'][561]++; + li.parentNode.insertBefore(p, li); + _$jscoverage['plugins/list.js'][562]++; + while (li.firstChild) { + _$jscoverage['plugins/list.js'][563]++; + p.appendChild(li.firstChild); +} + _$jscoverage['plugins/list.js'][565]++; + domUtils.remove(li); + } + else { + _$jscoverage['plugins/list.js'][567]++; + domUtils.remove(li, true); + } + } + _$jscoverage['plugins/list.js'][570]++; + range.moveToBookmark(bk).select(); + } + else { + _$jscoverage['plugins/list.js'][574]++; + var first = li.firstChild; + _$jscoverage['plugins/list.js'][575]++; + if (((! first) || (! domUtils.isBlockElm(first)))) { + _$jscoverage['plugins/list.js'][576]++; + var p = me.document.createElement("p"); + _$jscoverage['plugins/list.js'][578]++; + ((! li.firstChild) && domUtils.fillNode(me.document, p)); + _$jscoverage['plugins/list.js'][579]++; + while (li.firstChild) { + _$jscoverage['plugins/list.js'][581]++; + p.appendChild(li.firstChild); +} + _$jscoverage['plugins/list.js'][583]++; + li.appendChild(p); + _$jscoverage['plugins/list.js'][584]++; + first = p; + } + _$jscoverage['plugins/list.js'][587]++; + var span = me.document.createElement("span"); + _$jscoverage['plugins/list.js'][589]++; + range.insertNode(span); + _$jscoverage['plugins/list.js'][590]++; + domUtils.breakParent(span, li); + _$jscoverage['plugins/list.js'][592]++; + var nextLi = span.nextSibling; + _$jscoverage['plugins/list.js'][593]++; + first = nextLi.firstChild; + _$jscoverage['plugins/list.js'][595]++; + if ((! first)) { + _$jscoverage['plugins/list.js'][596]++; + p = me.document.createElement("p"); + _$jscoverage['plugins/list.js'][598]++; + domUtils.fillNode(me.document, p); + _$jscoverage['plugins/list.js'][599]++; + nextLi.appendChild(p); + _$jscoverage['plugins/list.js'][600]++; + first = p; + } + _$jscoverage['plugins/list.js'][602]++; + if (domUtils.isEmptyNode(first)) { + _$jscoverage['plugins/list.js'][603]++; + first.innerHTML = ""; + _$jscoverage['plugins/list.js'][604]++; + domUtils.fillNode(me.document, first); + } + _$jscoverage['plugins/list.js'][607]++; + range.setStart(first, 0).collapse(true).shrinkBoundary().select(); + _$jscoverage['plugins/list.js'][608]++; + domUtils.remove(span); + _$jscoverage['plugins/list.js'][609]++; + var pre = nextLi.previousSibling; + _$jscoverage['plugins/list.js'][610]++; + if ((pre && domUtils.isEmptyBlock(pre))) { + _$jscoverage['plugins/list.js'][611]++; + pre.innerHTML = "

    "; + _$jscoverage['plugins/list.js'][612]++; + domUtils.fillNode(me.document, pre.firstChild); + } + } + _$jscoverage['plugins/list.js'][617]++; + preventAndSave(); + } + } + } + _$jscoverage['plugins/list.js'][625]++; + if ((keyCode == 8)) { + _$jscoverage['plugins/list.js'][627]++; + range = me.selection.getRange(); + _$jscoverage['plugins/list.js'][628]++; + if ((range.collapsed && domUtils.isStartInblock(range))) { + _$jscoverage['plugins/list.js'][629]++; + tmpRange = range.cloneRange().trimBoundary(); + _$jscoverage['plugins/list.js'][630]++; + li = domUtils.findParentByTagName(range.startContainer, "li", true); + _$jscoverage['plugins/list.js'][632]++; + if ((li && domUtils.isStartInblock(tmpRange))) { + _$jscoverage['plugins/list.js'][633]++; + start = domUtils.findParentByTagName(range.startContainer, "p", true); + _$jscoverage['plugins/list.js'][634]++; + if ((start && (start !== li.firstChild))) { + _$jscoverage['plugins/list.js'][635]++; + var parentList = domUtils.findParentByTagName(start, ["ol", "ul"]); + _$jscoverage['plugins/list.js'][636]++; + domUtils.breakParent(start, parentList); + _$jscoverage['plugins/list.js'][637]++; + clearEmptySibling(start); + _$jscoverage['plugins/list.js'][638]++; + me.fireEvent("contentchange"); + _$jscoverage['plugins/list.js'][639]++; + range.setStart(start, 0).setCursor(false, true); + _$jscoverage['plugins/list.js'][640]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/list.js'][641]++; + domUtils.preventDefault(evt); + _$jscoverage['plugins/list.js'][642]++; + return; + } + _$jscoverage['plugins/list.js'][645]++; + if ((li && (pre = li.previousSibling))) { + _$jscoverage['plugins/list.js'][646]++; + if (((keyCode == 46) && li.childNodes.length)) { + _$jscoverage['plugins/list.js'][647]++; + return; + } + _$jscoverage['plugins/list.js'][650]++; + if (dtd.$list[pre.tagName]) { + _$jscoverage['plugins/list.js'][651]++; + pre = pre.lastChild; + } + _$jscoverage['plugins/list.js'][653]++; + (me.undoManger && me.undoManger.save()); + _$jscoverage['plugins/list.js'][654]++; + first = li.firstChild; + _$jscoverage['plugins/list.js'][655]++; + if (domUtils.isBlockElm(first)) { + _$jscoverage['plugins/list.js'][656]++; + if (domUtils.isEmptyNode(first)) { + _$jscoverage['plugins/list.js'][658]++; + pre.appendChild(first); + _$jscoverage['plugins/list.js'][659]++; + range.setStart(first, 0).setCursor(false, true); + _$jscoverage['plugins/list.js'][661]++; + while (li.firstChild) { + _$jscoverage['plugins/list.js'][662]++; + pre.appendChild(li.firstChild); +} + } + else { + _$jscoverage['plugins/list.js'][666]++; + span = me.document.createElement("span"); + _$jscoverage['plugins/list.js'][667]++; + range.insertNode(span); + _$jscoverage['plugins/list.js'][669]++; + if (domUtils.isEmptyBlock(pre)) { + _$jscoverage['plugins/list.js'][670]++; + pre.innerHTML = ""; + } + _$jscoverage['plugins/list.js'][672]++; + domUtils.moveChild(li, pre); + _$jscoverage['plugins/list.js'][673]++; + range.setStartBefore(span).collapse(true).select(true); + _$jscoverage['plugins/list.js'][675]++; + domUtils.remove(span); + } + } + else { + _$jscoverage['plugins/list.js'][679]++; + if (domUtils.isEmptyNode(li)) { + _$jscoverage['plugins/list.js'][680]++; + var p = me.document.createElement("p"); + _$jscoverage['plugins/list.js'][681]++; + pre.appendChild(p); + _$jscoverage['plugins/list.js'][682]++; + range.setStart(p, 0).setCursor(); + } + else { + _$jscoverage['plugins/list.js'][685]++; + range.setEnd(pre, pre.childNodes.length).collapse().select(true); + _$jscoverage['plugins/list.js'][686]++; + while (li.firstChild) { + _$jscoverage['plugins/list.js'][687]++; + pre.appendChild(li.firstChild); +} + } + } + _$jscoverage['plugins/list.js'][691]++; + domUtils.remove(li); + _$jscoverage['plugins/list.js'][692]++; + me.fireEvent("contentchange"); + _$jscoverage['plugins/list.js'][693]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/list.js'][694]++; + domUtils.preventDefault(evt); + _$jscoverage['plugins/list.js'][695]++; + return; + } + _$jscoverage['plugins/list.js'][700]++; + if ((li && (! li.previousSibling))) { + _$jscoverage['plugins/list.js'][701]++; + var parentList = li.parentNode; + _$jscoverage['plugins/list.js'][702]++; + var bk = range.createBookmark(); + _$jscoverage['plugins/list.js'][703]++; + if (domUtils.isTagNode(parentList.parentNode, "ol ul")) { + _$jscoverage['plugins/list.js'][704]++; + parentList.parentNode.insertBefore(li, parentList); + _$jscoverage['plugins/list.js'][705]++; + if (domUtils.isEmptyNode(parentList)) { + _$jscoverage['plugins/list.js'][706]++; + domUtils.remove(parentList); + } + } + else { + _$jscoverage['plugins/list.js'][710]++; + while (li.firstChild) { + _$jscoverage['plugins/list.js'][711]++; + parentList.parentNode.insertBefore(li.firstChild, parentList); +} + _$jscoverage['plugins/list.js'][714]++; + domUtils.remove(li); + _$jscoverage['plugins/list.js'][715]++; + if (domUtils.isEmptyNode(parentList)) { + _$jscoverage['plugins/list.js'][716]++; + domUtils.remove(parentList); + } + } + _$jscoverage['plugins/list.js'][720]++; + range.moveToBookmark(bk).setCursor(false, true); + _$jscoverage['plugins/list.js'][721]++; + me.fireEvent("contentchange"); + _$jscoverage['plugins/list.js'][722]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/list.js'][723]++; + domUtils.preventDefault(evt); + _$jscoverage['plugins/list.js'][724]++; + return; + } + } + } + } +})); + _$jscoverage['plugins/list.js'][737]++; + me.addListener("keyup", (function (type, evt) { + _$jscoverage['plugins/list.js'][738]++; + var keyCode = (evt.keyCode || evt.which); + _$jscoverage['plugins/list.js'][739]++; + if ((keyCode == 8)) { + _$jscoverage['plugins/list.js'][740]++; + var rng = me.selection.getRange(), list; + _$jscoverage['plugins/list.js'][741]++; + if ((list = domUtils.findParentByTagName(rng.startContainer, ["ol", "ul"], true))) { + _$jscoverage['plugins/list.js'][742]++; + adjustList(list, list.tagName.toLowerCase(), (getStyle(list) || domUtils.getComputedStyle(list, "list-style-type")), true); + } + } +})); + _$jscoverage['plugins/list.js'][747]++; + me.addListener("tabkeydown", (function () { + _$jscoverage['plugins/list.js'][749]++; + var range = me.selection.getRange(); + _$jscoverage['plugins/list.js'][752]++; + function checkLevel(li) { + _$jscoverage['plugins/list.js'][753]++; + if ((me.options.maxListLevel != -1)) { + _$jscoverage['plugins/list.js'][754]++; + var level = li.parentNode, levelNum = 0; + _$jscoverage['plugins/list.js'][755]++; + while (/[ou]l/i.test(level.tagName)) { + _$jscoverage['plugins/list.js'][756]++; + (levelNum++); + _$jscoverage['plugins/list.js'][757]++; + level = level.parentNode; +} + _$jscoverage['plugins/list.js'][759]++; + if ((levelNum >= me.options.maxListLevel)) { + _$jscoverage['plugins/list.js'][760]++; + return true; + } + } +} + _$jscoverage['plugins/list.js'][766]++; + var li = domUtils.findParentByTagName(range.startContainer, "li", true); + _$jscoverage['plugins/list.js'][767]++; + if (li) { + _$jscoverage['plugins/list.js'][769]++; + var bk; + _$jscoverage['plugins/list.js'][770]++; + if (range.collapsed) { + _$jscoverage['plugins/list.js'][771]++; + if (checkLevel(li)) { + _$jscoverage['plugins/list.js'][772]++; + return true; + } + _$jscoverage['plugins/list.js'][773]++; + var parentLi = li.parentNode, list = me.document.createElement(parentLi.tagName), index = utils.indexOf(listStyle[list.tagName], (getStyle(parentLi) || domUtils.getComputedStyle(parentLi, "list-style-type"))); + _$jscoverage['plugins/list.js'][776]++; + index = (((index + 1) == listStyle[list.tagName].length)? 0: (index + 1)); + _$jscoverage['plugins/list.js'][777]++; + var currentStyle = listStyle[list.tagName][index]; + _$jscoverage['plugins/list.js'][778]++; + setListStyle(list, currentStyle); + _$jscoverage['plugins/list.js'][779]++; + if (domUtils.isStartInblock(range)) { + _$jscoverage['plugins/list.js'][780]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/list.js'][781]++; + bk = range.createBookmark(); + _$jscoverage['plugins/list.js'][782]++; + parentLi.insertBefore(list, li); + _$jscoverage['plugins/list.js'][783]++; + list.appendChild(li); + _$jscoverage['plugins/list.js'][784]++; + adjustList(list, list.tagName.toLowerCase(), currentStyle); + _$jscoverage['plugins/list.js'][785]++; + me.fireEvent("contentchange"); + _$jscoverage['plugins/list.js'][786]++; + range.moveToBookmark(bk).select(true); + _$jscoverage['plugins/list.js'][787]++; + return true; + } + } + else { + _$jscoverage['plugins/list.js'][790]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/list.js'][791]++; + bk = range.createBookmark(); + _$jscoverage['plugins/list.js'][792]++; + for (var i = 0, closeList, parents = domUtils.findParents(li), ci; (ci = parents[(i++)]);) { + _$jscoverage['plugins/list.js'][793]++; + if (domUtils.isTagNode(ci, "ol ul")) { + _$jscoverage['plugins/list.js'][794]++; + closeList = ci; + _$jscoverage['plugins/list.js'][795]++; + break; + } +} + _$jscoverage['plugins/list.js'][798]++; + var current = li; + _$jscoverage['plugins/list.js'][799]++; + if (bk.end) { + _$jscoverage['plugins/list.js'][800]++; + while ((current && (! (domUtils.getPosition(current, bk.end) & domUtils.POSITION_FOLLOWING)))) { + _$jscoverage['plugins/list.js'][801]++; + if (checkLevel(current)) { + _$jscoverage['plugins/list.js'][802]++; + current = domUtils.getNextDomNode(current, false, null, (function (node) { + _$jscoverage['plugins/list.js'][802]++; + return (node !== closeList); +})); + _$jscoverage['plugins/list.js'][803]++; + continue; + } + _$jscoverage['plugins/list.js'][805]++; + var parentLi = current.parentNode, list = me.document.createElement(parentLi.tagName), index = utils.indexOf(listStyle[list.tagName], (getStyle(parentLi) || domUtils.getComputedStyle(parentLi, "list-style-type"))); + _$jscoverage['plugins/list.js'][808]++; + var currentIndex = (((index + 1) == listStyle[list.tagName].length)? 0: (index + 1)); + _$jscoverage['plugins/list.js'][809]++; + var currentStyle = listStyle[list.tagName][currentIndex]; + _$jscoverage['plugins/list.js'][810]++; + setListStyle(list, currentStyle); + _$jscoverage['plugins/list.js'][811]++; + parentLi.insertBefore(list, current); + _$jscoverage['plugins/list.js'][812]++; + while ((current && (! (domUtils.getPosition(current, bk.end) & domUtils.POSITION_FOLLOWING)))) { + _$jscoverage['plugins/list.js'][813]++; + li = current.nextSibling; + _$jscoverage['plugins/list.js'][814]++; + list.appendChild(current); + _$jscoverage['plugins/list.js'][815]++; + if (((! li) || domUtils.isTagNode(li, "ol ul"))) { + _$jscoverage['plugins/list.js'][816]++; + if (li) { + _$jscoverage['plugins/list.js'][817]++; + while ((li = li.firstChild)) { + _$jscoverage['plugins/list.js'][818]++; + if ((li.tagName == "LI")) { + _$jscoverage['plugins/list.js'][819]++; + break; + } +} + } + else { + _$jscoverage['plugins/list.js'][823]++; + li = domUtils.getNextDomNode(current, false, null, (function (node) { + _$jscoverage['plugins/list.js'][823]++; + return (node !== closeList); +})); + } + _$jscoverage['plugins/list.js'][825]++; + break; + } + _$jscoverage['plugins/list.js'][827]++; + current = li; +} + _$jscoverage['plugins/list.js'][829]++; + adjustList(list, list.tagName.toLowerCase(), currentStyle); + _$jscoverage['plugins/list.js'][830]++; + current = li; +} + } + _$jscoverage['plugins/list.js'][833]++; + me.fireEvent("contentchange"); + _$jscoverage['plugins/list.js'][834]++; + range.moveToBookmark(bk).select(); + _$jscoverage['plugins/list.js'][835]++; + return true; + } + } +})); + _$jscoverage['plugins/list.js'][840]++; + function getLi(start) { + _$jscoverage['plugins/list.js'][841]++; + while ((start && (! domUtils.isBody(start)))) { + _$jscoverage['plugins/list.js'][842]++; + if ((start.nodeName == "TABLE")) { + _$jscoverage['plugins/list.js'][843]++; + return null; + } + _$jscoverage['plugins/list.js'][845]++; + if ((start.nodeName == "LI")) { + _$jscoverage['plugins/list.js'][846]++; + return start; + } + _$jscoverage['plugins/list.js'][848]++; + start = start.parentNode; +} +} + _$jscoverage['plugins/list.js'][921]++; + me.commands.insertorderedlist = (me.commands.insertunorderedlist = {execCommand: (function (command, style) { + _$jscoverage['plugins/list.js'][925]++; + if ((! style)) { + _$jscoverage['plugins/list.js'][926]++; + style = ((command.toLowerCase() == "insertorderedlist")? "decimal": "disc"); + } + _$jscoverage['plugins/list.js'][928]++; + var me = this, range = this.selection.getRange(), filterFn = (function (node) { + _$jscoverage['plugins/list.js'][931]++; + return ((node.nodeType == 1)? (node.tagName.toLowerCase() != "br"): (! domUtils.isWhitespace(node))); +}), tag = ((command.toLowerCase() == "insertorderedlist")? "ol": "ul"), frag = me.document.createDocumentFragment(); + _$jscoverage['plugins/list.js'][937]++; + range.adjustmentBoundary().shrinkBoundary(); + _$jscoverage['plugins/list.js'][938]++; + var bko = range.createBookmark(true), start = getLi(me.document.getElementById(bko.start)), modifyStart = 0, end = getLi(me.document.getElementById(bko.end)), modifyEnd = 0, startParent, endParent, list, tmp; + _$jscoverage['plugins/list.js'][946]++; + if ((start || end)) { + _$jscoverage['plugins/list.js'][947]++; + (start && (startParent = start.parentNode)); + _$jscoverage['plugins/list.js'][948]++; + if ((! bko.end)) { + _$jscoverage['plugins/list.js'][949]++; + end = start; + } + _$jscoverage['plugins/list.js'][951]++; + (end && (endParent = end.parentNode)); + _$jscoverage['plugins/list.js'][953]++; + if ((startParent === endParent)) { + _$jscoverage['plugins/list.js'][954]++; + while ((start !== end)) { + _$jscoverage['plugins/list.js'][955]++; + tmp = start; + _$jscoverage['plugins/list.js'][956]++; + start = start.nextSibling; + _$jscoverage['plugins/list.js'][957]++; + if ((! domUtils.isBlockElm(tmp.firstChild))) { + _$jscoverage['plugins/list.js'][958]++; + var p = me.document.createElement("p"); + _$jscoverage['plugins/list.js'][959]++; + while (tmp.firstChild) { + _$jscoverage['plugins/list.js'][960]++; + p.appendChild(tmp.firstChild); +} + _$jscoverage['plugins/list.js'][962]++; + tmp.appendChild(p); + } + _$jscoverage['plugins/list.js'][964]++; + frag.appendChild(tmp); +} + _$jscoverage['plugins/list.js'][966]++; + tmp = me.document.createElement("span"); + _$jscoverage['plugins/list.js'][967]++; + startParent.insertBefore(tmp, end); + _$jscoverage['plugins/list.js'][968]++; + if ((! domUtils.isBlockElm(end.firstChild))) { + _$jscoverage['plugins/list.js'][969]++; + p = me.document.createElement("p"); + _$jscoverage['plugins/list.js'][970]++; + while (end.firstChild) { + _$jscoverage['plugins/list.js'][971]++; + p.appendChild(end.firstChild); +} + _$jscoverage['plugins/list.js'][973]++; + end.appendChild(p); + } + _$jscoverage['plugins/list.js'][975]++; + frag.appendChild(end); + _$jscoverage['plugins/list.js'][976]++; + domUtils.breakParent(tmp, startParent); + _$jscoverage['plugins/list.js'][977]++; + if (domUtils.isEmptyNode(tmp.previousSibling)) { + _$jscoverage['plugins/list.js'][978]++; + domUtils.remove(tmp.previousSibling); + } + _$jscoverage['plugins/list.js'][980]++; + if (domUtils.isEmptyNode(tmp.nextSibling)) { + _$jscoverage['plugins/list.js'][981]++; + domUtils.remove(tmp.nextSibling); + } + _$jscoverage['plugins/list.js'][983]++; + var nodeStyle = (getStyle(startParent) || domUtils.getComputedStyle(startParent, "list-style-type") || ((command.toLowerCase() == "insertorderedlist")? "decimal": "disc")); + _$jscoverage['plugins/list.js'][984]++; + if (((startParent.tagName.toLowerCase() == tag) && (nodeStyle == style))) { + _$jscoverage['plugins/list.js'][985]++; + for (var i = 0, ci, tmpFrag = me.document.createDocumentFragment(); (ci = frag.childNodes[(i++)]);) { + _$jscoverage['plugins/list.js'][986]++; + if (domUtils.isTagNode(ci, "ol ul")) { + _$jscoverage['plugins/list.js'][987]++; + utils.each(domUtils.getElementsByTagName(ci, "li"), (function (li) { + _$jscoverage['plugins/list.js'][988]++; + while (li.firstChild) { + _$jscoverage['plugins/list.js'][989]++; + tmpFrag.appendChild(li.firstChild); +} +})); + } + else { + _$jscoverage['plugins/list.js'][994]++; + while (ci.firstChild) { + _$jscoverage['plugins/list.js'][995]++; + tmpFrag.appendChild(ci.firstChild); +} + } +} + _$jscoverage['plugins/list.js'][1000]++; + tmp.parentNode.insertBefore(tmpFrag, tmp); + } + else { + _$jscoverage['plugins/list.js'][1002]++; + list = me.document.createElement(tag); + _$jscoverage['plugins/list.js'][1003]++; + setListStyle(list, style); + _$jscoverage['plugins/list.js'][1004]++; + list.appendChild(frag); + _$jscoverage['plugins/list.js'][1005]++; + tmp.parentNode.insertBefore(list, tmp); + } + _$jscoverage['plugins/list.js'][1008]++; + domUtils.remove(tmp); + _$jscoverage['plugins/list.js'][1009]++; + (list && adjustList(list, tag, style)); + _$jscoverage['plugins/list.js'][1010]++; + range.moveToBookmark(bko).select(); + _$jscoverage['plugins/list.js'][1011]++; + return; + } + _$jscoverage['plugins/list.js'][1014]++; + if (start) { + _$jscoverage['plugins/list.js'][1015]++; + while (start) { + _$jscoverage['plugins/list.js'][1016]++; + tmp = start.nextSibling; + _$jscoverage['plugins/list.js'][1017]++; + if (domUtils.isTagNode(start, "ol ul")) { + _$jscoverage['plugins/list.js'][1018]++; + frag.appendChild(start); + } + else { + _$jscoverage['plugins/list.js'][1020]++; + var tmpfrag = me.document.createDocumentFragment(), hasBlock = 0; + _$jscoverage['plugins/list.js'][1022]++; + while (start.firstChild) { + _$jscoverage['plugins/list.js'][1023]++; + if (domUtils.isBlockElm(start.firstChild)) { + _$jscoverage['plugins/list.js'][1024]++; + hasBlock = 1; + } + _$jscoverage['plugins/list.js'][1026]++; + tmpfrag.appendChild(start.firstChild); +} + _$jscoverage['plugins/list.js'][1028]++; + if ((! hasBlock)) { + _$jscoverage['plugins/list.js'][1029]++; + var tmpP = me.document.createElement("p"); + _$jscoverage['plugins/list.js'][1030]++; + tmpP.appendChild(tmpfrag); + _$jscoverage['plugins/list.js'][1031]++; + frag.appendChild(tmpP); + } + else { + _$jscoverage['plugins/list.js'][1033]++; + frag.appendChild(tmpfrag); + } + _$jscoverage['plugins/list.js'][1035]++; + domUtils.remove(start); + } + _$jscoverage['plugins/list.js'][1038]++; + start = tmp; +} + _$jscoverage['plugins/list.js'][1040]++; + startParent.parentNode.insertBefore(frag, startParent.nextSibling); + _$jscoverage['plugins/list.js'][1041]++; + if (domUtils.isEmptyNode(startParent)) { + _$jscoverage['plugins/list.js'][1042]++; + range.setStartBefore(startParent); + _$jscoverage['plugins/list.js'][1043]++; + domUtils.remove(startParent); + } + else { + _$jscoverage['plugins/list.js'][1045]++; + range.setStartAfter(startParent); + } + _$jscoverage['plugins/list.js'][1047]++; + modifyStart = 1; + } + _$jscoverage['plugins/list.js'][1050]++; + if ((end && domUtils.inDoc(endParent, me.document))) { + _$jscoverage['plugins/list.js'][1052]++; + start = endParent.firstChild; + _$jscoverage['plugins/list.js'][1053]++; + while ((start && (start !== end))) { + _$jscoverage['plugins/list.js'][1054]++; + tmp = start.nextSibling; + _$jscoverage['plugins/list.js'][1055]++; + if (domUtils.isTagNode(start, "ol ul")) { + _$jscoverage['plugins/list.js'][1056]++; + frag.appendChild(start); + } + else { + _$jscoverage['plugins/list.js'][1058]++; + tmpfrag = me.document.createDocumentFragment(); + _$jscoverage['plugins/list.js'][1059]++; + hasBlock = 0; + _$jscoverage['plugins/list.js'][1060]++; + while (start.firstChild) { + _$jscoverage['plugins/list.js'][1061]++; + if (domUtils.isBlockElm(start.firstChild)) { + _$jscoverage['plugins/list.js'][1062]++; + hasBlock = 1; + } + _$jscoverage['plugins/list.js'][1064]++; + tmpfrag.appendChild(start.firstChild); +} + _$jscoverage['plugins/list.js'][1066]++; + if ((! hasBlock)) { + _$jscoverage['plugins/list.js'][1067]++; + tmpP = me.document.createElement("p"); + _$jscoverage['plugins/list.js'][1068]++; + tmpP.appendChild(tmpfrag); + _$jscoverage['plugins/list.js'][1069]++; + frag.appendChild(tmpP); + } + else { + _$jscoverage['plugins/list.js'][1071]++; + frag.appendChild(tmpfrag); + } + _$jscoverage['plugins/list.js'][1073]++; + domUtils.remove(start); + } + _$jscoverage['plugins/list.js'][1075]++; + start = tmp; +} + _$jscoverage['plugins/list.js'][1077]++; + var tmpDiv = domUtils.createElement(me.document, "div", {"tmpDiv": 1}); + _$jscoverage['plugins/list.js'][1080]++; + domUtils.moveChild(end, tmpDiv); + _$jscoverage['plugins/list.js'][1082]++; + frag.appendChild(tmpDiv); + _$jscoverage['plugins/list.js'][1083]++; + domUtils.remove(end); + _$jscoverage['plugins/list.js'][1084]++; + endParent.parentNode.insertBefore(frag, endParent); + _$jscoverage['plugins/list.js'][1085]++; + range.setEndBefore(endParent); + _$jscoverage['plugins/list.js'][1086]++; + if (domUtils.isEmptyNode(endParent)) { + _$jscoverage['plugins/list.js'][1087]++; + domUtils.remove(endParent); + } + _$jscoverage['plugins/list.js'][1090]++; + modifyEnd = 1; + } + } + _$jscoverage['plugins/list.js'][1096]++; + if ((! modifyStart)) { + _$jscoverage['plugins/list.js'][1097]++; + range.setStartBefore(me.document.getElementById(bko.start)); + } + _$jscoverage['plugins/list.js'][1099]++; + if ((bko.end && (! modifyEnd))) { + _$jscoverage['plugins/list.js'][1100]++; + range.setEndAfter(me.document.getElementById(bko.end)); + } + _$jscoverage['plugins/list.js'][1102]++; + range.enlarge(true, (function (node) { + _$jscoverage['plugins/list.js'][1103]++; + return notExchange[node.tagName]; +})); + _$jscoverage['plugins/list.js'][1106]++; + frag = me.document.createDocumentFragment(); + _$jscoverage['plugins/list.js'][1108]++; + var bk = range.createBookmark(), current = domUtils.getNextDomNode(bk.start, false, filterFn), tmpRange = range.cloneRange(), tmpNode, block = domUtils.isBlockElm; + _$jscoverage['plugins/list.js'][1114]++; + while ((current && (current !== bk.end) && (domUtils.getPosition(current, bk.end) & domUtils.POSITION_PRECEDING))) { + _$jscoverage['plugins/list.js'][1116]++; + if (((current.nodeType == 3) || dtd.li[current.tagName])) { + _$jscoverage['plugins/list.js'][1117]++; + if (((current.nodeType == 1) && dtd.$list[current.tagName])) { + _$jscoverage['plugins/list.js'][1118]++; + while (current.firstChild) { + _$jscoverage['plugins/list.js'][1119]++; + frag.appendChild(current.firstChild); +} + _$jscoverage['plugins/list.js'][1121]++; + tmpNode = domUtils.getNextDomNode(current, false, filterFn); + _$jscoverage['plugins/list.js'][1122]++; + domUtils.remove(current); + _$jscoverage['plugins/list.js'][1123]++; + current = tmpNode; + _$jscoverage['plugins/list.js'][1124]++; + continue; + } + _$jscoverage['plugins/list.js'][1127]++; + tmpNode = current; + _$jscoverage['plugins/list.js'][1128]++; + tmpRange.setStartBefore(current); + _$jscoverage['plugins/list.js'][1130]++; + while ((current && (current !== bk.end) && ((! block(current)) || domUtils.isBookmarkNode(current)))) { + _$jscoverage['plugins/list.js'][1131]++; + tmpNode = current; + _$jscoverage['plugins/list.js'][1132]++; + current = domUtils.getNextDomNode(current, false, null, (function (node) { + _$jscoverage['plugins/list.js'][1133]++; + return (! notExchange[node.tagName]); +})); +} + _$jscoverage['plugins/list.js'][1137]++; + if ((current && block(current))) { + _$jscoverage['plugins/list.js'][1138]++; + tmp = domUtils.getNextDomNode(tmpNode, false, filterFn); + _$jscoverage['plugins/list.js'][1139]++; + if ((tmp && domUtils.isBookmarkNode(tmp))) { + _$jscoverage['plugins/list.js'][1140]++; + current = domUtils.getNextDomNode(tmp, false, filterFn); + _$jscoverage['plugins/list.js'][1141]++; + tmpNode = tmp; + } + } + _$jscoverage['plugins/list.js'][1144]++; + tmpRange.setEndAfter(tmpNode); + _$jscoverage['plugins/list.js'][1146]++; + current = domUtils.getNextDomNode(tmpNode, false, filterFn); + _$jscoverage['plugins/list.js'][1148]++; + var li = range.document.createElement("li"); + _$jscoverage['plugins/list.js'][1150]++; + li.appendChild(tmpRange.extractContents()); + _$jscoverage['plugins/list.js'][1151]++; + if (domUtils.isEmptyNode(li)) { + _$jscoverage['plugins/list.js'][1152]++; + var tmpNode = range.document.createElement("p"); + _$jscoverage['plugins/list.js'][1153]++; + while (li.firstChild) { + _$jscoverage['plugins/list.js'][1154]++; + tmpNode.appendChild(li.firstChild); +} + _$jscoverage['plugins/list.js'][1156]++; + li.appendChild(tmpNode); + } + _$jscoverage['plugins/list.js'][1158]++; + frag.appendChild(li); + } + else { + _$jscoverage['plugins/list.js'][1160]++; + current = domUtils.getNextDomNode(current, true, filterFn); + } +} + _$jscoverage['plugins/list.js'][1163]++; + range.moveToBookmark(bk).collapse(true); + _$jscoverage['plugins/list.js'][1164]++; + list = me.document.createElement(tag); + _$jscoverage['plugins/list.js'][1165]++; + setListStyle(list, style); + _$jscoverage['plugins/list.js'][1166]++; + list.appendChild(frag); + _$jscoverage['plugins/list.js'][1167]++; + range.insertNode(list); + _$jscoverage['plugins/list.js'][1169]++; + adjustList(list, tag, style); + _$jscoverage['plugins/list.js'][1171]++; + for (var i = 0, ci = ci, tmpDivs = domUtils.getElementsByTagName(list, "div"); (ci = tmpDivs[(i++)]);) { + _$jscoverage['plugins/list.js'][1172]++; + if (ci.getAttribute("tmpDiv")) { + _$jscoverage['plugins/list.js'][1173]++; + domUtils.remove(ci, true); + } +} + _$jscoverage['plugins/list.js'][1176]++; + range.moveToBookmark(bko).select(); +}), queryCommandState: (function (command) { + _$jscoverage['plugins/list.js'][1180]++; + var tag = ((command.toLowerCase() == "insertorderedlist")? "ol": "ul"); + _$jscoverage['plugins/list.js'][1181]++; + var path = this.selection.getStartElementPath(); + _$jscoverage['plugins/list.js'][1182]++; + for (var i = 0, ci; (ci = path[(i++)]);) { + _$jscoverage['plugins/list.js'][1183]++; + if ((ci.nodeName == "TABLE")) { + _$jscoverage['plugins/list.js'][1184]++; + return 0; + } + _$jscoverage['plugins/list.js'][1186]++; + if ((tag == ci.nodeName.toLowerCase())) { + _$jscoverage['plugins/list.js'][1187]++; + return 1; + } + _$jscoverage['plugins/list.js'][1188]++; + ; +} + _$jscoverage['plugins/list.js'][1190]++; + return 0; +}), queryCommandValue: (function (command) { + _$jscoverage['plugins/list.js'][1194]++; + var tag = ((command.toLowerCase() == "insertorderedlist")? "ol": "ul"); + _$jscoverage['plugins/list.js'][1195]++; + var path = this.selection.getStartElementPath(), node; + _$jscoverage['plugins/list.js'][1197]++; + for (var i = 0, ci; (ci = path[(i++)]);) { + _$jscoverage['plugins/list.js'][1198]++; + if ((ci.nodeName == "TABLE")) { + _$jscoverage['plugins/list.js'][1199]++; + node = null; + _$jscoverage['plugins/list.js'][1200]++; + break; + } + _$jscoverage['plugins/list.js'][1202]++; + if ((tag == ci.nodeName.toLowerCase())) { + _$jscoverage['plugins/list.js'][1203]++; + node = ci; + _$jscoverage['plugins/list.js'][1204]++; + break; + } + _$jscoverage['plugins/list.js'][1205]++; + ; +} + _$jscoverage['plugins/list.js'][1207]++; + return (node? (getStyle(node) || domUtils.getComputedStyle(node, "list-style-type")): null); +})}); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/music.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/music.js new file mode 100644 index 000000000..ee7d4efc9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/music.js @@ -0,0 +1,135 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/music.js']) { + _$jscoverage['plugins/music.js'] = []; + _$jscoverage['plugins/music.js'][24] = 0; + _$jscoverage['plugins/music.js'][25] = 0; + _$jscoverage['plugins/music.js'][37] = 0; + _$jscoverage['plugins/music.js'][38] = 0; + _$jscoverage['plugins/music.js'][50] = 0; + _$jscoverage['plugins/music.js'][51] = 0; + _$jscoverage['plugins/music.js'][53] = 0; + _$jscoverage['plugins/music.js'][54] = 0; + _$jscoverage['plugins/music.js'][55] = 0; + _$jscoverage['plugins/music.js'][57] = 0; + _$jscoverage['plugins/music.js'][59] = 0; + _$jscoverage['plugins/music.js'][60] = 0; + _$jscoverage['plugins/music.js'][61] = 0; + _$jscoverage['plugins/music.js'][62] = 0; + _$jscoverage['plugins/music.js'][66] = 0; + _$jscoverage['plugins/music.js'][67] = 0; + _$jscoverage['plugins/music.js'][69] = 0; + _$jscoverage['plugins/music.js'][70] = 0; + _$jscoverage['plugins/music.js'][72] = 0; + _$jscoverage['plugins/music.js'][73] = 0; + _$jscoverage['plugins/music.js'][74] = 0; + _$jscoverage['plugins/music.js'][76] = 0; + _$jscoverage['plugins/music.js'][79] = 0; + _$jscoverage['plugins/music.js'][81] = 0; + _$jscoverage['plugins/music.js'][83] = 0; + _$jscoverage['plugins/music.js'][86] = 0; + _$jscoverage['plugins/music.js'][89] = 0; +} +_$jscoverage['plugins/music.js'].source = ["/**"," * 插入音乐命令"," * @file"," */","","/**"," * 在当前光标处插入音乐"," * @command music"," * @method execCommand"," * @param { KeyValueMap } musicOptions 插入音乐的参数项, 支持的key有: url=>音乐地址;"," * width=>音乐容器宽度;height=>音乐容器高度;align=>音乐文件的对齐方式, 可选值有: left, center, right, none"," * @example"," * ```javascript"," * //editor是编辑器实例"," * //在编辑器里插入一个“植物大战僵尸”的APP"," * editor.execCommand( 'music' , {"," * width: 400,"," * height: 95,"," * align: \"center\","," * url: \"音乐地址\""," * } );"," * ```"," */","UE.plugins['music'] = function () {"," var me = this,"," div;",""," /*"," * 创建插入音乐字符串"," * @param url 音乐地址"," * @param width 音乐宽度"," * @param height 音乐高度"," * @param align 对齐"," * @param toEmbed 是否以flash代替显示"," * @param addParagraph 是否需要添加P标签"," */"," function creatInsertStr(url,width,height,align,toEmbed,addParagraph){"," return !toEmbed ?"," (addParagraph? ('<p '+ (align !=\"none\" ? ( align == \"center\"? ' style=\"text-align:center;\" ':' style=\"float:\"'+ align ) : '') + '>'): '') +"," '<img align=\"'+align+'\" width=\"'+ width +'\" height=\"' + height + '\" _url=\"'+url+'\" class=\"edui-faked-music\"' +"," ' src=\"'+me.options.langPath+me.options.lang+'/images/music.png\" />' +"," (addParagraph?'</p>':'')"," :"," '<embed type=\"application/x-shockwave-flash\" class=\"edui-faked-music\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\"' +"," ' src=\"' + url + '\" width=\"' + width + '\" height=\"' + height + '\" align=\"' + align + '\"' +"," ( align !=\"none\" ? ' style= \"'+ ( align == \"center\"? \"display:block;\":\" float: \"+ align ) + '\"' :'' ) +"," ' wmode=\"transparent\" play=\"true\" loop=\"false\" menu=\"false\" allowscriptaccess=\"never\" allowfullscreen=\"true\" >';"," }",""," function switchImgAndEmbed(img2embed) {"," var tmpdiv,"," nodes = domUtils.getElementsByTagName(me.document, !img2embed ? \"embed\" : \"img\");"," for (var i = 0, node; node = nodes[i++];) {"," if (node.className != \"edui-faked-music\") {"," continue;"," }"," tmpdiv = me.document.createElement(\"div\");"," //先看float在看align,浮动有的是时候是在float上定义的"," var align = domUtils.getComputedStyle(node,'float');"," align = align == 'none' ? (node.getAttribute('align') || '') : align;"," tmpdiv.innerHTML = creatInsertStr(img2embed ? node.getAttribute(\"_url\") : node.getAttribute(\"src\"), node.width, node.height, align, img2embed);"," node.parentNode.replaceChild(tmpdiv.firstChild, node);"," }"," }",""," me.addListener(\"beforegetcontent\", function () {"," switchImgAndEmbed(true);"," });"," me.addListener('aftersetcontent', function () {"," switchImgAndEmbed(false);"," });"," me.addListener('aftergetcontent', function (cmdName) {"," if (cmdName == 'aftergetcontent' && me.queryCommandState('source')) {"," return;"," }"," switchImgAndEmbed(false);"," });",""," me.commands[\"music\"] = {"," execCommand:function (cmd, musicObj) {"," var me = this,"," str = creatInsertStr(musicObj.url, musicObj.width || 400, musicObj.height || 95, \"none\", false, true);"," me.execCommand(\"inserthtml\",str);"," },"," queryCommandState:function () {"," var me = this,"," img = me.selection.getRange().getClosedNode(),"," flag = img && (img.className == \"edui-faked-music\");"," return flag ? 1 : 0;"," }"," };","};"]; +_$jscoverage['plugins/music.js'][24]++; +UE.plugins.music = (function () { + _$jscoverage['plugins/music.js'][25]++; + var me = this, div; + _$jscoverage['plugins/music.js'][37]++; + function creatInsertStr(url, width, height, align, toEmbed, addParagraph) { + _$jscoverage['plugins/music.js'][38]++; + return ((! toEmbed)? ((addParagraph? ("

    "): "") + "" + (addParagraph? "

    ": "")): ("")); +} + _$jscoverage['plugins/music.js'][50]++; + function switchImgAndEmbed(img2embed) { + _$jscoverage['plugins/music.js'][51]++; + var tmpdiv, nodes = domUtils.getElementsByTagName(me.document, ((! img2embed)? "embed": "img")); + _$jscoverage['plugins/music.js'][53]++; + for (var i = 0, node; (node = nodes[(i++)]);) { + _$jscoverage['plugins/music.js'][54]++; + if ((node.className != "edui-faked-music")) { + _$jscoverage['plugins/music.js'][55]++; + continue; + } + _$jscoverage['plugins/music.js'][57]++; + tmpdiv = me.document.createElement("div"); + _$jscoverage['plugins/music.js'][59]++; + var align = domUtils.getComputedStyle(node, "float"); + _$jscoverage['plugins/music.js'][60]++; + align = ((align == "none")? (node.getAttribute("align") || ""): align); + _$jscoverage['plugins/music.js'][61]++; + tmpdiv.innerHTML = creatInsertStr((img2embed? node.getAttribute("_url"): node.getAttribute("src")), node.width, node.height, align, img2embed); + _$jscoverage['plugins/music.js'][62]++; + node.parentNode.replaceChild(tmpdiv.firstChild, node); +} +} + _$jscoverage['plugins/music.js'][66]++; + me.addListener("beforegetcontent", (function () { + _$jscoverage['plugins/music.js'][67]++; + switchImgAndEmbed(true); +})); + _$jscoverage['plugins/music.js'][69]++; + me.addListener("aftersetcontent", (function () { + _$jscoverage['plugins/music.js'][70]++; + switchImgAndEmbed(false); +})); + _$jscoverage['plugins/music.js'][72]++; + me.addListener("aftergetcontent", (function (cmdName) { + _$jscoverage['plugins/music.js'][73]++; + if (((cmdName == "aftergetcontent") && me.queryCommandState("source"))) { + _$jscoverage['plugins/music.js'][74]++; + return; + } + _$jscoverage['plugins/music.js'][76]++; + switchImgAndEmbed(false); +})); + _$jscoverage['plugins/music.js'][79]++; + me.commands.music = {execCommand: (function (cmd, musicObj) { + _$jscoverage['plugins/music.js'][81]++; + var me = this, str = creatInsertStr(musicObj.url, (musicObj.width || 400), (musicObj.height || 95), "none", false, true); + _$jscoverage['plugins/music.js'][83]++; + me.execCommand("inserthtml", str); +}), queryCommandState: (function () { + _$jscoverage['plugins/music.js'][86]++; + var me = this, img = me.selection.getRange().getClosedNode(), flag = (img && (img.className == "edui-faked-music")); + _$jscoverage['plugins/music.js'][89]++; + return (flag? 1: 0); +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/pagebreak.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/pagebreak.js new file mode 100644 index 000000000..33d635338 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/pagebreak.js @@ -0,0 +1,303 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/pagebreak.js']) { + _$jscoverage['plugins/pagebreak.js'] = []; + _$jscoverage['plugins/pagebreak.js'][7] = 0; + _$jscoverage['plugins/pagebreak.js'][8] = 0; + _$jscoverage['plugins/pagebreak.js'][10] = 0; + _$jscoverage['plugins/pagebreak.js'][12] = 0; + _$jscoverage['plugins/pagebreak.js'][13] = 0; + _$jscoverage['plugins/pagebreak.js'][14] = 0; + _$jscoverage['plugins/pagebreak.js'][16] = 0; + _$jscoverage['plugins/pagebreak.js'][17] = 0; + _$jscoverage['plugins/pagebreak.js'][18] = 0; + _$jscoverage['plugins/pagebreak.js'][20] = 0; + _$jscoverage['plugins/pagebreak.js'][21] = 0; + _$jscoverage['plugins/pagebreak.js'][26] = 0; + _$jscoverage['plugins/pagebreak.js'][27] = 0; + _$jscoverage['plugins/pagebreak.js'][29] = 0; + _$jscoverage['plugins/pagebreak.js'][30] = 0; + _$jscoverage['plugins/pagebreak.js'][32] = 0; + _$jscoverage['plugins/pagebreak.js'][33] = 0; + _$jscoverage['plugins/pagebreak.js'][34] = 0; + _$jscoverage['plugins/pagebreak.js'][35] = 0; + _$jscoverage['plugins/pagebreak.js'][36] = 0; + _$jscoverage['plugins/pagebreak.js'][37] = 0; + _$jscoverage['plugins/pagebreak.js'][41] = 0; + _$jscoverage['plugins/pagebreak.js'][42] = 0; + _$jscoverage['plugins/pagebreak.js'][43] = 0; + _$jscoverage['plugins/pagebreak.js'][44] = 0; + _$jscoverage['plugins/pagebreak.js'][45] = 0; + _$jscoverage['plugins/pagebreak.js'][46] = 0; + _$jscoverage['plugins/pagebreak.js'][62] = 0; + _$jscoverage['plugins/pagebreak.js'][64] = 0; + _$jscoverage['plugins/pagebreak.js'][65] = 0; + _$jscoverage['plugins/pagebreak.js'][70] = 0; + _$jscoverage['plugins/pagebreak.js'][72] = 0; + _$jscoverage['plugins/pagebreak.js'][75] = 0; + _$jscoverage['plugins/pagebreak.js'][76] = 0; + _$jscoverage['plugins/pagebreak.js'][78] = 0; + _$jscoverage['plugins/pagebreak.js'][79] = 0; + _$jscoverage['plugins/pagebreak.js'][80] = 0; + _$jscoverage['plugins/pagebreak.js'][88] = 0; + _$jscoverage['plugins/pagebreak.js'][89] = 0; + _$jscoverage['plugins/pagebreak.js'][92] = 0; + _$jscoverage['plugins/pagebreak.js'][93] = 0; + _$jscoverage['plugins/pagebreak.js'][96] = 0; + _$jscoverage['plugins/pagebreak.js'][97] = 0; + _$jscoverage['plugins/pagebreak.js'][98] = 0; + _$jscoverage['plugins/pagebreak.js'][102] = 0; + _$jscoverage['plugins/pagebreak.js'][107] = 0; + _$jscoverage['plugins/pagebreak.js'][108] = 0; + _$jscoverage['plugins/pagebreak.js'][109] = 0; + _$jscoverage['plugins/pagebreak.js'][110] = 0; + _$jscoverage['plugins/pagebreak.js'][111] = 0; + _$jscoverage['plugins/pagebreak.js'][112] = 0; + _$jscoverage['plugins/pagebreak.js'][113] = 0; + _$jscoverage['plugins/pagebreak.js'][117] = 0; + _$jscoverage['plugins/pagebreak.js'][119] = 0; + _$jscoverage['plugins/pagebreak.js'][120] = 0; + _$jscoverage['plugins/pagebreak.js'][121] = 0; + _$jscoverage['plugins/pagebreak.js'][122] = 0; + _$jscoverage['plugins/pagebreak.js'][123] = 0; + _$jscoverage['plugins/pagebreak.js'][124] = 0; + _$jscoverage['plugins/pagebreak.js'][126] = 0; + _$jscoverage['plugins/pagebreak.js'][128] = 0; + _$jscoverage['plugins/pagebreak.js'][129] = 0; + _$jscoverage['plugins/pagebreak.js'][130] = 0; + _$jscoverage['plugins/pagebreak.js'][131] = 0; + _$jscoverage['plugins/pagebreak.js'][133] = 0; + _$jscoverage['plugins/pagebreak.js'][136] = 0; + _$jscoverage['plugins/pagebreak.js'][137] = 0; + _$jscoverage['plugins/pagebreak.js'][139] = 0; + _$jscoverage['plugins/pagebreak.js'][140] = 0; + _$jscoverage['plugins/pagebreak.js'][141] = 0; + _$jscoverage['plugins/pagebreak.js'][143] = 0; + _$jscoverage['plugins/pagebreak.js'][144] = 0; + _$jscoverage['plugins/pagebreak.js'][146] = 0; + _$jscoverage['plugins/pagebreak.js'][148] = 0; + _$jscoverage['plugins/pagebreak.js'][151] = 0; +} +_$jscoverage['plugins/pagebreak.js'].source = ["/**"," * 分页功能插件"," * @file"," * @since 1.2.6.1"," */","","UE.plugins['pagebreak'] = function () {"," var me = this,"," notBreakTags = ['td'];"," me.setOpt('pageBreakTag','_ueditor_page_break_tag_');",""," function fillNode(node){"," if(domUtils.isEmptyBlock(node)){"," var firstChild = node.firstChild,tmpNode;",""," while(firstChild && firstChild.nodeType == 1 && domUtils.isEmptyBlock(firstChild)){"," tmpNode = firstChild;"," firstChild = firstChild.firstChild;"," }"," !tmpNode && (tmpNode = node);"," domUtils.fillNode(me.document,tmpNode);"," }"," }"," //分页符样式添加",""," me.ready(function(){"," utils.cssRule('pagebreak','.pagebreak{display:block;clear:both !important;cursor:default !important;width: 100% !important;margin:0;}',me.document);"," });"," function isHr(node){"," return node && node.nodeType == 1 && node.tagName == 'HR' && node.className == 'pagebreak';"," }"," me.addInputRule(function(root){"," root.traversal(function(node){"," if(node.type == 'text' && node.data == me.options.pageBreakTag){"," var hr = UE.uNode.createElement('<hr class=\"pagebreak\" noshade=\"noshade\" size=\"5\" style=\"-webkit-user-select: none;\">');"," node.parentNode.insertBefore(hr,node);"," node.parentNode.removeChild(node)"," }"," })"," });"," me.addOutputRule(function(node){"," utils.each(node.getNodesByTagName('hr'),function(n){"," if(n.getAttr('class') == 'pagebreak'){"," var txt = UE.uNode.createText(me.options.pageBreakTag);"," n.parentNode.insertBefore(txt,n);"," n.parentNode.removeChild(n);"," }"," })",""," });",""," /**"," * 插入分页符,在当前光标插入分页符"," * @command pagebreak"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'pagebreak'); //插入一个hr标签,带有样式类名pagebreak"," * ```"," */"," me.commands['pagebreak'] = {"," execCommand:function () {"," var range = me.selection.getRange(),hr = me.document.createElement('hr');"," domUtils.setAttributes(hr,{"," 'class' : 'pagebreak',"," noshade:\"noshade\","," size:\"5\""," });"," domUtils.unSelectable(hr);"," //table单独处理"," var node = domUtils.findParentByTagName(range.startContainer, notBreakTags, true),",""," parents = [], pN;"," if (node) {"," switch (node.tagName) {"," case 'TD':"," pN = node.parentNode;"," if (!pN.previousSibling) {"," var table = domUtils.findParentByTagName(pN, 'table');","// var tableWrapDiv = table.parentNode;","// if(tableWrapDiv && tableWrapDiv.nodeType == 1","// && tableWrapDiv.tagName == 'DIV'","// && tableWrapDiv.getAttribute('dropdrag')","// ){","// domUtils.remove(tableWrapDiv,true);","// }"," table.parentNode.insertBefore(hr, table);"," parents = domUtils.findParents(hr, true);",""," } else {"," pN.parentNode.insertBefore(hr, pN);"," parents = domUtils.findParents(hr);",""," }"," pN = parents[1];"," if (hr !== pN) {"," domUtils.breakParent(hr, pN);",""," }"," //table要重写绑定一下拖拽"," me.fireEvent('afteradjusttable',me.document);"," }",""," } else {",""," if (!range.collapsed) {"," range.deleteContents();"," var start = range.startContainer;"," while ( !domUtils.isBody(start) && domUtils.isBlockElm(start) && domUtils.isEmptyNode(start)) {"," range.setStartBefore(start).collapse(true);"," domUtils.remove(start);"," start = range.startContainer;"," }",""," }"," range.insertNode(hr);",""," var pN = hr.parentNode, nextNode;"," while (!domUtils.isBody(pN)) {"," domUtils.breakParent(hr, pN);"," nextNode = hr.nextSibling;"," if (nextNode && domUtils.isEmptyBlock(nextNode)) {"," domUtils.remove(nextNode);"," }"," pN = hr.parentNode;"," }"," nextNode = hr.nextSibling;"," var pre = hr.previousSibling;"," if(isHr(pre)){"," domUtils.remove(pre);"," }else{"," pre && fillNode(pre);"," }",""," if(!nextNode){"," var p = me.document.createElement('p');",""," hr.parentNode.appendChild(p);"," domUtils.fillNode(me.document,p);"," range.setStart(p,0).collapse(true);"," }else{"," if(isHr(nextNode)){"," domUtils.remove(nextNode);"," }else{"," fillNode(nextNode);"," }"," range.setEndAfter(hr).collapse(false);"," }",""," range.select(true);",""," }",""," }"," };","};"]; +_$jscoverage['plugins/pagebreak.js'][7]++; +UE.plugins.pagebreak = (function () { + _$jscoverage['plugins/pagebreak.js'][8]++; + var me = this, notBreakTags = ["td"]; + _$jscoverage['plugins/pagebreak.js'][10]++; + me.setOpt("pageBreakTag", "_ueditor_page_break_tag_"); + _$jscoverage['plugins/pagebreak.js'][12]++; + function fillNode(node) { + _$jscoverage['plugins/pagebreak.js'][13]++; + if (domUtils.isEmptyBlock(node)) { + _$jscoverage['plugins/pagebreak.js'][14]++; + var firstChild = node.firstChild, tmpNode; + _$jscoverage['plugins/pagebreak.js'][16]++; + while ((firstChild && (firstChild.nodeType == 1) && domUtils.isEmptyBlock(firstChild))) { + _$jscoverage['plugins/pagebreak.js'][17]++; + tmpNode = firstChild; + _$jscoverage['plugins/pagebreak.js'][18]++; + firstChild = firstChild.firstChild; +} + _$jscoverage['plugins/pagebreak.js'][20]++; + ((! tmpNode) && (tmpNode = node)); + _$jscoverage['plugins/pagebreak.js'][21]++; + domUtils.fillNode(me.document, tmpNode); + } +} + _$jscoverage['plugins/pagebreak.js'][26]++; + me.ready((function () { + _$jscoverage['plugins/pagebreak.js'][27]++; + utils.cssRule("pagebreak", ".pagebreak{display:block;clear:both !important;cursor:default !important;width: 100% !important;margin:0;}", me.document); +})); + _$jscoverage['plugins/pagebreak.js'][29]++; + function isHr(node) { + _$jscoverage['plugins/pagebreak.js'][30]++; + return (node && (node.nodeType == 1) && (node.tagName == "HR") && (node.className == "pagebreak")); +} + _$jscoverage['plugins/pagebreak.js'][32]++; + me.addInputRule((function (root) { + _$jscoverage['plugins/pagebreak.js'][33]++; + root.traversal((function (node) { + _$jscoverage['plugins/pagebreak.js'][34]++; + if (((node.type == "text") && (node.data == me.options.pageBreakTag))) { + _$jscoverage['plugins/pagebreak.js'][35]++; + var hr = UE.uNode.createElement("
    "); + _$jscoverage['plugins/pagebreak.js'][36]++; + node.parentNode.insertBefore(hr, node); + _$jscoverage['plugins/pagebreak.js'][37]++; + node.parentNode.removeChild(node); + } +})); +})); + _$jscoverage['plugins/pagebreak.js'][41]++; + me.addOutputRule((function (node) { + _$jscoverage['plugins/pagebreak.js'][42]++; + utils.each(node.getNodesByTagName("hr"), (function (n) { + _$jscoverage['plugins/pagebreak.js'][43]++; + if ((n.getAttr("class") == "pagebreak")) { + _$jscoverage['plugins/pagebreak.js'][44]++; + var txt = UE.uNode.createText(me.options.pageBreakTag); + _$jscoverage['plugins/pagebreak.js'][45]++; + n.parentNode.insertBefore(txt, n); + _$jscoverage['plugins/pagebreak.js'][46]++; + n.parentNode.removeChild(n); + } +})); +})); + _$jscoverage['plugins/pagebreak.js'][62]++; + me.commands.pagebreak = {execCommand: (function () { + _$jscoverage['plugins/pagebreak.js'][64]++; + var range = me.selection.getRange(), hr = me.document.createElement("hr"); + _$jscoverage['plugins/pagebreak.js'][65]++; + domUtils.setAttributes(hr, {"class": "pagebreak", noshade: "noshade", size: "5"}); + _$jscoverage['plugins/pagebreak.js'][70]++; + domUtils.unSelectable(hr); + _$jscoverage['plugins/pagebreak.js'][72]++; + var node = domUtils.findParentByTagName(range.startContainer, notBreakTags, true), parents = [], pN; + _$jscoverage['plugins/pagebreak.js'][75]++; + if (node) { + _$jscoverage['plugins/pagebreak.js'][76]++; + switch (node.tagName) { + case "TD": + _$jscoverage['plugins/pagebreak.js'][78]++; + pN = node.parentNode; + _$jscoverage['plugins/pagebreak.js'][79]++; + if ((! pN.previousSibling)) { + _$jscoverage['plugins/pagebreak.js'][80]++; + var table = domUtils.findParentByTagName(pN, "table"); + _$jscoverage['plugins/pagebreak.js'][88]++; + table.parentNode.insertBefore(hr, table); + _$jscoverage['plugins/pagebreak.js'][89]++; + parents = domUtils.findParents(hr, true); + } + else { + _$jscoverage['plugins/pagebreak.js'][92]++; + pN.parentNode.insertBefore(hr, pN); + _$jscoverage['plugins/pagebreak.js'][93]++; + parents = domUtils.findParents(hr); + } + _$jscoverage['plugins/pagebreak.js'][96]++; + pN = parents[1]; + _$jscoverage['plugins/pagebreak.js'][97]++; + if ((hr !== pN)) { + _$jscoverage['plugins/pagebreak.js'][98]++; + domUtils.breakParent(hr, pN); + } + _$jscoverage['plugins/pagebreak.js'][102]++; + me.fireEvent("afteradjusttable", me.document); + } + } + else { + _$jscoverage['plugins/pagebreak.js'][107]++; + if ((! range.collapsed)) { + _$jscoverage['plugins/pagebreak.js'][108]++; + range.deleteContents(); + _$jscoverage['plugins/pagebreak.js'][109]++; + var start = range.startContainer; + _$jscoverage['plugins/pagebreak.js'][110]++; + while (((! domUtils.isBody(start)) && domUtils.isBlockElm(start) && domUtils.isEmptyNode(start))) { + _$jscoverage['plugins/pagebreak.js'][111]++; + range.setStartBefore(start).collapse(true); + _$jscoverage['plugins/pagebreak.js'][112]++; + domUtils.remove(start); + _$jscoverage['plugins/pagebreak.js'][113]++; + start = range.startContainer; +} + } + _$jscoverage['plugins/pagebreak.js'][117]++; + range.insertNode(hr); + _$jscoverage['plugins/pagebreak.js'][119]++; + var pN = hr.parentNode, nextNode; + _$jscoverage['plugins/pagebreak.js'][120]++; + while ((! domUtils.isBody(pN))) { + _$jscoverage['plugins/pagebreak.js'][121]++; + domUtils.breakParent(hr, pN); + _$jscoverage['plugins/pagebreak.js'][122]++; + nextNode = hr.nextSibling; + _$jscoverage['plugins/pagebreak.js'][123]++; + if ((nextNode && domUtils.isEmptyBlock(nextNode))) { + _$jscoverage['plugins/pagebreak.js'][124]++; + domUtils.remove(nextNode); + } + _$jscoverage['plugins/pagebreak.js'][126]++; + pN = hr.parentNode; +} + _$jscoverage['plugins/pagebreak.js'][128]++; + nextNode = hr.nextSibling; + _$jscoverage['plugins/pagebreak.js'][129]++; + var pre = hr.previousSibling; + _$jscoverage['plugins/pagebreak.js'][130]++; + if (isHr(pre)) { + _$jscoverage['plugins/pagebreak.js'][131]++; + domUtils.remove(pre); + } + else { + _$jscoverage['plugins/pagebreak.js'][133]++; + (pre && fillNode(pre)); + } + _$jscoverage['plugins/pagebreak.js'][136]++; + if ((! nextNode)) { + _$jscoverage['plugins/pagebreak.js'][137]++; + var p = me.document.createElement("p"); + _$jscoverage['plugins/pagebreak.js'][139]++; + hr.parentNode.appendChild(p); + _$jscoverage['plugins/pagebreak.js'][140]++; + domUtils.fillNode(me.document, p); + _$jscoverage['plugins/pagebreak.js'][141]++; + range.setStart(p, 0).collapse(true); + } + else { + _$jscoverage['plugins/pagebreak.js'][143]++; + if (isHr(nextNode)) { + _$jscoverage['plugins/pagebreak.js'][144]++; + domUtils.remove(nextNode); + } + else { + _$jscoverage['plugins/pagebreak.js'][146]++; + fillNode(nextNode); + } + _$jscoverage['plugins/pagebreak.js'][148]++; + range.setEndAfter(hr).collapse(false); + } + _$jscoverage['plugins/pagebreak.js'][151]++; + range.select(true); + } +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/paragraph.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/paragraph.js new file mode 100644 index 000000000..33ceb78b6 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/paragraph.js @@ -0,0 +1,290 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/paragraph.js']) { + _$jscoverage['plugins/paragraph.js'] = []; + _$jscoverage['plugins/paragraph.js'][47] = 0; + _$jscoverage['plugins/paragraph.js'][48] = 0; + _$jscoverage['plugins/paragraph.js'][53] = 0; + _$jscoverage['plugins/paragraph.js'][55] = 0; + _$jscoverage['plugins/paragraph.js'][59] = 0; + _$jscoverage['plugins/paragraph.js'][60] = 0; + _$jscoverage['plugins/paragraph.js'][64] = 0; + _$jscoverage['plugins/paragraph.js'][65] = 0; + _$jscoverage['plugins/paragraph.js'][66] = 0; + _$jscoverage['plugins/paragraph.js'][67] = 0; + _$jscoverage['plugins/paragraph.js'][68] = 0; + _$jscoverage['plugins/paragraph.js'][69] = 0; + _$jscoverage['plugins/paragraph.js'][70] = 0; + _$jscoverage['plugins/paragraph.js'][73] = 0; + _$jscoverage['plugins/paragraph.js'][75] = 0; + _$jscoverage['plugins/paragraph.js'][76] = 0; + _$jscoverage['plugins/paragraph.js'][77] = 0; + _$jscoverage['plugins/paragraph.js'][78] = 0; + _$jscoverage['plugins/paragraph.js'][79] = 0; + _$jscoverage['plugins/paragraph.js'][82] = 0; + _$jscoverage['plugins/paragraph.js'][84] = 0; + _$jscoverage['plugins/paragraph.js'][85] = 0; + _$jscoverage['plugins/paragraph.js'][89] = 0; + _$jscoverage['plugins/paragraph.js'][91] = 0; + _$jscoverage['plugins/paragraph.js'][93] = 0; + _$jscoverage['plugins/paragraph.js'][95] = 0; + _$jscoverage['plugins/paragraph.js'][96] = 0; + _$jscoverage['plugins/paragraph.js'][98] = 0; + _$jscoverage['plugins/paragraph.js'][100] = 0; + _$jscoverage['plugins/paragraph.js'][101] = 0; + _$jscoverage['plugins/paragraph.js'][102] = 0; + _$jscoverage['plugins/paragraph.js'][106] = 0; + _$jscoverage['plugins/paragraph.js'][107] = 0; + _$jscoverage['plugins/paragraph.js'][108] = 0; + _$jscoverage['plugins/paragraph.js'][109] = 0; + _$jscoverage['plugins/paragraph.js'][111] = 0; + _$jscoverage['plugins/paragraph.js'][112] = 0; + _$jscoverage['plugins/paragraph.js'][114] = 0; + _$jscoverage['plugins/paragraph.js'][118] = 0; + _$jscoverage['plugins/paragraph.js'][119] = 0; + _$jscoverage['plugins/paragraph.js'][121] = 0; + _$jscoverage['plugins/paragraph.js'][125] = 0; + _$jscoverage['plugins/paragraph.js'][127] = 0; + _$jscoverage['plugins/paragraph.js'][130] = 0; + _$jscoverage['plugins/paragraph.js'][132] = 0; + _$jscoverage['plugins/paragraph.js'][133] = 0; + _$jscoverage['plugins/paragraph.js'][135] = 0; + _$jscoverage['plugins/paragraph.js'][137] = 0; + _$jscoverage['plugins/paragraph.js'][138] = 0; + _$jscoverage['plugins/paragraph.js'][139] = 0; + _$jscoverage['plugins/paragraph.js'][141] = 0; + _$jscoverage['plugins/paragraph.js'][142] = 0; + _$jscoverage['plugins/paragraph.js'][143] = 0; + _$jscoverage['plugins/paragraph.js'][144] = 0; + _$jscoverage['plugins/paragraph.js'][146] = 0; + _$jscoverage['plugins/paragraph.js'][147] = 0; + _$jscoverage['plugins/paragraph.js'][148] = 0; + _$jscoverage['plugins/paragraph.js'][153] = 0; + _$jscoverage['plugins/paragraph.js'][154] = 0; + _$jscoverage['plugins/paragraph.js'][155] = 0; + _$jscoverage['plugins/paragraph.js'][156] = 0; + _$jscoverage['plugins/paragraph.js'][158] = 0; + _$jscoverage['plugins/paragraph.js'][160] = 0; + _$jscoverage['plugins/paragraph.js'][161] = 0; + _$jscoverage['plugins/paragraph.js'][166] = 0; + _$jscoverage['plugins/paragraph.js'][167] = 0; + _$jscoverage['plugins/paragraph.js'][168] = 0; + _$jscoverage['plugins/paragraph.js'][169] = 0; + _$jscoverage['plugins/paragraph.js'][173] = 0; + _$jscoverage['plugins/paragraph.js'][176] = 0; + _$jscoverage['plugins/paragraph.js'][179] = 0; + _$jscoverage['plugins/paragraph.js'][180] = 0; +} +_$jscoverage['plugins/paragraph.js'].source = ["/**"," * 段落样式"," * @file"," * @since 1.2.6.1"," */","/**"," * 对选区内文本添加相应标签嵌套"," * @command Paragraph"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param {String} style 标签值为:'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'"," * @param {Object} attrs 标签的属性"," * @example"," * ```javascript"," * editor.execCommand( 'Paragraph','h1','{"," * color:'#000'"," * }' );"," * ```"," */","/**"," * 对选区内文本添加相应标签嵌套"," * @command Paragraph"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param {String} style 标签值为:'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'"," * @param {Object} attrs 标签的属性"," * @param {String} sourceCmdName 对与customstyle特殊处理"," * @example"," * ```javascript"," * editor.execCommand( 'Paragraph','h1','{"," * color:'#000'"," * }' );"," * ```"," */","/**"," * 返回选区内节点标签名"," * @command Paragraph"," * @method queryCommandValue"," * @param { String } cmd 命令字符串"," * @return { String } 节点标签名"," * @example"," * ```javascript"," * editor.queryCommandValue( 'Paragraph' );"," * ```"," */","","UE.plugins['paragraph'] = function() {"," var me = this,"," block = domUtils.isBlockElm,"," notExchange = ['TD','LI','PRE'],",""," doParagraph = function(range,style,attrs,sourceCmdName){"," var bookmark = range.createBookmark(),"," filterFn = function( node ) {"," return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' && !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace( node );"," },"," para;",""," range.enlarge( true );"," var bookmark2 = range.createBookmark(),"," current = domUtils.getNextDomNode( bookmark2.start, false, filterFn ),"," tmpRange = range.cloneRange(),"," tmpNode;"," while ( current && !(domUtils.getPosition( current, bookmark2.end ) & domUtils.POSITION_FOLLOWING) ) {"," if ( current.nodeType == 3 || !block( current ) ) {"," tmpRange.setStartBefore( current );"," while ( current && current !== bookmark2.end && !block( current ) ) {"," tmpNode = current;"," current = domUtils.getNextDomNode( current, false, null, function( node ) {"," return !block( node );"," } );"," }"," tmpRange.setEndAfter( tmpNode );"," "," para = range.document.createElement( style );"," if(attrs){"," domUtils.setAttributes(para,attrs);"," if(sourceCmdName && sourceCmdName == 'customstyle' && attrs.style){"," para.style.cssText = attrs.style;"," }"," }"," para.appendChild( tmpRange.extractContents() );"," //需要内容占位"," if(domUtils.isEmptyNode(para)){"," domUtils.fillChar(range.document,para);"," "," }",""," tmpRange.insertNode( para );",""," var parent = para.parentNode;"," //如果para上一级是一个block元素且不是body,td就删除它"," if ( block( parent ) && !domUtils.isBody( para.parentNode ) && utils.indexOf(notExchange,parent.tagName)==-1) {"," //存储dir,style"," if(!(sourceCmdName && sourceCmdName == 'customstyle')){"," parent.getAttribute('dir') && para.setAttribute('dir',parent.getAttribute('dir'));"," //trace:1070"," parent.style.cssText && (para.style.cssText = parent.style.cssText + ';' + para.style.cssText);"," //trace:1030"," parent.style.textAlign && !para.style.textAlign && (para.style.textAlign = parent.style.textAlign);"," parent.style.textIndent && !para.style.textIndent && (para.style.textIndent = parent.style.textIndent);"," parent.style.padding && !para.style.padding && (para.style.padding = parent.style.padding);"," }",""," //trace:1706 选择的就是h1-6要删除"," if(attrs && /h\\d/i.test(parent.tagName) && !/h\\d/i.test(para.tagName) ){"," domUtils.setAttributes(parent,attrs);"," if(sourceCmdName && sourceCmdName == 'customstyle' && attrs.style){"," parent.style.cssText = attrs.style;"," }"," domUtils.remove(para,true);"," para = parent;"," }else{"," domUtils.remove( para.parentNode, true );"," }",""," }"," if( utils.indexOf(notExchange,parent.tagName)!=-1){"," current = parent;"," }else{"," current = para;"," }","",""," current = domUtils.getNextDomNode( current, false, filterFn );"," } else {"," current = domUtils.getNextDomNode( current, true, filterFn );"," }"," }"," return range.moveToBookmark( bookmark2 ).moveToBookmark( bookmark );"," };"," me.setOpt('paragraph',{'p':'', 'h1':'', 'h2':'', 'h3':'', 'h4':'', 'h5':'', 'h6':''});"," me.commands['paragraph'] = {"," execCommand : function( cmdName, style,attrs,sourceCmdName ) {"," var range = this.selection.getRange();"," //闭合时单独处理"," if(range.collapsed){"," var txt = this.document.createTextNode('p');"," range.insertNode(txt);"," //去掉冗余的fillchar"," if(browser.ie){"," var node = txt.previousSibling;"," if(node && domUtils.isWhitespace(node)){"," domUtils.remove(node);"," }"," node = txt.nextSibling;"," if(node && domUtils.isWhitespace(node)){"," domUtils.remove(node);"," }"," }",""," }"," range = doParagraph(range,style,attrs,sourceCmdName);"," if(txt){"," range.setStartBefore(txt).collapse(true);"," pN = txt.parentNode;",""," domUtils.remove(txt);",""," if(domUtils.isBlockElm(pN)&&domUtils.isEmptyNode(pN)){"," domUtils.fillNode(this.document,pN);"," }",""," }",""," if(browser.gecko && range.collapsed && range.startContainer.nodeType == 1){"," var child = range.startContainer.childNodes[range.startOffset];"," if(child && child.nodeType == 1 && child.tagName.toLowerCase() == style){"," range.setStart(child,0).collapse(true);"," }"," }"," //trace:1097 原来有true,原因忘了,但去了就不能清除多余的占位符了"," range.select();","",""," return true;"," },"," queryCommandValue : function() {"," var node = domUtils.filterNodeList(this.selection.getStartElementPath(),'p h1 h2 h3 h4 h5 h6');"," return node ? node.tagName.toLowerCase() : '';"," }"," };","};"]; +_$jscoverage['plugins/paragraph.js'][47]++; +UE.plugins.paragraph = (function () { + _$jscoverage['plugins/paragraph.js'][48]++; + var me = this, block = domUtils.isBlockElm, notExchange = ["TD", "LI", "PRE"], doParagraph = (function (range, style, attrs, sourceCmdName) { + _$jscoverage['plugins/paragraph.js'][53]++; + var bookmark = range.createBookmark(), filterFn = (function (node) { + _$jscoverage['plugins/paragraph.js'][55]++; + return ((node.nodeType == 1)? ((node.tagName.toLowerCase() != "br") && (! domUtils.isBookmarkNode(node))): (! domUtils.isWhitespace(node))); +}), para; + _$jscoverage['plugins/paragraph.js'][59]++; + range.enlarge(true); + _$jscoverage['plugins/paragraph.js'][60]++; + var bookmark2 = range.createBookmark(), current = domUtils.getNextDomNode(bookmark2.start, false, filterFn), tmpRange = range.cloneRange(), tmpNode; + _$jscoverage['plugins/paragraph.js'][64]++; + while ((current && (! (domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)))) { + _$jscoverage['plugins/paragraph.js'][65]++; + if (((current.nodeType == 3) || (! block(current)))) { + _$jscoverage['plugins/paragraph.js'][66]++; + tmpRange.setStartBefore(current); + _$jscoverage['plugins/paragraph.js'][67]++; + while ((current && (current !== bookmark2.end) && (! block(current)))) { + _$jscoverage['plugins/paragraph.js'][68]++; + tmpNode = current; + _$jscoverage['plugins/paragraph.js'][69]++; + current = domUtils.getNextDomNode(current, false, null, (function (node) { + _$jscoverage['plugins/paragraph.js'][70]++; + return (! block(node)); +})); +} + _$jscoverage['plugins/paragraph.js'][73]++; + tmpRange.setEndAfter(tmpNode); + _$jscoverage['plugins/paragraph.js'][75]++; + para = range.document.createElement(style); + _$jscoverage['plugins/paragraph.js'][76]++; + if (attrs) { + _$jscoverage['plugins/paragraph.js'][77]++; + domUtils.setAttributes(para, attrs); + _$jscoverage['plugins/paragraph.js'][78]++; + if ((sourceCmdName && (sourceCmdName == "customstyle") && attrs.style)) { + _$jscoverage['plugins/paragraph.js'][79]++; + para.style.cssText = attrs.style; + } + } + _$jscoverage['plugins/paragraph.js'][82]++; + para.appendChild(tmpRange.extractContents()); + _$jscoverage['plugins/paragraph.js'][84]++; + if (domUtils.isEmptyNode(para)) { + _$jscoverage['plugins/paragraph.js'][85]++; + domUtils.fillChar(range.document, para); + } + _$jscoverage['plugins/paragraph.js'][89]++; + tmpRange.insertNode(para); + _$jscoverage['plugins/paragraph.js'][91]++; + var parent = para.parentNode; + _$jscoverage['plugins/paragraph.js'][93]++; + if ((block(parent) && (! domUtils.isBody(para.parentNode)) && (utils.indexOf(notExchange, parent.tagName) == -1))) { + _$jscoverage['plugins/paragraph.js'][95]++; + if ((! (sourceCmdName && (sourceCmdName == "customstyle")))) { + _$jscoverage['plugins/paragraph.js'][96]++; + (parent.getAttribute("dir") && para.setAttribute("dir", parent.getAttribute("dir"))); + _$jscoverage['plugins/paragraph.js'][98]++; + (parent.style.cssText && (para.style.cssText = (parent.style.cssText + ";" + para.style.cssText))); + _$jscoverage['plugins/paragraph.js'][100]++; + (parent.style.textAlign && (! para.style.textAlign) && (para.style.textAlign = parent.style.textAlign)); + _$jscoverage['plugins/paragraph.js'][101]++; + (parent.style.textIndent && (! para.style.textIndent) && (para.style.textIndent = parent.style.textIndent)); + _$jscoverage['plugins/paragraph.js'][102]++; + (parent.style.padding && (! para.style.padding) && (para.style.padding = parent.style.padding)); + } + _$jscoverage['plugins/paragraph.js'][106]++; + if ((attrs && /h\d/i.test(parent.tagName) && (! /h\d/i.test(para.tagName)))) { + _$jscoverage['plugins/paragraph.js'][107]++; + domUtils.setAttributes(parent, attrs); + _$jscoverage['plugins/paragraph.js'][108]++; + if ((sourceCmdName && (sourceCmdName == "customstyle") && attrs.style)) { + _$jscoverage['plugins/paragraph.js'][109]++; + parent.style.cssText = attrs.style; + } + _$jscoverage['plugins/paragraph.js'][111]++; + domUtils.remove(para, true); + _$jscoverage['plugins/paragraph.js'][112]++; + para = parent; + } + else { + _$jscoverage['plugins/paragraph.js'][114]++; + domUtils.remove(para.parentNode, true); + } + } + _$jscoverage['plugins/paragraph.js'][118]++; + if ((utils.indexOf(notExchange, parent.tagName) != -1)) { + _$jscoverage['plugins/paragraph.js'][119]++; + current = parent; + } + else { + _$jscoverage['plugins/paragraph.js'][121]++; + current = para; + } + _$jscoverage['plugins/paragraph.js'][125]++; + current = domUtils.getNextDomNode(current, false, filterFn); + } + else { + _$jscoverage['plugins/paragraph.js'][127]++; + current = domUtils.getNextDomNode(current, true, filterFn); + } +} + _$jscoverage['plugins/paragraph.js'][130]++; + return range.moveToBookmark(bookmark2).moveToBookmark(bookmark); +}); + _$jscoverage['plugins/paragraph.js'][132]++; + me.setOpt("paragraph", {"p": "", "h1": "", "h2": "", "h3": "", "h4": "", "h5": "", "h6": ""}); + _$jscoverage['plugins/paragraph.js'][133]++; + me.commands.paragraph = {execCommand: (function (cmdName, style, attrs, sourceCmdName) { + _$jscoverage['plugins/paragraph.js'][135]++; + var range = this.selection.getRange(); + _$jscoverage['plugins/paragraph.js'][137]++; + if (range.collapsed) { + _$jscoverage['plugins/paragraph.js'][138]++; + var txt = this.document.createTextNode("p"); + _$jscoverage['plugins/paragraph.js'][139]++; + range.insertNode(txt); + _$jscoverage['plugins/paragraph.js'][141]++; + if (browser.ie) { + _$jscoverage['plugins/paragraph.js'][142]++; + var node = txt.previousSibling; + _$jscoverage['plugins/paragraph.js'][143]++; + if ((node && domUtils.isWhitespace(node))) { + _$jscoverage['plugins/paragraph.js'][144]++; + domUtils.remove(node); + } + _$jscoverage['plugins/paragraph.js'][146]++; + node = txt.nextSibling; + _$jscoverage['plugins/paragraph.js'][147]++; + if ((node && domUtils.isWhitespace(node))) { + _$jscoverage['plugins/paragraph.js'][148]++; + domUtils.remove(node); + } + } + } + _$jscoverage['plugins/paragraph.js'][153]++; + range = doParagraph(range, style, attrs, sourceCmdName); + _$jscoverage['plugins/paragraph.js'][154]++; + if (txt) { + _$jscoverage['plugins/paragraph.js'][155]++; + range.setStartBefore(txt).collapse(true); + _$jscoverage['plugins/paragraph.js'][156]++; + pN = txt.parentNode; + _$jscoverage['plugins/paragraph.js'][158]++; + domUtils.remove(txt); + _$jscoverage['plugins/paragraph.js'][160]++; + if ((domUtils.isBlockElm(pN) && domUtils.isEmptyNode(pN))) { + _$jscoverage['plugins/paragraph.js'][161]++; + domUtils.fillNode(this.document, pN); + } + } + _$jscoverage['plugins/paragraph.js'][166]++; + if ((browser.gecko && range.collapsed && (range.startContainer.nodeType == 1))) { + _$jscoverage['plugins/paragraph.js'][167]++; + var child = range.startContainer.childNodes[range.startOffset]; + _$jscoverage['plugins/paragraph.js'][168]++; + if ((child && (child.nodeType == 1) && (child.tagName.toLowerCase() == style))) { + _$jscoverage['plugins/paragraph.js'][169]++; + range.setStart(child, 0).collapse(true); + } + } + _$jscoverage['plugins/paragraph.js'][173]++; + range.select(); + _$jscoverage['plugins/paragraph.js'][176]++; + return true; +}), queryCommandValue: (function () { + _$jscoverage['plugins/paragraph.js'][179]++; + var node = domUtils.filterNodeList(this.selection.getStartElementPath(), "p h1 h2 h3 h4 h5 h6"); + _$jscoverage['plugins/paragraph.js'][180]++; + return (node? node.tagName.toLowerCase(): ""); +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/paste.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/paste.js new file mode 100644 index 000000000..df0dde7f3 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/paste.js @@ -0,0 +1,574 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/paste.js']) { + _$jscoverage['plugins/paste.js'] = []; + _$jscoverage['plugins/paste.js'][12] = 0; + _$jscoverage['plugins/paste.js'][13] = 0; + _$jscoverage['plugins/paste.js'][14] = 0; + _$jscoverage['plugins/paste.js'][15] = 0; + _$jscoverage['plugins/paste.js'][16] = 0; + _$jscoverage['plugins/paste.js'][18] = 0; + _$jscoverage['plugins/paste.js'][22] = 0; + _$jscoverage['plugins/paste.js'][24] = 0; + _$jscoverage['plugins/paste.js'][25] = 0; + _$jscoverage['plugins/paste.js'][28] = 0; + _$jscoverage['plugins/paste.js'][29] = 0; + _$jscoverage['plugins/paste.js'][33] = 0; + _$jscoverage['plugins/paste.js'][35] = 0; + _$jscoverage['plugins/paste.js'][36] = 0; + _$jscoverage['plugins/paste.js'][37] = 0; + _$jscoverage['plugins/paste.js'][38] = 0; + _$jscoverage['plugins/paste.js'][39] = 0; + _$jscoverage['plugins/paste.js'][41] = 0; + _$jscoverage['plugins/paste.js'][42] = 0; + _$jscoverage['plugins/paste.js'][46] = 0; + _$jscoverage['plugins/paste.js'][47] = 0; + _$jscoverage['plugins/paste.js'][50] = 0; + _$jscoverage['plugins/paste.js'][51] = 0; + _$jscoverage['plugins/paste.js'][55] = 0; + _$jscoverage['plugins/paste.js'][57] = 0; + _$jscoverage['plugins/paste.js'][59] = 0; + _$jscoverage['plugins/paste.js'][60] = 0; + _$jscoverage['plugins/paste.js'][61] = 0; + _$jscoverage['plugins/paste.js'][63] = 0; + _$jscoverage['plugins/paste.js'][64] = 0; + _$jscoverage['plugins/paste.js'][65] = 0; + _$jscoverage['plugins/paste.js'][66] = 0; + _$jscoverage['plugins/paste.js'][70] = 0; + _$jscoverage['plugins/paste.js'][72] = 0; + _$jscoverage['plugins/paste.js'][73] = 0; + _$jscoverage['plugins/paste.js'][74] = 0; + _$jscoverage['plugins/paste.js'][75] = 0; + _$jscoverage['plugins/paste.js'][76] = 0; + _$jscoverage['plugins/paste.js'][77] = 0; + _$jscoverage['plugins/paste.js'][80] = 0; + _$jscoverage['plugins/paste.js'][81] = 0; + _$jscoverage['plugins/paste.js'][82] = 0; + _$jscoverage['plugins/paste.js'][83] = 0; + _$jscoverage['plugins/paste.js'][84] = 0; + _$jscoverage['plugins/paste.js'][85] = 0; + _$jscoverage['plugins/paste.js'][87] = 0; + _$jscoverage['plugins/paste.js'][90] = 0; + _$jscoverage['plugins/paste.js'][91] = 0; + _$jscoverage['plugins/paste.js'][92] = 0; + _$jscoverage['plugins/paste.js'][95] = 0; + _$jscoverage['plugins/paste.js'][96] = 0; + _$jscoverage['plugins/paste.js'][97] = 0; + _$jscoverage['plugins/paste.js'][98] = 0; + _$jscoverage['plugins/paste.js'][102] = 0; + _$jscoverage['plugins/paste.js'][103] = 0; + _$jscoverage['plugins/paste.js'][104] = 0; + _$jscoverage['plugins/paste.js'][105] = 0; + _$jscoverage['plugins/paste.js'][108] = 0; + _$jscoverage['plugins/paste.js'][109] = 0; + _$jscoverage['plugins/paste.js'][110] = 0; + _$jscoverage['plugins/paste.js'][111] = 0; + _$jscoverage['plugins/paste.js'][116] = 0; + _$jscoverage['plugins/paste.js'][119] = 0; + _$jscoverage['plugins/paste.js'][121] = 0; + _$jscoverage['plugins/paste.js'][123] = 0; + _$jscoverage['plugins/paste.js'][124] = 0; + _$jscoverage['plugins/paste.js'][127] = 0; + _$jscoverage['plugins/paste.js'][129] = 0; + _$jscoverage['plugins/paste.js'][130] = 0; + _$jscoverage['plugins/paste.js'][131] = 0; + _$jscoverage['plugins/paste.js'][132] = 0; + _$jscoverage['plugins/paste.js'][134] = 0; + _$jscoverage['plugins/paste.js'][135] = 0; + _$jscoverage['plugins/paste.js'][136] = 0; + _$jscoverage['plugins/paste.js'][140] = 0; + _$jscoverage['plugins/paste.js'][141] = 0; + _$jscoverage['plugins/paste.js'][143] = 0; + _$jscoverage['plugins/paste.js'][144] = 0; + _$jscoverage['plugins/paste.js'][146] = 0; + _$jscoverage['plugins/paste.js'][148] = 0; + _$jscoverage['plugins/paste.js'][149] = 0; + _$jscoverage['plugins/paste.js'][152] = 0; + _$jscoverage['plugins/paste.js'][153] = 0; + _$jscoverage['plugins/paste.js'][155] = 0; + _$jscoverage['plugins/paste.js'][157] = 0; + _$jscoverage['plugins/paste.js'][158] = 0; + _$jscoverage['plugins/paste.js'][160] = 0; + _$jscoverage['plugins/paste.js'][164] = 0; + _$jscoverage['plugins/paste.js'][166] = 0; + _$jscoverage['plugins/paste.js'][167] = 0; + _$jscoverage['plugins/paste.js'][168] = 0; + _$jscoverage['plugins/paste.js'][170] = 0; + _$jscoverage['plugins/paste.js'][172] = 0; + _$jscoverage['plugins/paste.js'][174] = 0; + _$jscoverage['plugins/paste.js'][175] = 0; + _$jscoverage['plugins/paste.js'][176] = 0; + _$jscoverage['plugins/paste.js'][177] = 0; + _$jscoverage['plugins/paste.js'][178] = 0; + _$jscoverage['plugins/paste.js'][179] = 0; + _$jscoverage['plugins/paste.js'][181] = 0; + _$jscoverage['plugins/paste.js'][183] = 0; + _$jscoverage['plugins/paste.js'][184] = 0; + _$jscoverage['plugins/paste.js'][187] = 0; + _$jscoverage['plugins/paste.js'][188] = 0; + _$jscoverage['plugins/paste.js'][190] = 0; + _$jscoverage['plugins/paste.js'][194] = 0; + _$jscoverage['plugins/paste.js'][196] = 0; + _$jscoverage['plugins/paste.js'][197] = 0; + _$jscoverage['plugins/paste.js'][198] = 0; + _$jscoverage['plugins/paste.js'][199] = 0; + _$jscoverage['plugins/paste.js'][200] = 0; + _$jscoverage['plugins/paste.js'][201] = 0; + _$jscoverage['plugins/paste.js'][203] = 0; + _$jscoverage['plugins/paste.js'][204] = 0; + _$jscoverage['plugins/paste.js'][205] = 0; + _$jscoverage['plugins/paste.js'][208] = 0; + _$jscoverage['plugins/paste.js'][209] = 0; + _$jscoverage['plugins/paste.js'][211] = 0; + _$jscoverage['plugins/paste.js'][218] = 0; + _$jscoverage['plugins/paste.js'][219] = 0; + _$jscoverage['plugins/paste.js'][220] = 0; + _$jscoverage['plugins/paste.js'][221] = 0; + _$jscoverage['plugins/paste.js'][222] = 0; + _$jscoverage['plugins/paste.js'][223] = 0; + _$jscoverage['plugins/paste.js'][224] = 0; + _$jscoverage['plugins/paste.js'][225] = 0; + _$jscoverage['plugins/paste.js'][226] = 0; + _$jscoverage['plugins/paste.js'][228] = 0; + _$jscoverage['plugins/paste.js'][229] = 0; + _$jscoverage['plugins/paste.js'][234] = 0; + _$jscoverage['plugins/paste.js'][236] = 0; + _$jscoverage['plugins/paste.js'][238] = 0; + _$jscoverage['plugins/paste.js'][242] = 0; + _$jscoverage['plugins/paste.js'][245] = 0; + _$jscoverage['plugins/paste.js'][249] = 0; + _$jscoverage['plugins/paste.js'][250] = 0; + _$jscoverage['plugins/paste.js'][252] = 0; + _$jscoverage['plugins/paste.js'][253] = 0; + _$jscoverage['plugins/paste.js'][254] = 0; + _$jscoverage['plugins/paste.js'][255] = 0; + _$jscoverage['plugins/paste.js'][258] = 0; + _$jscoverage['plugins/paste.js'][260] = 0; + _$jscoverage['plugins/paste.js'][261] = 0; + _$jscoverage['plugins/paste.js'][264] = 0; + _$jscoverage['plugins/paste.js'][265] = 0; + _$jscoverage['plugins/paste.js'][266] = 0; + _$jscoverage['plugins/paste.js'][267] = 0; + _$jscoverage['plugins/paste.js'][268] = 0; + _$jscoverage['plugins/paste.js'][273] = 0; + _$jscoverage['plugins/paste.js'][274] = 0; + _$jscoverage['plugins/paste.js'][275] = 0; + _$jscoverage['plugins/paste.js'][277] = 0; + _$jscoverage['plugins/paste.js'][278] = 0; +} +_$jscoverage['plugins/paste.js'].source = ["///import core","///import plugins/inserthtml.js","///import plugins/undo.js","///import plugins/serialize.js","///commands 粘贴","///commandsName PastePlain","///commandsTitle 纯文本粘贴模式","/*"," ** @description 粘贴"," * @author zhanyi"," */","UE.plugins['paste'] = function () {"," function getClipboardData(callback) {"," var doc = this.document;"," if (doc.getElementById('baidu_pastebin')) {"," return;"," }"," var range = this.selection.getRange(),"," bk = range.createBookmark(),"," //创建剪贴的容器div"," pastebin = doc.createElement('div');"," pastebin.id = 'baidu_pastebin';"," // Safari 要求div必须有内容,才能粘贴内容进来"," browser.webkit && pastebin.appendChild(doc.createTextNode(domUtils.fillChar + domUtils.fillChar));"," doc.body.appendChild(pastebin);"," //trace:717 隐藏的span不能得到top"," //bk.start.innerHTML = '&nbsp;';"," bk.start.style.display = '';"," pastebin.style.cssText = \"position:absolute;width:1px;height:1px;overflow:hidden;left:-1000px;white-space:nowrap;top:\" +"," //要在现在光标平行的位置加入,否则会出现跳动的问题"," domUtils.getXY(bk.start).y + 'px';",""," range.selectNodeContents(pastebin).select(true);",""," setTimeout(function () {"," if (browser.webkit) {"," for (var i = 0, pastebins = doc.querySelectorAll('#baidu_pastebin'), pi; pi = pastebins[i++];) {"," if (domUtils.isEmptyNode(pi)) {"," domUtils.remove(pi);"," } else {"," pastebin = pi;"," break;"," }"," }"," }"," try {"," pastebin.parentNode.removeChild(pastebin);"," } catch (e) {"," }"," range.moveToBookmark(bk).select(true);"," callback(pastebin);"," }, 0);"," }",""," var me = this;",""," var txtContent, htmlContent, address;",""," function filter(div) {"," var html;"," if (div.firstChild) {"," //去掉cut中添加的边界值"," var nodes = domUtils.getElementsByTagName(div, 'span');"," for (var i = 0, ni; ni = nodes[i++];) {"," if (ni.id == '_baidu_cut_start' || ni.id == '_baidu_cut_end') {"," domUtils.remove(ni);"," }"," }",""," if (browser.webkit) {",""," var brs = div.querySelectorAll('div br');"," for (var i = 0, bi; bi = brs[i++];) {"," var pN = bi.parentNode;"," if (pN.tagName == 'DIV' && pN.childNodes.length == 1) {"," pN.innerHTML = '<p><br/></p>';"," domUtils.remove(pN);"," }"," }"," var divs = div.querySelectorAll('#baidu_pastebin');"," for (var i = 0, di; di = divs[i++];) {"," var tmpP = me.document.createElement('p');"," di.parentNode.insertBefore(tmpP, di);"," while (di.firstChild) {"," tmpP.appendChild(di.firstChild);"," }"," domUtils.remove(di);"," }",""," var metas = div.querySelectorAll('meta');"," for (var i = 0, ci; ci = metas[i++];) {"," domUtils.remove(ci);"," }",""," var brs = div.querySelectorAll('br');"," for (i = 0; ci = brs[i++];) {"," if (/^apple-/i.test(ci.className)) {"," domUtils.remove(ci);"," }"," }"," }"," if (browser.gecko) {"," var dirtyNodes = div.querySelectorAll('[_moz_dirty]');"," for (i = 0; ci = dirtyNodes[i++];) {"," ci.removeAttribute('_moz_dirty');"," }"," }"," if (!browser.ie) {"," var spans = div.querySelectorAll('span.Apple-style-span');"," for (var i = 0, ci; ci = spans[i++];) {"," domUtils.remove(ci, true);"," }"," }",""," //ie下使用innerHTML会产生多余的\\r\\n字符,也会产生&nbsp;这里过滤掉"," html = div.innerHTML;//.replace(/>(?:(\\s|&nbsp;)*?)</g,'><');",""," //过滤word粘贴过来的冗余属性"," html = UE.filterWord(html);"," //取消了忽略空白的第二个参数,粘贴过来的有些是有空白的,会被套上相关的标签"," var root = UE.htmlparser(html);"," //如果给了过滤规则就先进行过滤"," if (me.options.filterRules) {"," UE.filterNode(root, me.options.filterRules);"," }"," //执行默认的处理"," me.filterInputRule(root);"," //针对chrome的处理"," if (browser.webkit) {"," var br = root.lastChild();"," if (br && br.type == 'element' && br.tagName == 'br') {"," root.removeChild(br)"," }"," utils.each(me.body.querySelectorAll('div'), function (node) {"," if (domUtils.isEmptyBlock(node)) {"," domUtils.remove(node)"," }"," })"," }"," html = {'html': root.toHtml()};"," me.fireEvent('beforepaste', html, root);"," //抢了默认的粘贴,那后边的内容就不执行了,比如表格粘贴"," if(!html.html){"," return;"," }"," root = UE.htmlparser(html.html,true);"," //如果开启了纯文本模式"," if (me.queryCommandState('pasteplain') === 1) {"," me.execCommand('insertHtml', UE.filterNode(root, me.options.filterTxtRules).toHtml(), true);"," } else {"," //文本模式"," UE.filterNode(root, me.options.filterTxtRules);"," txtContent = root.toHtml();"," //完全模式"," htmlContent = html.html;",""," address = me.selection.getRange().createAddress(true);"," me.execCommand('insertHtml', htmlContent, true);"," }"," me.fireEvent(\"afterpaste\", html);"," }"," }",""," me.addListener('pasteTransfer', function (cmd, plainType) {",""," if (address && txtContent && htmlContent && txtContent != htmlContent) {"," var range = me.selection.getRange();"," range.moveToAddress(address, true);",""," if (!range.collapsed) {",""," while (!domUtils.isBody(range.startContainer)"," ) {"," var start = range.startContainer;"," if(start.nodeType == 1){"," start = start.childNodes[range.startOffset];"," if(!start){"," range.setStartBefore(range.startContainer);"," continue;"," }"," var pre = start.previousSibling;",""," if(pre && pre.nodeType == 3 && new RegExp('^[\\n\\r\\t '+domUtils.fillChar+']*$').test(pre.nodeValue)){"," range.setStartBefore(pre)"," }"," }"," if(range.startOffset == 0){"," range.setStartBefore(range.startContainer);"," }else{"," break;"," }",""," }"," while (!domUtils.isBody(range.endContainer)"," ) {"," var end = range.endContainer;"," if(end.nodeType == 1){"," end = end.childNodes[range.endOffset];"," if(!end){"," range.setEndAfter(range.endContainer);"," continue;"," }"," var next = end.nextSibling;"," if(next && next.nodeType == 3 && new RegExp('^[\\n\\r\\t'+domUtils.fillChar+']*$').test(next.nodeValue)){"," range.setEndAfter(next)"," }"," }"," if(range.endOffset == range.endContainer[range.endContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length){"," range.setEndAfter(range.endContainer);"," }else{"," break;"," }",""," }",""," }",""," range.deleteContents();"," range.select(true);"," me.__hasEnterExecCommand = true;"," var html = htmlContent;"," if (plainType === 2) {"," html = html.replace(/<(\\/?)([\\w\\-]+)([^>]*)>/gi, function (a, b, tagName, attrs) {"," tagName = tagName.toLowerCase();"," if ({img: 1}[tagName]) {"," return a;"," }"," attrs = attrs.replace(/([\\w\\-]*?)\\s*=\\s*((\"([^\"]*)\")|('([^']*)')|([^\\s>]+))/gi, function (str, atr, val) {"," if ({"," 'src': 1,"," 'href': 1,"," 'name': 1"," }[atr.toLowerCase()]) {"," return atr + '=' + val + ' '"," }"," return ''"," });"," if ({"," 'span': 1,"," 'div': 1"," }[tagName]) {"," return ''"," } else {",""," return '<' + b + tagName + ' ' + utils.trim(attrs) + '>'"," }",""," });"," } else if (plainType) {"," html = txtContent;"," }"," me.execCommand('inserthtml', html, true);"," me.__hasEnterExecCommand = false;"," var rng = me.selection.getRange();"," while (!domUtils.isBody(rng.startContainer) && !rng.startOffset &&"," rng.startContainer[rng.startContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length"," ) {"," rng.setStartBefore(rng.startContainer);"," }"," var tmpAddress = rng.createAddress(true);"," address.endAddress = tmpAddress.startAddress;"," }"," });"," me.addListener('ready', function () {"," domUtils.on(me.body, 'cut', function () {"," var range = me.selection.getRange();"," if (!range.collapsed && me.undoManger) {"," me.undoManger.save();"," }"," });",""," //ie下beforepaste在点击右键时也会触发,所以用监控键盘才处理"," domUtils.on(me.body, browser.ie || browser.opera ? 'keydown' : 'paste', function (e) {"," if ((browser.ie || browser.opera) && ((!e.ctrlKey && !e.metaKey) || e.keyCode != '86')) {"," return;"," }"," getClipboardData.call(me, function (div) {"," filter(div);"," });"," });",""," });","};",""]; +_$jscoverage['plugins/paste.js'][12]++; +UE.plugins.paste = (function () { + _$jscoverage['plugins/paste.js'][13]++; + function getClipboardData(callback) { + _$jscoverage['plugins/paste.js'][14]++; + var doc = this.document; + _$jscoverage['plugins/paste.js'][15]++; + if (doc.getElementById("baidu_pastebin")) { + _$jscoverage['plugins/paste.js'][16]++; + return; + } + _$jscoverage['plugins/paste.js'][18]++; + var range = this.selection.getRange(), bk = range.createBookmark(), pastebin = doc.createElement("div"); + _$jscoverage['plugins/paste.js'][22]++; + pastebin.id = "baidu_pastebin"; + _$jscoverage['plugins/paste.js'][24]++; + (browser.webkit && pastebin.appendChild(doc.createTextNode((domUtils.fillChar + domUtils.fillChar)))); + _$jscoverage['plugins/paste.js'][25]++; + doc.body.appendChild(pastebin); + _$jscoverage['plugins/paste.js'][28]++; + bk.start.style.display = ""; + _$jscoverage['plugins/paste.js'][29]++; + pastebin.style.cssText = ("position:absolute;width:1px;height:1px;overflow:hidden;left:-1000px;white-space:nowrap;top:" + domUtils.getXY(bk.start).y + "px"); + _$jscoverage['plugins/paste.js'][33]++; + range.selectNodeContents(pastebin).select(true); + _$jscoverage['plugins/paste.js'][35]++; + setTimeout((function () { + _$jscoverage['plugins/paste.js'][36]++; + if (browser.webkit) { + _$jscoverage['plugins/paste.js'][37]++; + for (var i = 0, pastebins = doc.querySelectorAll("#baidu_pastebin"), pi; (pi = pastebins[(i++)]);) { + _$jscoverage['plugins/paste.js'][38]++; + if (domUtils.isEmptyNode(pi)) { + _$jscoverage['plugins/paste.js'][39]++; + domUtils.remove(pi); + } + else { + _$jscoverage['plugins/paste.js'][41]++; + pastebin = pi; + _$jscoverage['plugins/paste.js'][42]++; + break; + } +} + } + _$jscoverage['plugins/paste.js'][46]++; + try { + _$jscoverage['plugins/paste.js'][47]++; + pastebin.parentNode.removeChild(pastebin); + } + catch (e) { + } + _$jscoverage['plugins/paste.js'][50]++; + range.moveToBookmark(bk).select(true); + _$jscoverage['plugins/paste.js'][51]++; + callback(pastebin); +}), 0); +} + _$jscoverage['plugins/paste.js'][55]++; + var me = this; + _$jscoverage['plugins/paste.js'][57]++; + var txtContent, htmlContent, address; + _$jscoverage['plugins/paste.js'][59]++; + function filter(div) { + _$jscoverage['plugins/paste.js'][60]++; + var html; + _$jscoverage['plugins/paste.js'][61]++; + if (div.firstChild) { + _$jscoverage['plugins/paste.js'][63]++; + var nodes = domUtils.getElementsByTagName(div, "span"); + _$jscoverage['plugins/paste.js'][64]++; + for (var i = 0, ni; (ni = nodes[(i++)]);) { + _$jscoverage['plugins/paste.js'][65]++; + if (((ni.id == "_baidu_cut_start") || (ni.id == "_baidu_cut_end"))) { + _$jscoverage['plugins/paste.js'][66]++; + domUtils.remove(ni); + } +} + _$jscoverage['plugins/paste.js'][70]++; + if (browser.webkit) { + _$jscoverage['plugins/paste.js'][72]++; + var brs = div.querySelectorAll("div br"); + _$jscoverage['plugins/paste.js'][73]++; + for (var i = 0, bi; (bi = brs[(i++)]);) { + _$jscoverage['plugins/paste.js'][74]++; + var pN = bi.parentNode; + _$jscoverage['plugins/paste.js'][75]++; + if (((pN.tagName == "DIV") && (pN.childNodes.length == 1))) { + _$jscoverage['plugins/paste.js'][76]++; + pN.innerHTML = "


    "; + _$jscoverage['plugins/paste.js'][77]++; + domUtils.remove(pN); + } +} + _$jscoverage['plugins/paste.js'][80]++; + var divs = div.querySelectorAll("#baidu_pastebin"); + _$jscoverage['plugins/paste.js'][81]++; + for (var i = 0, di; (di = divs[(i++)]);) { + _$jscoverage['plugins/paste.js'][82]++; + var tmpP = me.document.createElement("p"); + _$jscoverage['plugins/paste.js'][83]++; + di.parentNode.insertBefore(tmpP, di); + _$jscoverage['plugins/paste.js'][84]++; + while (di.firstChild) { + _$jscoverage['plugins/paste.js'][85]++; + tmpP.appendChild(di.firstChild); +} + _$jscoverage['plugins/paste.js'][87]++; + domUtils.remove(di); +} + _$jscoverage['plugins/paste.js'][90]++; + var metas = div.querySelectorAll("meta"); + _$jscoverage['plugins/paste.js'][91]++; + for (var i = 0, ci; (ci = metas[(i++)]);) { + _$jscoverage['plugins/paste.js'][92]++; + domUtils.remove(ci); +} + _$jscoverage['plugins/paste.js'][95]++; + var brs = div.querySelectorAll("br"); + _$jscoverage['plugins/paste.js'][96]++; + for (i = 0; (ci = brs[(i++)]);) { + _$jscoverage['plugins/paste.js'][97]++; + if (/^apple-/i.test(ci.className)) { + _$jscoverage['plugins/paste.js'][98]++; + domUtils.remove(ci); + } +} + } + _$jscoverage['plugins/paste.js'][102]++; + if (browser.gecko) { + _$jscoverage['plugins/paste.js'][103]++; + var dirtyNodes = div.querySelectorAll("[_moz_dirty]"); + _$jscoverage['plugins/paste.js'][104]++; + for (i = 0; (ci = dirtyNodes[(i++)]);) { + _$jscoverage['plugins/paste.js'][105]++; + ci.removeAttribute("_moz_dirty"); +} + } + _$jscoverage['plugins/paste.js'][108]++; + if ((! browser.ie)) { + _$jscoverage['plugins/paste.js'][109]++; + var spans = div.querySelectorAll("span.Apple-style-span"); + _$jscoverage['plugins/paste.js'][110]++; + for (var i = 0, ci = ci; (ci = spans[(i++)]);) { + _$jscoverage['plugins/paste.js'][111]++; + domUtils.remove(ci, true); +} + } + _$jscoverage['plugins/paste.js'][116]++; + html = div.innerHTML; + _$jscoverage['plugins/paste.js'][119]++; + html = UE.filterWord(html); + _$jscoverage['plugins/paste.js'][121]++; + var root = UE.htmlparser(html); + _$jscoverage['plugins/paste.js'][123]++; + if (me.options.filterRules) { + _$jscoverage['plugins/paste.js'][124]++; + UE.filterNode(root, me.options.filterRules); + } + _$jscoverage['plugins/paste.js'][127]++; + me.filterInputRule(root); + _$jscoverage['plugins/paste.js'][129]++; + if (browser.webkit) { + _$jscoverage['plugins/paste.js'][130]++; + var br = root.lastChild(); + _$jscoverage['plugins/paste.js'][131]++; + if ((br && (br.type == "element") && (br.tagName == "br"))) { + _$jscoverage['plugins/paste.js'][132]++; + root.removeChild(br); + } + _$jscoverage['plugins/paste.js'][134]++; + utils.each(me.body.querySelectorAll("div"), (function (node) { + _$jscoverage['plugins/paste.js'][135]++; + if (domUtils.isEmptyBlock(node)) { + _$jscoverage['plugins/paste.js'][136]++; + domUtils.remove(node); + } +})); + } + _$jscoverage['plugins/paste.js'][140]++; + html = {"html": root.toHtml()}; + _$jscoverage['plugins/paste.js'][141]++; + me.fireEvent("beforepaste", html, root); + _$jscoverage['plugins/paste.js'][143]++; + if ((! html.html)) { + _$jscoverage['plugins/paste.js'][144]++; + return; + } + _$jscoverage['plugins/paste.js'][146]++; + root = UE.htmlparser(html.html, true); + _$jscoverage['plugins/paste.js'][148]++; + if ((me.queryCommandState("pasteplain") === 1)) { + _$jscoverage['plugins/paste.js'][149]++; + me.execCommand("insertHtml", UE.filterNode(root, me.options.filterTxtRules).toHtml(), true); + } + else { + _$jscoverage['plugins/paste.js'][152]++; + UE.filterNode(root, me.options.filterTxtRules); + _$jscoverage['plugins/paste.js'][153]++; + txtContent = root.toHtml(); + _$jscoverage['plugins/paste.js'][155]++; + htmlContent = html.html; + _$jscoverage['plugins/paste.js'][157]++; + address = me.selection.getRange().createAddress(true); + _$jscoverage['plugins/paste.js'][158]++; + me.execCommand("insertHtml", htmlContent, true); + } + _$jscoverage['plugins/paste.js'][160]++; + me.fireEvent("afterpaste", html); + } +} + _$jscoverage['plugins/paste.js'][164]++; + me.addListener("pasteTransfer", (function (cmd, plainType) { + _$jscoverage['plugins/paste.js'][166]++; + if ((address && txtContent && htmlContent && (txtContent != htmlContent))) { + _$jscoverage['plugins/paste.js'][167]++; + var range = me.selection.getRange(); + _$jscoverage['plugins/paste.js'][168]++; + range.moveToAddress(address, true); + _$jscoverage['plugins/paste.js'][170]++; + if ((! range.collapsed)) { + _$jscoverage['plugins/paste.js'][172]++; + while ((! domUtils.isBody(range.startContainer))) { + _$jscoverage['plugins/paste.js'][174]++; + var start = range.startContainer; + _$jscoverage['plugins/paste.js'][175]++; + if ((start.nodeType == 1)) { + _$jscoverage['plugins/paste.js'][176]++; + start = start.childNodes[range.startOffset]; + _$jscoverage['plugins/paste.js'][177]++; + if ((! start)) { + _$jscoverage['plugins/paste.js'][178]++; + range.setStartBefore(range.startContainer); + _$jscoverage['plugins/paste.js'][179]++; + continue; + } + _$jscoverage['plugins/paste.js'][181]++; + var pre = start.previousSibling; + _$jscoverage['plugins/paste.js'][183]++; + if ((pre && (pre.nodeType == 3) && new RegExp(("^[\n\r\t " + domUtils.fillChar + "]*$")).test(pre.nodeValue))) { + _$jscoverage['plugins/paste.js'][184]++; + range.setStartBefore(pre); + } + } + _$jscoverage['plugins/paste.js'][187]++; + if ((range.startOffset == 0)) { + _$jscoverage['plugins/paste.js'][188]++; + range.setStartBefore(range.startContainer); + } + else { + _$jscoverage['plugins/paste.js'][190]++; + break; + } +} + _$jscoverage['plugins/paste.js'][194]++; + while ((! domUtils.isBody(range.endContainer))) { + _$jscoverage['plugins/paste.js'][196]++; + var end = range.endContainer; + _$jscoverage['plugins/paste.js'][197]++; + if ((end.nodeType == 1)) { + _$jscoverage['plugins/paste.js'][198]++; + end = end.childNodes[range.endOffset]; + _$jscoverage['plugins/paste.js'][199]++; + if ((! end)) { + _$jscoverage['plugins/paste.js'][200]++; + range.setEndAfter(range.endContainer); + _$jscoverage['plugins/paste.js'][201]++; + continue; + } + _$jscoverage['plugins/paste.js'][203]++; + var next = end.nextSibling; + _$jscoverage['plugins/paste.js'][204]++; + if ((next && (next.nodeType == 3) && new RegExp(("^[\n\r\t" + domUtils.fillChar + "]*$")).test(next.nodeValue))) { + _$jscoverage['plugins/paste.js'][205]++; + range.setEndAfter(next); + } + } + _$jscoverage['plugins/paste.js'][208]++; + if ((range.endOffset == range.endContainer[((range.endContainer.nodeType == 3)? "nodeValue": "childNodes")].length)) { + _$jscoverage['plugins/paste.js'][209]++; + range.setEndAfter(range.endContainer); + } + else { + _$jscoverage['plugins/paste.js'][211]++; + break; + } +} + } + _$jscoverage['plugins/paste.js'][218]++; + range.deleteContents(); + _$jscoverage['plugins/paste.js'][219]++; + range.select(true); + _$jscoverage['plugins/paste.js'][220]++; + me.__hasEnterExecCommand = true; + _$jscoverage['plugins/paste.js'][221]++; + var html = htmlContent; + _$jscoverage['plugins/paste.js'][222]++; + if ((plainType === 2)) { + _$jscoverage['plugins/paste.js'][223]++; + html = html.replace(/<(\/?)([\w\-]+)([^>]*)>/gi, (function (a, b, tagName, attrs) { + _$jscoverage['plugins/paste.js'][224]++; + tagName = tagName.toLowerCase(); + _$jscoverage['plugins/paste.js'][225]++; + if ({img: 1}[tagName]) { + _$jscoverage['plugins/paste.js'][226]++; + return a; + } + _$jscoverage['plugins/paste.js'][228]++; + attrs = attrs.replace(/([\w\-]*?)\s*=\s*(("([^"]*)")|('([^']*)')|([^\s>]+))/gi, (function (str, atr, val) { + _$jscoverage['plugins/paste.js'][229]++; + if ({"src": 1, "href": 1, "name": 1}[atr.toLowerCase()]) { + _$jscoverage['plugins/paste.js'][234]++; + return (atr + "=" + val + " "); + } + _$jscoverage['plugins/paste.js'][236]++; + return ""; +})); + _$jscoverage['plugins/paste.js'][238]++; + if ({"span": 1, "div": 1}[tagName]) { + _$jscoverage['plugins/paste.js'][242]++; + return ""; + } + else { + _$jscoverage['plugins/paste.js'][245]++; + return ("<" + b + tagName + " " + utils.trim(attrs) + ">"); + } +})); + } + else { + _$jscoverage['plugins/paste.js'][249]++; + if (plainType) { + _$jscoverage['plugins/paste.js'][250]++; + html = txtContent; + } + } + _$jscoverage['plugins/paste.js'][252]++; + me.execCommand("inserthtml", html, true); + _$jscoverage['plugins/paste.js'][253]++; + me.__hasEnterExecCommand = false; + _$jscoverage['plugins/paste.js'][254]++; + var rng = me.selection.getRange(); + _$jscoverage['plugins/paste.js'][255]++; + while (((! domUtils.isBody(rng.startContainer)) && (! rng.startOffset) && rng.startContainer[((rng.startContainer.nodeType == 3)? "nodeValue": "childNodes")].length)) { + _$jscoverage['plugins/paste.js'][258]++; + rng.setStartBefore(rng.startContainer); +} + _$jscoverage['plugins/paste.js'][260]++; + var tmpAddress = rng.createAddress(true); + _$jscoverage['plugins/paste.js'][261]++; + address.endAddress = tmpAddress.startAddress; + } +})); + _$jscoverage['plugins/paste.js'][264]++; + me.addListener("ready", (function () { + _$jscoverage['plugins/paste.js'][265]++; + domUtils.on(me.body, "cut", (function () { + _$jscoverage['plugins/paste.js'][266]++; + var range = me.selection.getRange(); + _$jscoverage['plugins/paste.js'][267]++; + if (((! range.collapsed) && me.undoManger)) { + _$jscoverage['plugins/paste.js'][268]++; + me.undoManger.save(); + } +})); + _$jscoverage['plugins/paste.js'][273]++; + domUtils.on(me.body, ((browser.ie || browser.opera)? "keydown": "paste"), (function (e) { + _$jscoverage['plugins/paste.js'][274]++; + if (((browser.ie || browser.opera) && (((! e.ctrlKey) && (! e.metaKey)) || (e.keyCode != "86")))) { + _$jscoverage['plugins/paste.js'][275]++; + return; + } + _$jscoverage['plugins/paste.js'][277]++; + getClipboardData.call(me, (function (div) { + _$jscoverage['plugins/paste.js'][278]++; + filter(div); +})); +})); +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/preview.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/preview.js new file mode 100644 index 000000000..4612b2bba --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/preview.js @@ -0,0 +1,59 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/preview.js']) { + _$jscoverage['plugins/preview.js'] = []; + _$jscoverage['plugins/preview.js'][17] = 0; + _$jscoverage['plugins/preview.js'][19] = 0; + _$jscoverage['plugins/preview.js'][21] = 0; + _$jscoverage['plugins/preview.js'][22] = 0; + _$jscoverage['plugins/preview.js'][28] = 0; +} +_$jscoverage['plugins/preview.js'].source = ["/**"," * 预览"," * @file"," * @since 1.2.6.1"," */","","/**"," * 预览"," * @command preview"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'preview' );"," * ```"," */","UE.commands['preview'] = {"," execCommand : function(){"," var w = window.open('', '_blank', ''),"," d = w.document;"," d.open();"," d.write('<html><head><script src=\"'+this.options.UEDITOR_HOME_URL+'ueditor.parse.js\"></script><script>' +"," \"setTimeout(function(){uParse('div',{\" +"," \" 'highlightJsUrl':'\"+this.options.UEDITOR_HOME_URL+\"third-party/SyntaxHighlighter/shCore.js',\" +"," \" 'highlightCssUrl':'\"+this.options.UEDITOR_HOME_URL+\"third-party/SyntaxHighlighter/shCoreDefault.css'\" +"," \"})},300)\" +"," '</script></head><body><div>'+this.getContent(null,null,true)+'</div></body></html>');"," d.close();"," },"," notNeedUndo : 1","};"]; +_$jscoverage['plugins/preview.js'][17]++; +UE.commands.preview = {execCommand: (function () { + _$jscoverage['plugins/preview.js'][19]++; + var w = window.open("", "_blank", ""), d = w.document; + _$jscoverage['plugins/preview.js'][21]++; + d.open(); + _$jscoverage['plugins/preview.js'][22]++; + d.write(("
    " + this.getContent(null, null, true) + "
    ")); + _$jscoverage['plugins/preview.js'][28]++; + d.close(); +}), notNeedUndo: 1}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/print.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/print.js new file mode 100644 index 000000000..da94c1bb2 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/print.js @@ -0,0 +1,50 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/print.js']) { + _$jscoverage['plugins/print.js'] = []; + _$jscoverage['plugins/print.js'][17] = 0; + _$jscoverage['plugins/print.js'][19] = 0; +} +_$jscoverage['plugins/print.js'].source = ["/**"," * 打印"," * @file"," * @since 1.2.6.1"," */","","/**"," * 打印"," * @command print"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'print' );"," * ```"," */","UE.commands['print'] = {"," execCommand : function(){"," this.window.print();"," },"," notNeedUndo : 1","};",""]; +_$jscoverage['plugins/print.js'][17]++; +UE.commands.print = {execCommand: (function () { + _$jscoverage['plugins/print.js'][19]++; + this.window.print(); +}), notNeedUndo: 1}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/puretxtpaste.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/puretxtpaste.js new file mode 100644 index 000000000..cc8fe4e0a --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/puretxtpaste.js @@ -0,0 +1,144 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/puretxtpaste.js']) { + _$jscoverage['plugins/puretxtpaste.js'] = []; + _$jscoverage['plugins/puretxtpaste.js'][7] = 0; + _$jscoverage['plugins/puretxtpaste.js'][8] = 0; + _$jscoverage['plugins/puretxtpaste.js'][9] = 0; + _$jscoverage['plugins/puretxtpaste.js'][12] = 0; + _$jscoverage['plugins/puretxtpaste.js'][13] = 0; + _$jscoverage['plugins/puretxtpaste.js'][14] = 0; + _$jscoverage['plugins/puretxtpaste.js'][16] = 0; + _$jscoverage['plugins/puretxtpaste.js'][17] = 0; + _$jscoverage['plugins/puretxtpaste.js'][19] = 0; + _$jscoverage['plugins/puretxtpaste.js'][25] = 0; + _$jscoverage['plugins/puretxtpaste.js'][26] = 0; + _$jscoverage['plugins/puretxtpaste.js'][27] = 0; + _$jscoverage['plugins/puretxtpaste.js'][28] = 0; + _$jscoverage['plugins/puretxtpaste.js'][30] = 0; + _$jscoverage['plugins/puretxtpaste.js'][31] = 0; + _$jscoverage['plugins/puretxtpaste.js'][32] = 0; + _$jscoverage['plugins/puretxtpaste.js'][34] = 0; + _$jscoverage['plugins/puretxtpaste.js'][38] = 0; + _$jscoverage['plugins/puretxtpaste.js'][39] = 0; + _$jscoverage['plugins/puretxtpaste.js'][41] = 0; + _$jscoverage['plugins/puretxtpaste.js'][55] = 0; + _$jscoverage['plugins/puretxtpaste.js'][56] = 0; + _$jscoverage['plugins/puretxtpaste.js'][57] = 0; + _$jscoverage['plugins/puretxtpaste.js'][59] = 0; + _$jscoverage['plugins/puretxtpaste.js'][65] = 0; + _$jscoverage['plugins/puretxtpaste.js'][89] = 0; + _$jscoverage['plugins/puretxtpaste.js'][91] = 0; + _$jscoverage['plugins/puretxtpaste.js'][94] = 0; +} +_$jscoverage['plugins/puretxtpaste.js'].source = ["/**"," * 纯文本粘贴插件"," * @file"," * @since 1.2.6.1"," */","","UE.plugins['pasteplain'] = function(){"," var me = this;"," me.setOpt({"," 'pasteplain':false,"," 'filterTxtRules' : function(){"," function transP(node){"," node.tagName = 'p';"," node.setStyle();"," }"," function removeNode(node){"," node.parentNode.removeChild(node,true)"," }"," return {"," //直接删除及其字节点内容"," '-' : 'script style object iframe embed input select',"," 'p': {$:{}},"," 'br':{$:{}},"," div: function (node) {"," var tmpNode, p = UE.uNode.createElement('p');"," while (tmpNode = node.firstChild()) {"," if (tmpNode.type == 'text' || !UE.dom.dtd.$block[tmpNode.tagName]) {"," p.appendChild(tmpNode);"," } else {"," if (p.firstChild()) {"," node.parentNode.insertBefore(p, node);"," p = UE.uNode.createElement('p');"," } else {"," node.parentNode.insertBefore(tmpNode, node);"," }"," }"," }"," if (p.firstChild()) {"," node.parentNode.insertBefore(p, node);"," }"," node.parentNode.removeChild(node);"," },"," ol: removeNode,"," ul: removeNode,"," dl:removeNode,"," dt:removeNode,"," dd:removeNode,"," 'li':removeNode,"," 'caption':transP,"," 'th':transP,"," 'tr':transP,"," 'h1':transP,'h2':transP,'h3':transP,'h4':transP,'h5':transP,'h6':transP,"," 'td':function(node){"," //没有内容的td直接删掉"," var txt = !!node.innerText();"," if(txt){"," node.parentNode.insertAfter(UE.uNode.createText(' &nbsp; &nbsp;'),node);"," }"," node.parentNode.removeChild(node,node.innerText())"," }"," }"," }()"," });"," //暂时这里支持一下老版本的属性"," var pasteplain = me.options.pasteplain;",""," /**"," * 启用或取消纯文本粘贴模式"," * @command pasteplain"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.queryCommandState( 'pasteplain' );"," * ```"," */",""," /**"," * 查询当前是否处于纯文本粘贴模式"," * @command pasteplain"," * @method queryCommandState"," * @param { String } cmd 命令字符串"," * @return { int } 如果处于纯文本模式,返回1,否则,返回0"," * @example"," * ```javascript"," * editor.queryCommandState( 'pasteplain' );"," * ```"," */"," me.commands['pasteplain'] = {"," queryCommandState: function (){"," return pasteplain ? 1 : 0;"," },"," execCommand: function (){"," pasteplain = !pasteplain|0;"," },"," notNeedUndo : 1"," };","};"]; +_$jscoverage['plugins/puretxtpaste.js'][7]++; +UE.plugins.pasteplain = (function () { + _$jscoverage['plugins/puretxtpaste.js'][8]++; + var me = this; + _$jscoverage['plugins/puretxtpaste.js'][9]++; + me.setOpt({"pasteplain": false, "filterTxtRules": (function () { + _$jscoverage['plugins/puretxtpaste.js'][12]++; + function transP(node) { + _$jscoverage['plugins/puretxtpaste.js'][13]++; + node.tagName = "p"; + _$jscoverage['plugins/puretxtpaste.js'][14]++; + node.setStyle(); +} + _$jscoverage['plugins/puretxtpaste.js'][16]++; + function removeNode(node) { + _$jscoverage['plugins/puretxtpaste.js'][17]++; + node.parentNode.removeChild(node, true); +} + _$jscoverage['plugins/puretxtpaste.js'][19]++; + return ({"-": "script style object iframe embed input select", "p": {$: {}}, "br": {$: {}}, div: (function (node) { + _$jscoverage['plugins/puretxtpaste.js'][25]++; + var tmpNode, p = UE.uNode.createElement("p"); + _$jscoverage['plugins/puretxtpaste.js'][26]++; + while ((tmpNode = node.firstChild())) { + _$jscoverage['plugins/puretxtpaste.js'][27]++; + if (((tmpNode.type == "text") || (! UE.dom.dtd.$block[tmpNode.tagName]))) { + _$jscoverage['plugins/puretxtpaste.js'][28]++; + p.appendChild(tmpNode); + } + else { + _$jscoverage['plugins/puretxtpaste.js'][30]++; + if (p.firstChild()) { + _$jscoverage['plugins/puretxtpaste.js'][31]++; + node.parentNode.insertBefore(p, node); + _$jscoverage['plugins/puretxtpaste.js'][32]++; + p = UE.uNode.createElement("p"); + } + else { + _$jscoverage['plugins/puretxtpaste.js'][34]++; + node.parentNode.insertBefore(tmpNode, node); + } + } +} + _$jscoverage['plugins/puretxtpaste.js'][38]++; + if (p.firstChild()) { + _$jscoverage['plugins/puretxtpaste.js'][39]++; + node.parentNode.insertBefore(p, node); + } + _$jscoverage['plugins/puretxtpaste.js'][41]++; + node.parentNode.removeChild(node); +}), ol: removeNode, ul: removeNode, dl: removeNode, dt: removeNode, dd: removeNode, "li": removeNode, "caption": transP, "th": transP, "tr": transP, "h1": transP, "h2": transP, "h3": transP, "h4": transP, "h5": transP, "h6": transP, "td": (function (node) { + _$jscoverage['plugins/puretxtpaste.js'][55]++; + var txt = (! (! node.innerText())); + _$jscoverage['plugins/puretxtpaste.js'][56]++; + if (txt) { + _$jscoverage['plugins/puretxtpaste.js'][57]++; + node.parentNode.insertAfter(UE.uNode.createText("    "), node); + } + _$jscoverage['plugins/puretxtpaste.js'][59]++; + node.parentNode.removeChild(node, node.innerText()); +})}); +})()}); + _$jscoverage['plugins/puretxtpaste.js'][65]++; + var pasteplain = me.options.pasteplain; + _$jscoverage['plugins/puretxtpaste.js'][89]++; + me.commands.pasteplain = {queryCommandState: (function () { + _$jscoverage['plugins/puretxtpaste.js'][91]++; + return (pasteplain? 1: 0); +}), execCommand: (function () { + _$jscoverage['plugins/puretxtpaste.js'][94]++; + pasteplain = ((! pasteplain) | 0); +}), notNeedUndo: 1}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/removeformat.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/removeformat.js new file mode 100644 index 000000000..c13eaaf8d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/removeformat.js @@ -0,0 +1,318 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/removeformat.js']) { + _$jscoverage['plugins/removeformat.js'] = []; + _$jscoverage['plugins/removeformat.js'][22] = 0; + _$jscoverage['plugins/removeformat.js'][23] = 0; + _$jscoverage['plugins/removeformat.js'][24] = 0; + _$jscoverage['plugins/removeformat.js'][28] = 0; + _$jscoverage['plugins/removeformat.js'][31] = 0; + _$jscoverage['plugins/removeformat.js'][36] = 0; + _$jscoverage['plugins/removeformat.js'][39] = 0; + _$jscoverage['plugins/removeformat.js'][40] = 0; + _$jscoverage['plugins/removeformat.js'][41] = 0; + _$jscoverage['plugins/removeformat.js'][43] = 0; + _$jscoverage['plugins/removeformat.js'][46] = 0; + _$jscoverage['plugins/removeformat.js'][47] = 0; + _$jscoverage['plugins/removeformat.js'][48] = 0; + _$jscoverage['plugins/removeformat.js'][49] = 0; + _$jscoverage['plugins/removeformat.js'][50] = 0; + _$jscoverage['plugins/removeformat.js'][53] = 0; + _$jscoverage['plugins/removeformat.js'][56] = 0; + _$jscoverage['plugins/removeformat.js'][58] = 0; + _$jscoverage['plugins/removeformat.js'][60] = 0; + _$jscoverage['plugins/removeformat.js'][61] = 0; + _$jscoverage['plugins/removeformat.js'][62] = 0; + _$jscoverage['plugins/removeformat.js'][66] = 0; + _$jscoverage['plugins/removeformat.js'][67] = 0; + _$jscoverage['plugins/removeformat.js'][68] = 0; + _$jscoverage['plugins/removeformat.js'][69] = 0; + _$jscoverage['plugins/removeformat.js'][72] = 0; + _$jscoverage['plugins/removeformat.js'][73] = 0; + _$jscoverage['plugins/removeformat.js'][74] = 0; + _$jscoverage['plugins/removeformat.js'][80] = 0; + _$jscoverage['plugins/removeformat.js'][82] = 0; + _$jscoverage['plugins/removeformat.js'][85] = 0; + _$jscoverage['plugins/removeformat.js'][86] = 0; + _$jscoverage['plugins/removeformat.js'][88] = 0; + _$jscoverage['plugins/removeformat.js'][90] = 0; + _$jscoverage['plugins/removeformat.js'][92] = 0; + _$jscoverage['plugins/removeformat.js'][93] = 0; + _$jscoverage['plugins/removeformat.js'][94] = 0; + _$jscoverage['plugins/removeformat.js'][95] = 0; + _$jscoverage['plugins/removeformat.js'][99] = 0; + _$jscoverage['plugins/removeformat.js'][101] = 0; + _$jscoverage['plugins/removeformat.js'][102] = 0; + _$jscoverage['plugins/removeformat.js'][103] = 0; + _$jscoverage['plugins/removeformat.js'][106] = 0; + _$jscoverage['plugins/removeformat.js'][108] = 0; + _$jscoverage['plugins/removeformat.js'][109] = 0; + _$jscoverage['plugins/removeformat.js'][110] = 0; + _$jscoverage['plugins/removeformat.js'][111] = 0; + _$jscoverage['plugins/removeformat.js'][112] = 0; + _$jscoverage['plugins/removeformat.js'][113] = 0; + _$jscoverage['plugins/removeformat.js'][116] = 0; + _$jscoverage['plugins/removeformat.js'][120] = 0; + _$jscoverage['plugins/removeformat.js'][121] = 0; + _$jscoverage['plugins/removeformat.js'][122] = 0; + _$jscoverage['plugins/removeformat.js'][123] = 0; + _$jscoverage['plugins/removeformat.js'][129] = 0; + _$jscoverage['plugins/removeformat.js'][134] = 0; + _$jscoverage['plugins/removeformat.js'][135] = 0; + _$jscoverage['plugins/removeformat.js'][136] = 0; + _$jscoverage['plugins/removeformat.js'][138] = 0; + _$jscoverage['plugins/removeformat.js'][139] = 0; + _$jscoverage['plugins/removeformat.js'][140] = 0; + _$jscoverage['plugins/removeformat.js'][142] = 0; + _$jscoverage['plugins/removeformat.js'][144] = 0; + _$jscoverage['plugins/removeformat.js'][147] = 0; + _$jscoverage['plugins/removeformat.js'][148] = 0; + _$jscoverage['plugins/removeformat.js'][149] = 0; + _$jscoverage['plugins/removeformat.js'][152] = 0; + _$jscoverage['plugins/removeformat.js'][153] = 0; + _$jscoverage['plugins/removeformat.js'][155] = 0; + _$jscoverage['plugins/removeformat.js'][156] = 0; + _$jscoverage['plugins/removeformat.js'][159] = 0; + _$jscoverage['plugins/removeformat.js'][160] = 0; + _$jscoverage['plugins/removeformat.js'][161] = 0; + _$jscoverage['plugins/removeformat.js'][162] = 0; + _$jscoverage['plugins/removeformat.js'][163] = 0; + _$jscoverage['plugins/removeformat.js'][164] = 0; + _$jscoverage['plugins/removeformat.js'][166] = 0; + _$jscoverage['plugins/removeformat.js'][175] = 0; + _$jscoverage['plugins/removeformat.js'][176] = 0; + _$jscoverage['plugins/removeformat.js'][177] = 0; +} +_$jscoverage['plugins/removeformat.js'].source = ["/**"," * 清除格式"," * @file"," * @since 1.2.6.1"," */","","/**"," * 对图片居左居中居右排版"," * @command removeformat"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param {String} tags 以逗号隔开的标签。如:span,a"," * @param {String} style 样式"," * @param {String} attrs 属性"," * @param {String} notIncluedA 是否把a标签切开"," * @example"," * ```javascript"," * editor.execCommand( 'removeformat', 'center' );"," * ```"," */","","UE.plugins['removeformat'] = function(){"," var me = this;"," me.setOpt({"," 'removeFormatTags': 'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var',"," 'removeFormatAttributes':'class,style,lang,width,height,align,hspace,valign'"," });"," me.commands['removeformat'] = {"," execCommand : function( cmdName, tags, style, attrs,notIncludeA ) {",""," var tagReg = new RegExp( '^(?:' + (tags || this.options.removeFormatTags).replace( /,/g, '|' ) + ')$', 'i' ) ,"," removeFormatAttributes = style ? [] : (attrs || this.options.removeFormatAttributes).split( ',' ),"," range = new dom.Range( this.document ),"," bookmark,node,parent,"," filter = function( node ) {"," return node.nodeType == 1;"," };",""," function isRedundantSpan (node) {"," if (node.nodeType == 3 || node.tagName.toLowerCase() != 'span'){"," return 0;"," }"," if (browser.ie) {"," //ie 下判断实效,所以只能简单用style来判断"," //return node.style.cssText == '' ? 1 : 0;"," var attrs = node.attributes;"," if ( attrs.length ) {"," for ( var i = 0,l = attrs.length; i<l; i++ ) {"," if ( attrs[i].specified ) {"," return 0;"," }"," }"," return 1;"," }"," }"," return !node.attributes.length;"," }"," function doRemove( range ) {",""," var bookmark1 = range.createBookmark();"," if ( range.collapsed ) {"," range.enlarge( true );"," }",""," //不能把a标签切了"," if(!notIncludeA){"," var aNode = domUtils.findParentByTagName(range.startContainer,'a',true);"," if(aNode){"," range.setStartBefore(aNode);"," }",""," aNode = domUtils.findParentByTagName(range.endContainer,'a',true);"," if(aNode){"," range.setEndAfter(aNode);"," }",""," }","",""," bookmark = range.createBookmark();",""," node = bookmark.start;",""," //切开始"," while ( (parent = node.parentNode) && !domUtils.isBlockElm( parent ) ) {"," domUtils.breakParent( node, parent );",""," domUtils.clearEmptySibling( node );"," }"," if ( bookmark.end ) {"," //切结束"," node = bookmark.end;"," while ( (parent = node.parentNode) && !domUtils.isBlockElm( parent ) ) {"," domUtils.breakParent( node, parent );"," domUtils.clearEmptySibling( node );"," }",""," //开始去除样式"," var current = domUtils.getNextDomNode( bookmark.start, false, filter ),"," next;"," while ( current ) {"," if ( current == bookmark.end ) {"," break;"," }",""," next = domUtils.getNextDomNode( current, true, filter );",""," if ( !dtd.$empty[current.tagName.toLowerCase()] && !domUtils.isBookmarkNode( current ) ) {"," if ( tagReg.test( current.tagName ) ) {"," if ( style ) {"," domUtils.removeStyle( current, style );"," if ( isRedundantSpan( current ) && style != 'text-decoration'){"," domUtils.remove( current, true );"," }"," } else {"," domUtils.remove( current, true );"," }"," } else {"," //trace:939 不能把list上的样式去掉"," if(!dtd.$tableContent[current.tagName] && !dtd.$list[current.tagName]){"," domUtils.removeAttributes( current, removeFormatAttributes );"," if ( isRedundantSpan( current ) ){"," domUtils.remove( current, true );"," }"," }",""," }"," }"," current = next;"," }"," }"," //trace:1035"," //trace:1096 不能把td上的样式去掉,比如边框"," var pN = bookmark.start.parentNode;"," if(domUtils.isBlockElm(pN) && !dtd.$tableContent[pN.tagName] && !dtd.$list[pN.tagName]){"," domUtils.removeAttributes( pN,removeFormatAttributes );"," }"," pN = bookmark.end.parentNode;"," if(bookmark.end && domUtils.isBlockElm(pN) && !dtd.$tableContent[pN.tagName]&& !dtd.$list[pN.tagName]){"," domUtils.removeAttributes( pN,removeFormatAttributes );"," }"," range.moveToBookmark( bookmark ).moveToBookmark(bookmark1);"," //清除冗余的代码 <b><bookmark></b>"," var node = range.startContainer,"," tmp,"," collapsed = range.collapsed;"," while(node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]){"," tmp = node.parentNode;"," range.setStartBefore(node);"," //trace:937"," //更新结束边界"," if(range.startContainer === range.endContainer){"," range.endOffset--;"," }"," domUtils.remove(node);"," node = tmp;"," }",""," if(!collapsed){"," node = range.endContainer;"," while(node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]){"," tmp = node.parentNode;"," range.setEndBefore(node);"," domUtils.remove(node);",""," node = tmp;"," }","",""," }"," }","","",""," range = this.selection.getRange();"," doRemove( range );"," range.select();",""," }",""," };","","};"]; +_$jscoverage['plugins/removeformat.js'][22]++; +UE.plugins.removeformat = (function () { + _$jscoverage['plugins/removeformat.js'][23]++; + var me = this; + _$jscoverage['plugins/removeformat.js'][24]++; + me.setOpt({"removeFormatTags": "b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var", "removeFormatAttributes": "class,style,lang,width,height,align,hspace,valign"}); + _$jscoverage['plugins/removeformat.js'][28]++; + me.commands.removeformat = {execCommand: (function (cmdName, tags, style, attrs, notIncludeA) { + _$jscoverage['plugins/removeformat.js'][31]++; + var tagReg = new RegExp(("^(?:" + (tags || this.options.removeFormatTags).replace(/,/g, "|") + ")$"), "i"), removeFormatAttributes = (style? []: (attrs || this.options.removeFormatAttributes).split(",")), range = new (dom.Range)(this.document), bookmark, node, parent, filter = (function (node) { + _$jscoverage['plugins/removeformat.js'][36]++; + return (node.nodeType == 1); +}); + _$jscoverage['plugins/removeformat.js'][39]++; + function isRedundantSpan(node) { + _$jscoverage['plugins/removeformat.js'][40]++; + if (((node.nodeType == 3) || (node.tagName.toLowerCase() != "span"))) { + _$jscoverage['plugins/removeformat.js'][41]++; + return 0; + } + _$jscoverage['plugins/removeformat.js'][43]++; + if (browser.ie) { + _$jscoverage['plugins/removeformat.js'][46]++; + var attrs = node.attributes; + _$jscoverage['plugins/removeformat.js'][47]++; + if (attrs.length) { + _$jscoverage['plugins/removeformat.js'][48]++; + for (var i = 0, l = attrs.length; (i < l); (i++)) { + _$jscoverage['plugins/removeformat.js'][49]++; + if (attrs[i].specified) { + _$jscoverage['plugins/removeformat.js'][50]++; + return 0; + } +} + _$jscoverage['plugins/removeformat.js'][53]++; + return 1; + } + } + _$jscoverage['plugins/removeformat.js'][56]++; + return (! node.attributes.length); +} + _$jscoverage['plugins/removeformat.js'][58]++; + function doRemove(range) { + _$jscoverage['plugins/removeformat.js'][60]++; + var bookmark1 = range.createBookmark(); + _$jscoverage['plugins/removeformat.js'][61]++; + if (range.collapsed) { + _$jscoverage['plugins/removeformat.js'][62]++; + range.enlarge(true); + } + _$jscoverage['plugins/removeformat.js'][66]++; + if ((! notIncludeA)) { + _$jscoverage['plugins/removeformat.js'][67]++; + var aNode = domUtils.findParentByTagName(range.startContainer, "a", true); + _$jscoverage['plugins/removeformat.js'][68]++; + if (aNode) { + _$jscoverage['plugins/removeformat.js'][69]++; + range.setStartBefore(aNode); + } + _$jscoverage['plugins/removeformat.js'][72]++; + aNode = domUtils.findParentByTagName(range.endContainer, "a", true); + _$jscoverage['plugins/removeformat.js'][73]++; + if (aNode) { + _$jscoverage['plugins/removeformat.js'][74]++; + range.setEndAfter(aNode); + } + } + _$jscoverage['plugins/removeformat.js'][80]++; + bookmark = range.createBookmark(); + _$jscoverage['plugins/removeformat.js'][82]++; + node = bookmark.start; + _$jscoverage['plugins/removeformat.js'][85]++; + while (((parent = node.parentNode) && (! domUtils.isBlockElm(parent)))) { + _$jscoverage['plugins/removeformat.js'][86]++; + domUtils.breakParent(node, parent); + _$jscoverage['plugins/removeformat.js'][88]++; + domUtils.clearEmptySibling(node); +} + _$jscoverage['plugins/removeformat.js'][90]++; + if (bookmark.end) { + _$jscoverage['plugins/removeformat.js'][92]++; + node = bookmark.end; + _$jscoverage['plugins/removeformat.js'][93]++; + while (((parent = node.parentNode) && (! domUtils.isBlockElm(parent)))) { + _$jscoverage['plugins/removeformat.js'][94]++; + domUtils.breakParent(node, parent); + _$jscoverage['plugins/removeformat.js'][95]++; + domUtils.clearEmptySibling(node); +} + _$jscoverage['plugins/removeformat.js'][99]++; + var current = domUtils.getNextDomNode(bookmark.start, false, filter), next; + _$jscoverage['plugins/removeformat.js'][101]++; + while (current) { + _$jscoverage['plugins/removeformat.js'][102]++; + if ((current == bookmark.end)) { + _$jscoverage['plugins/removeformat.js'][103]++; + break; + } + _$jscoverage['plugins/removeformat.js'][106]++; + next = domUtils.getNextDomNode(current, true, filter); + _$jscoverage['plugins/removeformat.js'][108]++; + if (((! dtd.$empty[current.tagName.toLowerCase()]) && (! domUtils.isBookmarkNode(current)))) { + _$jscoverage['plugins/removeformat.js'][109]++; + if (tagReg.test(current.tagName)) { + _$jscoverage['plugins/removeformat.js'][110]++; + if (style) { + _$jscoverage['plugins/removeformat.js'][111]++; + domUtils.removeStyle(current, style); + _$jscoverage['plugins/removeformat.js'][112]++; + if ((isRedundantSpan(current) && (style != "text-decoration"))) { + _$jscoverage['plugins/removeformat.js'][113]++; + domUtils.remove(current, true); + } + } + else { + _$jscoverage['plugins/removeformat.js'][116]++; + domUtils.remove(current, true); + } + } + else { + _$jscoverage['plugins/removeformat.js'][120]++; + if (((! dtd.$tableContent[current.tagName]) && (! dtd.$list[current.tagName]))) { + _$jscoverage['plugins/removeformat.js'][121]++; + domUtils.removeAttributes(current, removeFormatAttributes); + _$jscoverage['plugins/removeformat.js'][122]++; + if (isRedundantSpan(current)) { + _$jscoverage['plugins/removeformat.js'][123]++; + domUtils.remove(current, true); + } + } + } + } + _$jscoverage['plugins/removeformat.js'][129]++; + current = next; +} + } + _$jscoverage['plugins/removeformat.js'][134]++; + var pN = bookmark.start.parentNode; + _$jscoverage['plugins/removeformat.js'][135]++; + if ((domUtils.isBlockElm(pN) && (! dtd.$tableContent[pN.tagName]) && (! dtd.$list[pN.tagName]))) { + _$jscoverage['plugins/removeformat.js'][136]++; + domUtils.removeAttributes(pN, removeFormatAttributes); + } + _$jscoverage['plugins/removeformat.js'][138]++; + pN = bookmark.end.parentNode; + _$jscoverage['plugins/removeformat.js'][139]++; + if ((bookmark.end && domUtils.isBlockElm(pN) && (! dtd.$tableContent[pN.tagName]) && (! dtd.$list[pN.tagName]))) { + _$jscoverage['plugins/removeformat.js'][140]++; + domUtils.removeAttributes(pN, removeFormatAttributes); + } + _$jscoverage['plugins/removeformat.js'][142]++; + range.moveToBookmark(bookmark).moveToBookmark(bookmark1); + _$jscoverage['plugins/removeformat.js'][144]++; + var node = range.startContainer, tmp, collapsed = range.collapsed; + _$jscoverage['plugins/removeformat.js'][147]++; + while (((node.nodeType == 1) && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName])) { + _$jscoverage['plugins/removeformat.js'][148]++; + tmp = node.parentNode; + _$jscoverage['plugins/removeformat.js'][149]++; + range.setStartBefore(node); + _$jscoverage['plugins/removeformat.js'][152]++; + if ((range.startContainer === range.endContainer)) { + _$jscoverage['plugins/removeformat.js'][153]++; + (range.endOffset--); + } + _$jscoverage['plugins/removeformat.js'][155]++; + domUtils.remove(node); + _$jscoverage['plugins/removeformat.js'][156]++; + node = tmp; +} + _$jscoverage['plugins/removeformat.js'][159]++; + if ((! collapsed)) { + _$jscoverage['plugins/removeformat.js'][160]++; + node = range.endContainer; + _$jscoverage['plugins/removeformat.js'][161]++; + while (((node.nodeType == 1) && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName])) { + _$jscoverage['plugins/removeformat.js'][162]++; + tmp = node.parentNode; + _$jscoverage['plugins/removeformat.js'][163]++; + range.setEndBefore(node); + _$jscoverage['plugins/removeformat.js'][164]++; + domUtils.remove(node); + _$jscoverage['plugins/removeformat.js'][166]++; + node = tmp; +} + } +} + _$jscoverage['plugins/removeformat.js'][175]++; + range = this.selection.getRange(); + _$jscoverage['plugins/removeformat.js'][176]++; + doRemove(range); + _$jscoverage['plugins/removeformat.js'][177]++; + range.select(); +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/rowspacing.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/rowspacing.js new file mode 100644 index 000000000..3d4a37ff9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/rowspacing.js @@ -0,0 +1,83 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/rowspacing.js']) { + _$jscoverage['plugins/rowspacing.js'] = []; + _$jscoverage['plugins/rowspacing.js'][19] = 0; + _$jscoverage['plugins/rowspacing.js'][20] = 0; + _$jscoverage['plugins/rowspacing.js'][21] = 0; + _$jscoverage['plugins/rowspacing.js'][26] = 0; + _$jscoverage['plugins/rowspacing.js'][28] = 0; + _$jscoverage['plugins/rowspacing.js'][29] = 0; + _$jscoverage['plugins/rowspacing.js'][32] = 0; + _$jscoverage['plugins/rowspacing.js'][35] = 0; + _$jscoverage['plugins/rowspacing.js'][36] = 0; + _$jscoverage['plugins/rowspacing.js'][37] = 0; + _$jscoverage['plugins/rowspacing.js'][39] = 0; +} +_$jscoverage['plugins/rowspacing.js'].source = ["/**"," * 段前段后间距插件"," * @file"," * @since 1.2.6.1"," */","","/**"," * 设置段前距,段后距"," * @command rowspacing"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param { String } value 传入段间距的值,以px为单位"," * @param { String } dir 传入间距位置,top或bottom,分别表示段前和段后"," * @example"," * ```javascript"," * editor.execCommand( 'rowspacing', '10', 'top' );"," * ```"," */","UE.plugins['rowspacing'] = function(){"," var me = this;"," me.setOpt({"," 'rowspacingtop':['5', '10', '15', '20', '25'],"," 'rowspacingbottom':['5', '10', '15', '20', '25']",""," });"," me.commands['rowspacing'] = {"," execCommand : function( cmdName,value,dir ) {"," this.execCommand('paragraph','p',{style:'margin-'+dir+':'+value + 'px'});"," return true;"," },"," queryCommandValue : function(cmdName,dir) {"," var pN = domUtils.filterNodeList(this.selection.getStartElementPath(),function(node){return domUtils.isBlockElm(node) }),"," value;"," //trace:1026"," if(pN){"," value = domUtils.getComputedStyle(pN,'margin-'+dir).replace(/[^\\d]/g,'');"," return !value ? 0 : value;"," }"," return 0;",""," }"," };","};","",""]; +_$jscoverage['plugins/rowspacing.js'][19]++; +UE.plugins.rowspacing = (function () { + _$jscoverage['plugins/rowspacing.js'][20]++; + var me = this; + _$jscoverage['plugins/rowspacing.js'][21]++; + me.setOpt({"rowspacingtop": ["5", "10", "15", "20", "25"], "rowspacingbottom": ["5", "10", "15", "20", "25"]}); + _$jscoverage['plugins/rowspacing.js'][26]++; + me.commands.rowspacing = {execCommand: (function (cmdName, value, dir) { + _$jscoverage['plugins/rowspacing.js'][28]++; + this.execCommand("paragraph", "p", {style: ("margin-" + dir + ":" + value + "px")}); + _$jscoverage['plugins/rowspacing.js'][29]++; + return true; +}), queryCommandValue: (function (cmdName, dir) { + _$jscoverage['plugins/rowspacing.js'][32]++; + var pN = domUtils.filterNodeList(this.selection.getStartElementPath(), (function (node) { + _$jscoverage['plugins/rowspacing.js'][32]++; + return domUtils.isBlockElm(node); +})), value; + _$jscoverage['plugins/rowspacing.js'][35]++; + if (pN) { + _$jscoverage['plugins/rowspacing.js'][36]++; + value = domUtils.getComputedStyle(pN, ("margin-" + dir)).replace(/[^\d]/g, ""); + _$jscoverage['plugins/rowspacing.js'][37]++; + return ((! value)? 0: value); + } + _$jscoverage['plugins/rowspacing.js'][39]++; + return 0; +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/scrawl.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/scrawl.js new file mode 100644 index 000000000..62c528f16 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/scrawl.js @@ -0,0 +1,50 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/scrawl.js']) { + _$jscoverage['plugins/scrawl.js'] = []; + _$jscoverage['plugins/scrawl.js'][17] = 0; + _$jscoverage['plugins/scrawl.js'][19] = 0; +} +_$jscoverage['plugins/scrawl.js'].source = ["/**"," * 涂鸦"," * @file"," * @since 1.2.6.1"," */","","/*"," * 涂鸦浏览器判断"," * @command scrawl"," * @method queryCommandState"," * @return { Int } ie8下返回-1,反之返回0"," * @example"," * ```javascript"," * editor.queryCommandState( 'scrawl' );"," * ```"," */","UE.commands['scrawl'] = {"," queryCommandState : function(){"," return ( browser.ie && browser.version <= 8 ) ? -1 :0;"," }","};"]; +_$jscoverage['plugins/scrawl.js'][17]++; +UE.commands.scrawl = {queryCommandState: (function () { + _$jscoverage['plugins/scrawl.js'][19]++; + return ((browser.ie && (browser.version <= 8))? -1: 0); +})}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/searchreplace.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/searchreplace.js new file mode 100644 index 000000000..4129d8216 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/searchreplace.js @@ -0,0 +1,405 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/searchreplace.js']) { + _$jscoverage['plugins/searchreplace.js'] = []; + _$jscoverage['plugins/searchreplace.js'][10] = 0; + _$jscoverage['plugins/searchreplace.js'][12] = 0; + _$jscoverage['plugins/searchreplace.js'][15] = 0; + _$jscoverage['plugins/searchreplace.js'][16] = 0; + _$jscoverage['plugins/searchreplace.js'][17] = 0; + _$jscoverage['plugins/searchreplace.js'][19] = 0; + _$jscoverage['plugins/searchreplace.js'][21] = 0; + _$jscoverage['plugins/searchreplace.js'][31] = 0; + _$jscoverage['plugins/searchreplace.js'][32] = 0; + _$jscoverage['plugins/searchreplace.js'][33] = 0; + _$jscoverage['plugins/searchreplace.js'][34] = 0; + _$jscoverage['plugins/searchreplace.js'][35] = 0; + _$jscoverage['plugins/searchreplace.js'][37] = 0; + _$jscoverage['plugins/searchreplace.js'][38] = 0; + _$jscoverage['plugins/searchreplace.js'][39] = 0; + _$jscoverage['plugins/searchreplace.js'][40] = 0; + _$jscoverage['plugins/searchreplace.js'][41] = 0; + _$jscoverage['plugins/searchreplace.js'][42] = 0; + _$jscoverage['plugins/searchreplace.js'][43] = 0; + _$jscoverage['plugins/searchreplace.js'][44] = 0; + _$jscoverage['plugins/searchreplace.js'][46] = 0; + _$jscoverage['plugins/searchreplace.js'][50] = 0; + _$jscoverage['plugins/searchreplace.js'][51] = 0; + _$jscoverage['plugins/searchreplace.js'][52] = 0; + _$jscoverage['plugins/searchreplace.js'][55] = 0; + _$jscoverage['plugins/searchreplace.js'][57] = 0; + _$jscoverage['plugins/searchreplace.js'][58] = 0; + _$jscoverage['plugins/searchreplace.js'][60] = 0; + _$jscoverage['plugins/searchreplace.js'][61] = 0; + _$jscoverage['plugins/searchreplace.js'][62] = 0; + _$jscoverage['plugins/searchreplace.js'][64] = 0; + _$jscoverage['plugins/searchreplace.js'][65] = 0; + _$jscoverage['plugins/searchreplace.js'][68] = 0; + _$jscoverage['plugins/searchreplace.js'][69] = 0; + _$jscoverage['plugins/searchreplace.js'][70] = 0; + _$jscoverage['plugins/searchreplace.js'][71] = 0; + _$jscoverage['plugins/searchreplace.js'][72] = 0; + _$jscoverage['plugins/searchreplace.js'][73] = 0; + _$jscoverage['plugins/searchreplace.js'][75] = 0; + _$jscoverage['plugins/searchreplace.js'][77] = 0; + _$jscoverage['plugins/searchreplace.js'][78] = 0; + _$jscoverage['plugins/searchreplace.js'][79] = 0; + _$jscoverage['plugins/searchreplace.js'][80] = 0; + _$jscoverage['plugins/searchreplace.js'][83] = 0; + _$jscoverage['plugins/searchreplace.js'][84] = 0; + _$jscoverage['plugins/searchreplace.js'][85] = 0; + _$jscoverage['plugins/searchreplace.js'][90] = 0; + _$jscoverage['plugins/searchreplace.js'][91] = 0; + _$jscoverage['plugins/searchreplace.js'][92] = 0; + _$jscoverage['plugins/searchreplace.js'][93] = 0; + _$jscoverage['plugins/searchreplace.js'][94] = 0; + _$jscoverage['plugins/searchreplace.js'][95] = 0; + _$jscoverage['plugins/searchreplace.js'][97] = 0; + _$jscoverage['plugins/searchreplace.js'][98] = 0; + _$jscoverage['plugins/searchreplace.js'][99] = 0; + _$jscoverage['plugins/searchreplace.js'][102] = 0; + _$jscoverage['plugins/searchreplace.js'][103] = 0; + _$jscoverage['plugins/searchreplace.js'][104] = 0; + _$jscoverage['plugins/searchreplace.js'][105] = 0; + _$jscoverage['plugins/searchreplace.js'][108] = 0; + _$jscoverage['plugins/searchreplace.js'][109] = 0; + _$jscoverage['plugins/searchreplace.js'][112] = 0; + _$jscoverage['plugins/searchreplace.js'][113] = 0; + _$jscoverage['plugins/searchreplace.js'][114] = 0; + _$jscoverage['plugins/searchreplace.js'][116] = 0; + _$jscoverage['plugins/searchreplace.js'][119] = 0; + _$jscoverage['plugins/searchreplace.js'][120] = 0; + _$jscoverage['plugins/searchreplace.js'][126] = 0; + _$jscoverage['plugins/searchreplace.js'][127] = 0; + _$jscoverage['plugins/searchreplace.js'][128] = 0; + _$jscoverage['plugins/searchreplace.js'][129] = 0; + _$jscoverage['plugins/searchreplace.js'][131] = 0; + _$jscoverage['plugins/searchreplace.js'][135] = 0; + _$jscoverage['plugins/searchreplace.js'][136] = 0; + _$jscoverage['plugins/searchreplace.js'][138] = 0; + _$jscoverage['plugins/searchreplace.js'][139] = 0; + _$jscoverage['plugins/searchreplace.js'][140] = 0; + _$jscoverage['plugins/searchreplace.js'][142] = 0; + _$jscoverage['plugins/searchreplace.js'][144] = 0; + _$jscoverage['plugins/searchreplace.js'][146] = 0; + _$jscoverage['plugins/searchreplace.js'][147] = 0; + _$jscoverage['plugins/searchreplace.js'][148] = 0; + _$jscoverage['plugins/searchreplace.js'][150] = 0; + _$jscoverage['plugins/searchreplace.js'][151] = 0; + _$jscoverage['plugins/searchreplace.js'][153] = 0; + _$jscoverage['plugins/searchreplace.js'][154] = 0; + _$jscoverage['plugins/searchreplace.js'][155] = 0; + _$jscoverage['plugins/searchreplace.js'][157] = 0; + _$jscoverage['plugins/searchreplace.js'][158] = 0; + _$jscoverage['plugins/searchreplace.js'][159] = 0; + _$jscoverage['plugins/searchreplace.js'][160] = 0; + _$jscoverage['plugins/searchreplace.js'][162] = 0; + _$jscoverage['plugins/searchreplace.js'][163] = 0; + _$jscoverage['plugins/searchreplace.js'][164] = 0; + _$jscoverage['plugins/searchreplace.js'][166] = 0; + _$jscoverage['plugins/searchreplace.js'][167] = 0; + _$jscoverage['plugins/searchreplace.js'][168] = 0; + _$jscoverage['plugins/searchreplace.js'][169] = 0; + _$jscoverage['plugins/searchreplace.js'][170] = 0; + _$jscoverage['plugins/searchreplace.js'][171] = 0; + _$jscoverage['plugins/searchreplace.js'][174] = 0; + _$jscoverage['plugins/searchreplace.js'][176] = 0; + _$jscoverage['plugins/searchreplace.js'][177] = 0; + _$jscoverage['plugins/searchreplace.js'][178] = 0; + _$jscoverage['plugins/searchreplace.js'][183] = 0; +} +_$jscoverage['plugins/searchreplace.js'].source = ["///import core","///commands 查找替换","///commandsName SearchReplace","///commandsTitle 查询替换","///commandsDialog dialogs\\searchreplace","/*"," * @description 查找替换"," * @author zhanyi"," */","UE.plugins['searchreplace'] = function(){",""," var currentRange,"," first,"," me = this;"," me.addListener('reset',function(){"," currentRange = null;"," first = null;"," });"," me.commands['searchreplace'] = {"," execCommand : function(cmdName,opt){"," var me = this,"," sel = me.selection,"," range,"," nativeRange,"," num = 0,"," opt = utils.extend(opt,{"," all : false,"," casesensitive : false,"," dir : 1"," },true);"," var searchStr = opt.searchStr;"," if(browser.ie){"," me.focus();"," while(1){"," var tmpRange;",""," nativeRange = me.document.selection.createRange();"," tmpRange = nativeRange.duplicate();"," tmpRange.moveToElementText(me.document.body);"," if(opt.all){"," first = 0;"," opt.dir = 1;"," if(currentRange){"," tmpRange.setEndPoint(opt.dir == -1 ? 'EndToStart' : 'StartToEnd',currentRange);"," }else{"," tmpRange.moveToElementText(me.document.body);"," }",""," }else{"," tmpRange.setEndPoint(opt.dir == -1 ? 'EndToStart' : 'StartToEnd',nativeRange);"," if(opt.hasOwnProperty(\"replaceStr\")){"," tmpRange.setEndPoint(opt.dir == -1 ? 'StartToEnd' : 'EndToStart',nativeRange);"," }"," }"," nativeRange = tmpRange.duplicate();",""," if(/^\\/[^/]+\\/\\w*$/.test(opt.searchStr)){"," var str = tmpRange.text,"," reg = new RegExp(opt.searchStr.replace(/^\\/|\\/\\w*$/g,''),'g' + (opt.casesensitive ? '':'i'));"," var match = str.match(reg);"," if(match && match.length){"," searchStr = opt.dir < 0 ? match[match.length -1] : match[0];"," }else{"," currentRange = null;"," return num;"," }"," }"," if(!tmpRange.findText(searchStr,opt.dir,opt.casesensitive ? 4 : 0)){"," currentRange = null;"," tmpRange = me.document.selection.createRange();"," tmpRange.scrollIntoView();"," currentRange = null;"," return num;"," }"," tmpRange.select();"," //替换"," if(opt.hasOwnProperty(\"replaceStr\")){"," range = sel.getRange();"," range.deleteContents().insertNode(range.document.createTextNode(opt.replaceStr)).select();"," currentRange = sel.getNative().createRange();",""," }"," num++;"," if(!opt.all){"," break;"," }"," }"," }else{",""," var w = me.window,nativeSel = sel.getNative();"," while(1){"," if(opt.all){"," if(currentRange){"," currentRange.collapse(false);"," nativeRange = currentRange;"," }else{"," nativeRange = me.document.createRange();"," nativeRange.setStart(me.document.body,0);"," nativeRange.collapse(true);"," }",""," nativeSel.removeAllRanges();"," nativeSel.addRange( nativeRange );"," first = 0;"," opt.dir = 1;"," }else{"," //safari弹出层,原生已经找不到range了,所以需要先选回来,再取原生"," if(browser.safari){"," me.selection.getRange().select();",""," }"," var nativeSel = w.getSelection();"," if(!nativeSel.rangeCount){"," nativeRange = currentRange || me._bakNativeRange;"," }else{"," nativeRange = nativeSel.getRangeAt(0);"," }",""," if(opt.hasOwnProperty(\"replaceStr\")){"," nativeRange.collapse(opt.dir == 1 ? true : false);"," }"," }",""," //如果是第一次并且海选中了内容那就要清除,为find做准备",""," if(!first){"," nativeRange.collapse( opt.dir <0 ? true : false);"," nativeSel.removeAllRanges();"," nativeSel.addRange( nativeRange );"," }else{"," nativeSel.removeAllRanges();"," }"," //是正则查找",""," if(/^\\/[^/]+\\/\\w*$/.test(opt.searchStr)){"," var tmpRange = nativeRange.cloneRange();"," //向前查找"," if(opt.dir < 0 ){"," nativeRange.collapse(true);"," nativeRange.setStart(me.body,0);"," }else{"," nativeRange.setEnd(me.body,me.body.childNodes.length);"," }"," var str = nativeRange + '',"," reg = new RegExp(opt.searchStr.replace(/^\\/|\\/\\w*$/g,''),'g' + (opt.casesensitive ? '':'i'));"," var match = str.match(reg);"," if(match && match.length){"," searchStr = opt.dir < 0 ? match[match.length -1] : match[0];"," }else{"," currentRange = null;"," return num;"," }"," nativeSel.removeAllRanges();"," nativeRange = tmpRange;"," nativeSel.addRange(nativeRange);"," }"," if(!w.find(searchStr,opt.casesensitive,opt.dir < 0 ? true : false) ) {"," currentRange = null;"," nativeSel.removeAllRanges();"," return num;"," }"," first = 0;"," range = w.getSelection().getRangeAt(0);"," if(!range.collapsed){",""," if(opt.hasOwnProperty(\"replaceStr\")){"," range.deleteContents();"," var text = w.document.createTextNode(opt.replaceStr);"," range.insertNode(text);"," range.selectNode(text);"," nativeSel.addRange(range);",""," }"," currentRange = range.cloneRange();"," }"," num++;"," if(!opt.all){"," break;"," }"," }",""," }"," return true;"," }"," };","","};"]; +_$jscoverage['plugins/searchreplace.js'][10]++; +UE.plugins.searchreplace = (function () { + _$jscoverage['plugins/searchreplace.js'][12]++; + var currentRange, first, me = this; + _$jscoverage['plugins/searchreplace.js'][15]++; + me.addListener("reset", (function () { + _$jscoverage['plugins/searchreplace.js'][16]++; + currentRange = null; + _$jscoverage['plugins/searchreplace.js'][17]++; + first = null; +})); + _$jscoverage['plugins/searchreplace.js'][19]++; + me.commands.searchreplace = {execCommand: (function (cmdName, opt) { + _$jscoverage['plugins/searchreplace.js'][21]++; + var me = this, sel = me.selection, range, nativeRange, num = 0, opt = utils.extend(opt, {all: false, casesensitive: false, dir: 1}, true); + _$jscoverage['plugins/searchreplace.js'][31]++; + var searchStr = opt.searchStr; + _$jscoverage['plugins/searchreplace.js'][32]++; + if (browser.ie) { + _$jscoverage['plugins/searchreplace.js'][33]++; + me.focus(); + _$jscoverage['plugins/searchreplace.js'][34]++; + while (true) { + _$jscoverage['plugins/searchreplace.js'][35]++; + var tmpRange; + _$jscoverage['plugins/searchreplace.js'][37]++; + nativeRange = me.document.selection.createRange(); + _$jscoverage['plugins/searchreplace.js'][38]++; + tmpRange = nativeRange.duplicate(); + _$jscoverage['plugins/searchreplace.js'][39]++; + tmpRange.moveToElementText(me.document.body); + _$jscoverage['plugins/searchreplace.js'][40]++; + if (opt.all) { + _$jscoverage['plugins/searchreplace.js'][41]++; + first = 0; + _$jscoverage['plugins/searchreplace.js'][42]++; + opt.dir = 1; + _$jscoverage['plugins/searchreplace.js'][43]++; + if (currentRange) { + _$jscoverage['plugins/searchreplace.js'][44]++; + tmpRange.setEndPoint(((opt.dir == -1)? "EndToStart": "StartToEnd"), currentRange); + } + else { + _$jscoverage['plugins/searchreplace.js'][46]++; + tmpRange.moveToElementText(me.document.body); + } + } + else { + _$jscoverage['plugins/searchreplace.js'][50]++; + tmpRange.setEndPoint(((opt.dir == -1)? "EndToStart": "StartToEnd"), nativeRange); + _$jscoverage['plugins/searchreplace.js'][51]++; + if (opt.hasOwnProperty("replaceStr")) { + _$jscoverage['plugins/searchreplace.js'][52]++; + tmpRange.setEndPoint(((opt.dir == -1)? "StartToEnd": "EndToStart"), nativeRange); + } + } + _$jscoverage['plugins/searchreplace.js'][55]++; + nativeRange = tmpRange.duplicate(); + _$jscoverage['plugins/searchreplace.js'][57]++; + if (/^\/[^/]+\/\w*$/.test(opt.searchStr)) { + _$jscoverage['plugins/searchreplace.js'][58]++; + var str = tmpRange.text, reg = new RegExp(opt.searchStr.replace(/^\/|\/\w*$/g, ""), ("g" + (opt.casesensitive? "": "i"))); + _$jscoverage['plugins/searchreplace.js'][60]++; + var match = str.match(reg); + _$jscoverage['plugins/searchreplace.js'][61]++; + if ((match && match.length)) { + _$jscoverage['plugins/searchreplace.js'][62]++; + searchStr = ((opt.dir < 0)? match[(match.length - 1)]: match[0]); + } + else { + _$jscoverage['plugins/searchreplace.js'][64]++; + currentRange = null; + _$jscoverage['plugins/searchreplace.js'][65]++; + return num; + } + } + _$jscoverage['plugins/searchreplace.js'][68]++; + if ((! tmpRange.findText(searchStr, opt.dir, (opt.casesensitive? 4: 0)))) { + _$jscoverage['plugins/searchreplace.js'][69]++; + currentRange = null; + _$jscoverage['plugins/searchreplace.js'][70]++; + tmpRange = me.document.selection.createRange(); + _$jscoverage['plugins/searchreplace.js'][71]++; + tmpRange.scrollIntoView(); + _$jscoverage['plugins/searchreplace.js'][72]++; + currentRange = null; + _$jscoverage['plugins/searchreplace.js'][73]++; + return num; + } + _$jscoverage['plugins/searchreplace.js'][75]++; + tmpRange.select(); + _$jscoverage['plugins/searchreplace.js'][77]++; + if (opt.hasOwnProperty("replaceStr")) { + _$jscoverage['plugins/searchreplace.js'][78]++; + range = sel.getRange(); + _$jscoverage['plugins/searchreplace.js'][79]++; + range.deleteContents().insertNode(range.document.createTextNode(opt.replaceStr)).select(); + _$jscoverage['plugins/searchreplace.js'][80]++; + currentRange = sel.getNative().createRange(); + } + _$jscoverage['plugins/searchreplace.js'][83]++; + (num++); + _$jscoverage['plugins/searchreplace.js'][84]++; + if ((! opt.all)) { + _$jscoverage['plugins/searchreplace.js'][85]++; + break; + } +} + } + else { + _$jscoverage['plugins/searchreplace.js'][90]++; + var w = me.window, nativeSel = sel.getNative(); + _$jscoverage['plugins/searchreplace.js'][91]++; + while (true) { + _$jscoverage['plugins/searchreplace.js'][92]++; + if (opt.all) { + _$jscoverage['plugins/searchreplace.js'][93]++; + if (currentRange) { + _$jscoverage['plugins/searchreplace.js'][94]++; + currentRange.collapse(false); + _$jscoverage['plugins/searchreplace.js'][95]++; + nativeRange = currentRange; + } + else { + _$jscoverage['plugins/searchreplace.js'][97]++; + nativeRange = me.document.createRange(); + _$jscoverage['plugins/searchreplace.js'][98]++; + nativeRange.setStart(me.document.body, 0); + _$jscoverage['plugins/searchreplace.js'][99]++; + nativeRange.collapse(true); + } + _$jscoverage['plugins/searchreplace.js'][102]++; + nativeSel.removeAllRanges(); + _$jscoverage['plugins/searchreplace.js'][103]++; + nativeSel.addRange(nativeRange); + _$jscoverage['plugins/searchreplace.js'][104]++; + first = 0; + _$jscoverage['plugins/searchreplace.js'][105]++; + opt.dir = 1; + } + else { + _$jscoverage['plugins/searchreplace.js'][108]++; + if (browser.safari) { + _$jscoverage['plugins/searchreplace.js'][109]++; + me.selection.getRange().select(); + } + _$jscoverage['plugins/searchreplace.js'][112]++; + var nativeSel = w.getSelection(); + _$jscoverage['plugins/searchreplace.js'][113]++; + if ((! nativeSel.rangeCount)) { + _$jscoverage['plugins/searchreplace.js'][114]++; + nativeRange = (currentRange || me._bakNativeRange); + } + else { + _$jscoverage['plugins/searchreplace.js'][116]++; + nativeRange = nativeSel.getRangeAt(0); + } + _$jscoverage['plugins/searchreplace.js'][119]++; + if (opt.hasOwnProperty("replaceStr")) { + _$jscoverage['plugins/searchreplace.js'][120]++; + nativeRange.collapse(((opt.dir == 1)? true: false)); + } + } + _$jscoverage['plugins/searchreplace.js'][126]++; + if ((! first)) { + _$jscoverage['plugins/searchreplace.js'][127]++; + nativeRange.collapse(((opt.dir < 0)? true: false)); + _$jscoverage['plugins/searchreplace.js'][128]++; + nativeSel.removeAllRanges(); + _$jscoverage['plugins/searchreplace.js'][129]++; + nativeSel.addRange(nativeRange); + } + else { + _$jscoverage['plugins/searchreplace.js'][131]++; + nativeSel.removeAllRanges(); + } + _$jscoverage['plugins/searchreplace.js'][135]++; + if (/^\/[^/]+\/\w*$/.test(opt.searchStr)) { + _$jscoverage['plugins/searchreplace.js'][136]++; + var tmpRange = nativeRange.cloneRange(); + _$jscoverage['plugins/searchreplace.js'][138]++; + if ((opt.dir < 0)) { + _$jscoverage['plugins/searchreplace.js'][139]++; + nativeRange.collapse(true); + _$jscoverage['plugins/searchreplace.js'][140]++; + nativeRange.setStart(me.body, 0); + } + else { + _$jscoverage['plugins/searchreplace.js'][142]++; + nativeRange.setEnd(me.body, me.body.childNodes.length); + } + _$jscoverage['plugins/searchreplace.js'][144]++; + var str = (nativeRange + ""), reg = new RegExp(opt.searchStr.replace(/^\/|\/\w*$/g, ""), ("g" + (opt.casesensitive? "": "i"))); + _$jscoverage['plugins/searchreplace.js'][146]++; + var match = str.match(reg); + _$jscoverage['plugins/searchreplace.js'][147]++; + if ((match && match.length)) { + _$jscoverage['plugins/searchreplace.js'][148]++; + searchStr = ((opt.dir < 0)? match[(match.length - 1)]: match[0]); + } + else { + _$jscoverage['plugins/searchreplace.js'][150]++; + currentRange = null; + _$jscoverage['plugins/searchreplace.js'][151]++; + return num; + } + _$jscoverage['plugins/searchreplace.js'][153]++; + nativeSel.removeAllRanges(); + _$jscoverage['plugins/searchreplace.js'][154]++; + nativeRange = tmpRange; + _$jscoverage['plugins/searchreplace.js'][155]++; + nativeSel.addRange(nativeRange); + } + _$jscoverage['plugins/searchreplace.js'][157]++; + if ((! w.find(searchStr, opt.casesensitive, ((opt.dir < 0)? true: false)))) { + _$jscoverage['plugins/searchreplace.js'][158]++; + currentRange = null; + _$jscoverage['plugins/searchreplace.js'][159]++; + nativeSel.removeAllRanges(); + _$jscoverage['plugins/searchreplace.js'][160]++; + return num; + } + _$jscoverage['plugins/searchreplace.js'][162]++; + first = 0; + _$jscoverage['plugins/searchreplace.js'][163]++; + range = w.getSelection().getRangeAt(0); + _$jscoverage['plugins/searchreplace.js'][164]++; + if ((! range.collapsed)) { + _$jscoverage['plugins/searchreplace.js'][166]++; + if (opt.hasOwnProperty("replaceStr")) { + _$jscoverage['plugins/searchreplace.js'][167]++; + range.deleteContents(); + _$jscoverage['plugins/searchreplace.js'][168]++; + var text = w.document.createTextNode(opt.replaceStr); + _$jscoverage['plugins/searchreplace.js'][169]++; + range.insertNode(text); + _$jscoverage['plugins/searchreplace.js'][170]++; + range.selectNode(text); + _$jscoverage['plugins/searchreplace.js'][171]++; + nativeSel.addRange(range); + } + _$jscoverage['plugins/searchreplace.js'][174]++; + currentRange = range.cloneRange(); + } + _$jscoverage['plugins/searchreplace.js'][176]++; + (num++); + _$jscoverage['plugins/searchreplace.js'][177]++; + if ((! opt.all)) { + _$jscoverage['plugins/searchreplace.js'][178]++; + break; + } +} + } + _$jscoverage['plugins/searchreplace.js'][183]++; + return true; +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/selectall.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/selectall.js new file mode 100644 index 000000000..a59fe08d2 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/selectall.js @@ -0,0 +1,80 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/selectall.js']) { + _$jscoverage['plugins/selectall.js'] = []; + _$jscoverage['plugins/selectall.js'][17] = 0; + _$jscoverage['plugins/selectall.js'][18] = 0; + _$jscoverage['plugins/selectall.js'][19] = 0; + _$jscoverage['plugins/selectall.js'][22] = 0; + _$jscoverage['plugins/selectall.js'][24] = 0; + _$jscoverage['plugins/selectall.js'][25] = 0; + _$jscoverage['plugins/selectall.js'][27] = 0; + _$jscoverage['plugins/selectall.js'][28] = 0; + _$jscoverage['plugins/selectall.js'][30] = 0; + _$jscoverage['plugins/selectall.js'][32] = 0; + _$jscoverage['plugins/selectall.js'][39] = 0; +} +_$jscoverage['plugins/selectall.js'].source = ["/**"," * 全选"," * @file"," * @since 1.2.6.1"," */","","/**"," * 选中编辑器里的所有内容"," * @command selectall"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'selectall' );"," * ```"," */","UE.plugins['selectall'] = function(){"," var me = this;"," me.commands['selectall'] = {"," execCommand : function(){"," //去掉了原生的selectAll,因为会出现报错和当内容为空时,不能出现闭合状态的光标"," var me = this,body = me.body,"," range = me.selection.getRange();"," range.selectNodeContents(body);"," if(domUtils.isEmptyBlock(body)){"," //opera不能自动合并到元素的里边,要手动处理一下"," if(browser.opera && body.firstChild && body.firstChild.nodeType == 1){"," range.setStartAtFirst(body.firstChild);"," }"," range.collapse(true);"," }"," range.select(true);"," },"," notNeedUndo : 1"," };","",""," //快捷键"," me.addshortcutkey({"," \"selectAll\" : \"ctrl+65\""," });","};"]; +_$jscoverage['plugins/selectall.js'][17]++; +UE.plugins.selectall = (function () { + _$jscoverage['plugins/selectall.js'][18]++; + var me = this; + _$jscoverage['plugins/selectall.js'][19]++; + me.commands.selectall = {execCommand: (function () { + _$jscoverage['plugins/selectall.js'][22]++; + var me = this, body = me.body, range = me.selection.getRange(); + _$jscoverage['plugins/selectall.js'][24]++; + range.selectNodeContents(body); + _$jscoverage['plugins/selectall.js'][25]++; + if (domUtils.isEmptyBlock(body)) { + _$jscoverage['plugins/selectall.js'][27]++; + if ((browser.opera && body.firstChild && (body.firstChild.nodeType == 1))) { + _$jscoverage['plugins/selectall.js'][28]++; + range.setStartAtFirst(body.firstChild); + } + _$jscoverage['plugins/selectall.js'][30]++; + range.collapse(true); + } + _$jscoverage['plugins/selectall.js'][32]++; + range.select(true); +}), notNeedUndo: 1}; + _$jscoverage['plugins/selectall.js'][39]++; + me.addshortcutkey({"selectAll": "ctrl+65"}); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/shortcutmenu.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/shortcutmenu.js new file mode 100644 index 000000000..1f728c1db --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/shortcutmenu.js @@ -0,0 +1,145 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/shortcutmenu.js']) { + _$jscoverage['plugins/shortcutmenu.js'] = []; + _$jscoverage['plugins/shortcutmenu.js'][12] = 0; + _$jscoverage['plugins/shortcutmenu.js'][13] = 0; + _$jscoverage['plugins/shortcutmenu.js'][17] = 0; + _$jscoverage['plugins/shortcutmenu.js'][18] = 0; + _$jscoverage['plugins/shortcutmenu.js'][21] = 0; + _$jscoverage['plugins/shortcutmenu.js'][22] = 0; + _$jscoverage['plugins/shortcutmenu.js'][32] = 0; + _$jscoverage['plugins/shortcutmenu.js'][33] = 0; + _$jscoverage['plugins/shortcutmenu.js'][34] = 0; + _$jscoverage['plugins/shortcutmenu.js'][36] = 0; + _$jscoverage['plugins/shortcutmenu.js'][37] = 0; + _$jscoverage['plugins/shortcutmenu.js'][44] = 0; + _$jscoverage['plugins/shortcutmenu.js'][45] = 0; + _$jscoverage['plugins/shortcutmenu.js'][48] = 0; + _$jscoverage['plugins/shortcutmenu.js'][52] = 0; + _$jscoverage['plugins/shortcutmenu.js'][53] = 0; + _$jscoverage['plugins/shortcutmenu.js'][54] = 0; + _$jscoverage['plugins/shortcutmenu.js'][55] = 0; + _$jscoverage['plugins/shortcutmenu.js'][56] = 0; + _$jscoverage['plugins/shortcutmenu.js'][57] = 0; + _$jscoverage['plugins/shortcutmenu.js'][59] = 0; + _$jscoverage['plugins/shortcutmenu.js'][61] = 0; + _$jscoverage['plugins/shortcutmenu.js'][62] = 0; + _$jscoverage['plugins/shortcutmenu.js'][63] = 0; + _$jscoverage['plugins/shortcutmenu.js'][69] = 0; + _$jscoverage['plugins/shortcutmenu.js'][70] = 0; + _$jscoverage['plugins/shortcutmenu.js'][74] = 0; + _$jscoverage['plugins/shortcutmenu.js'][75] = 0; + _$jscoverage['plugins/shortcutmenu.js'][76] = 0; +} +_$jscoverage['plugins/shortcutmenu.js'].source = ["///import core","///commands 弹出菜单","// commandsName popupmenu","///commandsTitle 弹出菜单","/*"," * 弹出菜单"," * @function"," * @name baidu.editor.plugins.popupmenu"," * @author xuheng"," */","","UE.plugins['shortcutmenu'] = function () {"," var me = this,"," menu,"," items = me.options.shortcutMenu || [];",""," if (!items.length) {"," return;"," }",""," me.addListener ('contextmenu mouseup' , function (type , e) {"," var me = this,"," customEvt = {"," type : type ,"," target : e.target || e.srcElement ,"," screenX : e.screenX ,"," screenY : e.screenY ,"," clientX : e.clientX ,"," clientY : e.clientY"," };",""," setTimeout (function () {"," var rng = me.selection.getRange ();"," if (rng.collapsed === false || type == \"contextmenu\") {",""," if (!menu) {"," menu = new baidu.editor.ui.ShortCutMenu ({"," editor : me ,"," items : items ,"," theme : me.options.theme ,"," className : 'edui-shortcutmenu'"," });",""," menu.render ();"," me.fireEvent (\"afterrendershortcutmenu\" , menu);"," }",""," menu.show (customEvt , !!UE.plugins['contextmenu']);"," }"," });",""," if (type == 'contextmenu') {"," domUtils.preventDefault (e);"," if (browser.ie) {"," var ieRange;"," try {"," ieRange = me.selection.getNative ().createRange ();"," } catch (e) {"," return;"," }"," if (ieRange.item) {"," var range = new dom.Range (me.document);"," range.selectNode (ieRange.item (0)).select (true , true);",""," }"," }"," }",""," if (type == \"keydown\") {"," menu && !menu.isHidden && menu.hide ();"," }"," });",""," me.addListener ('keydown' , function (type) {"," if (type == \"keydown\") {"," menu && !menu.isHidden && menu.hide ();"," }",""," });","","};","",""]; +_$jscoverage['plugins/shortcutmenu.js'][12]++; +UE.plugins.shortcutmenu = (function () { + _$jscoverage['plugins/shortcutmenu.js'][13]++; + var me = this, menu, items = (me.options.shortcutMenu || []); + _$jscoverage['plugins/shortcutmenu.js'][17]++; + if ((! items.length)) { + _$jscoverage['plugins/shortcutmenu.js'][18]++; + return; + } + _$jscoverage['plugins/shortcutmenu.js'][21]++; + me.addListener("contextmenu mouseup", (function (type, e) { + _$jscoverage['plugins/shortcutmenu.js'][22]++; + var me = this, customEvt = {type: type, target: (e.target || e.srcElement), screenX: e.screenX, screenY: e.screenY, clientX: e.clientX, clientY: e.clientY}; + _$jscoverage['plugins/shortcutmenu.js'][32]++; + setTimeout((function () { + _$jscoverage['plugins/shortcutmenu.js'][33]++; + var rng = me.selection.getRange(); + _$jscoverage['plugins/shortcutmenu.js'][34]++; + if (((rng.collapsed === false) || (type == "contextmenu"))) { + _$jscoverage['plugins/shortcutmenu.js'][36]++; + if ((! menu)) { + _$jscoverage['plugins/shortcutmenu.js'][37]++; + menu = new (baidu.editor.ui.ShortCutMenu)({editor: me, items: items, theme: me.options.theme, className: "edui-shortcutmenu"}); + _$jscoverage['plugins/shortcutmenu.js'][44]++; + menu.render(); + _$jscoverage['plugins/shortcutmenu.js'][45]++; + me.fireEvent("afterrendershortcutmenu", menu); + } + _$jscoverage['plugins/shortcutmenu.js'][48]++; + menu.show(customEvt, (! (! UE.plugins.contextmenu))); + } +})); + _$jscoverage['plugins/shortcutmenu.js'][52]++; + if ((type == "contextmenu")) { + _$jscoverage['plugins/shortcutmenu.js'][53]++; + domUtils.preventDefault(e); + _$jscoverage['plugins/shortcutmenu.js'][54]++; + if (browser.ie) { + _$jscoverage['plugins/shortcutmenu.js'][55]++; + var ieRange; + _$jscoverage['plugins/shortcutmenu.js'][56]++; + try { + _$jscoverage['plugins/shortcutmenu.js'][57]++; + ieRange = me.selection.getNative().createRange(); + } + catch (e) { + _$jscoverage['plugins/shortcutmenu.js'][59]++; + return; + } + _$jscoverage['plugins/shortcutmenu.js'][61]++; + if (ieRange.item) { + _$jscoverage['plugins/shortcutmenu.js'][62]++; + var range = new (dom.Range)(me.document); + _$jscoverage['plugins/shortcutmenu.js'][63]++; + range.selectNode(ieRange.item(0)).select(true, true); + } + } + } + _$jscoverage['plugins/shortcutmenu.js'][69]++; + if ((type == "keydown")) { + _$jscoverage['plugins/shortcutmenu.js'][70]++; + (menu && (! menu.isHidden) && menu.hide()); + } +})); + _$jscoverage['plugins/shortcutmenu.js'][74]++; + me.addListener("keydown", (function (type) { + _$jscoverage['plugins/shortcutmenu.js'][75]++; + if ((type == "keydown")) { + _$jscoverage['plugins/shortcutmenu.js'][76]++; + (menu && (! menu.isHidden) && menu.hide()); + } +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/snapscreen.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/snapscreen.js new file mode 100644 index 000000000..11e252cb1 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/snapscreen.js @@ -0,0 +1,173 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/snapscreen.js']) { + _$jscoverage['plugins/snapscreen.js'] = []; + _$jscoverage['plugins/snapscreen.js'][20] = 0; + _$jscoverage['plugins/snapscreen.js'][21] = 0; + _$jscoverage['plugins/snapscreen.js'][25] = 0; + _$jscoverage['plugins/snapscreen.js'][31] = 0; + _$jscoverage['plugins/snapscreen.js'][33] = 0; + _$jscoverage['plugins/snapscreen.js'][34] = 0; + _$jscoverage['plugins/snapscreen.js'][35] = 0; + _$jscoverage['plugins/snapscreen.js'][36] = 0; + _$jscoverage['plugins/snapscreen.js'][37] = 0; + _$jscoverage['plugins/snapscreen.js'][38] = 0; + _$jscoverage['plugins/snapscreen.js'][39] = 0; + _$jscoverage['plugins/snapscreen.js'][41] = 0; + _$jscoverage['plugins/snapscreen.js'][42] = 0; + _$jscoverage['plugins/snapscreen.js'][43] = 0; + _$jscoverage['plugins/snapscreen.js'][44] = 0; + _$jscoverage['plugins/snapscreen.js'][48] = 0; + _$jscoverage['plugins/snapscreen.js'][50] = 0; + _$jscoverage['plugins/snapscreen.js'][51] = 0; + _$jscoverage['plugins/snapscreen.js'][52] = 0; + _$jscoverage['plugins/snapscreen.js'][54] = 0; + _$jscoverage['plugins/snapscreen.js'][55] = 0; + _$jscoverage['plugins/snapscreen.js'][58] = 0; + _$jscoverage['plugins/snapscreen.js'][59] = 0; + _$jscoverage['plugins/snapscreen.js'][60] = 0; + _$jscoverage['plugins/snapscreen.js'][62] = 0; + _$jscoverage['plugins/snapscreen.js'][68] = 0; + _$jscoverage['plugins/snapscreen.js'][71] = 0; + _$jscoverage['plugins/snapscreen.js'][72] = 0; + _$jscoverage['plugins/snapscreen.js'][74] = 0; + _$jscoverage['plugins/snapscreen.js'][75] = 0; + _$jscoverage['plugins/snapscreen.js'][76] = 0; + _$jscoverage['plugins/snapscreen.js'][77] = 0; + _$jscoverage['plugins/snapscreen.js'][78] = 0; + _$jscoverage['plugins/snapscreen.js'][79] = 0; + _$jscoverage['plugins/snapscreen.js'][81] = 0; + _$jscoverage['plugins/snapscreen.js'][82] = 0; + _$jscoverage['plugins/snapscreen.js'][84] = 0; +} +_$jscoverage['plugins/snapscreen.js'].source = ["/**"," * 截屏"," * @file"," * @since 1.2.6.1"," */","","/**"," * 截屏"," * @command snapscreen"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * //editor是编辑器实例"," * //执行截屏命令, 需要服务器端配合接收图片"," * editor.execCommand( 'snapscreen' );"," * ```"," */","","UE.plugins['snapscreen'] = function(){"," var me = this,"," doc,"," snapplugin;",""," me.setOpt({"," snapscreenServerPort: location.port //屏幕截图的server端端口"," ,snapscreenImgAlign: '' //截图的图片默认的排版方式"," ,snapscreenHost: location.hostname //屏幕截图的server端文件所在的网站地址或者ip,请不要加http://",""," });"," me.commands['snapscreen'] = {"," execCommand: function(){"," var me = this,lang = me.getLang(\"snapScreen_plugin\");"," if(!snapplugin){"," var container = me.container;"," doc = container.ownerDocument || container.document;"," snapplugin = doc.createElement(\"object\");"," try{snapplugin.type = \"application/x-pluginbaidusnap\";}catch(e){"," return;"," }"," snapplugin.style.cssText = \"position:absolute;left:-9999px;\";"," snapplugin.setAttribute(\"width\",\"0\");"," snapplugin.setAttribute(\"height\",\"0\");"," container.appendChild(snapplugin);"," }","",""," var editorOptions = me.options;",""," var onSuccess = function(rs){"," try{"," rs = eval(\"(\"+ rs +\")\");"," }catch(e){"," alert(lang.callBackErrorMsg);"," return;"," }",""," if(rs.state != 'SUCCESS'){"," alert(rs.state);"," return;"," }"," me.execCommand('insertimage', {"," src: editorOptions.snapscreenPath + rs.url,"," floatStyle: editorOptions.snapscreenImgAlign,"," _src:editorOptions.snapscreenPath + rs.url"," });"," };"," var onStartUpload = function(){"," //开始截图上传"," };"," var onError = function(){"," alert(lang.uploadErrorMsg);"," };"," try{"," var port = editorOptions.snapscreenServerPort + '';"," editorOptions.snapscreenServerUrl = editorOptions.snapscreenServerUrl.split( editorOptions.snapscreenHost );"," editorOptions.snapscreenServerUrl = editorOptions.snapscreenServerUrl[1] || editorOptions.snapscreenServerUrl[0];"," if( editorOptions.snapscreenServerUrl.indexOf(\":\"+port) === 0 ) {"," editorOptions.snapscreenServerUrl = editorOptions.snapscreenServerUrl.substring( port.length+1 );"," }"," var ret =snapplugin.saveSnapshot(editorOptions.snapscreenHost, editorOptions.snapscreenServerUrl, port);"," onSuccess(ret);"," }catch(e){"," me.ui._dialogs['snapscreenDialog'].open();"," }"," }"," };","}",""]; +_$jscoverage['plugins/snapscreen.js'][20]++; +UE.plugins.snapscreen = (function () { + _$jscoverage['plugins/snapscreen.js'][21]++; + var me = this, doc, snapplugin; + _$jscoverage['plugins/snapscreen.js'][25]++; + me.setOpt({snapscreenServerPort: location.port, snapscreenImgAlign: "", snapscreenHost: location.hostname}); + _$jscoverage['plugins/snapscreen.js'][31]++; + me.commands.snapscreen = {execCommand: (function () { + _$jscoverage['plugins/snapscreen.js'][33]++; + var me = this, lang = me.getLang("snapScreen_plugin"); + _$jscoverage['plugins/snapscreen.js'][34]++; + if ((! snapplugin)) { + _$jscoverage['plugins/snapscreen.js'][35]++; + var container = me.container; + _$jscoverage['plugins/snapscreen.js'][36]++; + doc = (container.ownerDocument || container.document); + _$jscoverage['plugins/snapscreen.js'][37]++; + snapplugin = doc.createElement("object"); + _$jscoverage['plugins/snapscreen.js'][38]++; + try { + _$jscoverage['plugins/snapscreen.js'][38]++; + snapplugin.type = "application/x-pluginbaidusnap"; + } + catch (e) { + _$jscoverage['plugins/snapscreen.js'][39]++; + return; + } + _$jscoverage['plugins/snapscreen.js'][41]++; + snapplugin.style.cssText = "position:absolute;left:-9999px;"; + _$jscoverage['plugins/snapscreen.js'][42]++; + snapplugin.setAttribute("width", "0"); + _$jscoverage['plugins/snapscreen.js'][43]++; + snapplugin.setAttribute("height", "0"); + _$jscoverage['plugins/snapscreen.js'][44]++; + container.appendChild(snapplugin); + } + _$jscoverage['plugins/snapscreen.js'][48]++; + var editorOptions = me.options; + _$jscoverage['plugins/snapscreen.js'][50]++; + var onSuccess = (function (rs) { + _$jscoverage['plugins/snapscreen.js'][51]++; + try { + _$jscoverage['plugins/snapscreen.js'][52]++; + rs = eval(("(" + rs + ")")); + } + catch (e) { + _$jscoverage['plugins/snapscreen.js'][54]++; + alert(lang.callBackErrorMsg); + _$jscoverage['plugins/snapscreen.js'][55]++; + return; + } + _$jscoverage['plugins/snapscreen.js'][58]++; + if ((rs.state != "SUCCESS")) { + _$jscoverage['plugins/snapscreen.js'][59]++; + alert(rs.state); + _$jscoverage['plugins/snapscreen.js'][60]++; + return; + } + _$jscoverage['plugins/snapscreen.js'][62]++; + me.execCommand("insertimage", {src: (editorOptions.snapscreenPath + rs.url), floatStyle: editorOptions.snapscreenImgAlign, _src: (editorOptions.snapscreenPath + rs.url)}); +}); + _$jscoverage['plugins/snapscreen.js'][68]++; + var onStartUpload = (function () { +}); + _$jscoverage['plugins/snapscreen.js'][71]++; + var onError = (function () { + _$jscoverage['plugins/snapscreen.js'][72]++; + alert(lang.uploadErrorMsg); +}); + _$jscoverage['plugins/snapscreen.js'][74]++; + try { + _$jscoverage['plugins/snapscreen.js'][75]++; + var port = (editorOptions.snapscreenServerPort + ""); + _$jscoverage['plugins/snapscreen.js'][76]++; + editorOptions.snapscreenServerUrl = editorOptions.snapscreenServerUrl.split(editorOptions.snapscreenHost); + _$jscoverage['plugins/snapscreen.js'][77]++; + editorOptions.snapscreenServerUrl = (editorOptions.snapscreenServerUrl[1] || editorOptions.snapscreenServerUrl[0]); + _$jscoverage['plugins/snapscreen.js'][78]++; + if ((editorOptions.snapscreenServerUrl.indexOf((":" + port)) === 0)) { + _$jscoverage['plugins/snapscreen.js'][79]++; + editorOptions.snapscreenServerUrl = editorOptions.snapscreenServerUrl.substring((port.length + 1)); + } + _$jscoverage['plugins/snapscreen.js'][81]++; + var ret = snapplugin.saveSnapshot(editorOptions.snapscreenHost, editorOptions.snapscreenServerUrl, port); + _$jscoverage['plugins/snapscreen.js'][82]++; + onSuccess(ret); + } + catch (e) { + _$jscoverage['plugins/snapscreen.js'][84]++; + me.ui._dialogs.snapscreenDialog.open(); + } +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/source.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/source.js new file mode 100644 index 000000000..a67509153 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/source.js @@ -0,0 +1,476 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/source.js']) { + _$jscoverage['plugins/source.js'] = []; + _$jscoverage['plugins/source.js'][7] = 0; + _$jscoverage['plugins/source.js'][8] = 0; + _$jscoverage['plugins/source.js'][10] = 0; + _$jscoverage['plugins/source.js'][11] = 0; + _$jscoverage['plugins/source.js'][13] = 0; + _$jscoverage['plugins/source.js'][14] = 0; + _$jscoverage['plugins/source.js'][15] = 0; + _$jscoverage['plugins/source.js'][16] = 0; + _$jscoverage['plugins/source.js'][17] = 0; + _$jscoverage['plugins/source.js'][18] = 0; + _$jscoverage['plugins/source.js'][21] = 0; + _$jscoverage['plugins/source.js'][22] = 0; + _$jscoverage['plugins/source.js'][24] = 0; + _$jscoverage['plugins/source.js'][27] = 0; + _$jscoverage['plugins/source.js'][30] = 0; + _$jscoverage['plugins/source.js'][31] = 0; + _$jscoverage['plugins/source.js'][32] = 0; + _$jscoverage['plugins/source.js'][33] = 0; + _$jscoverage['plugins/source.js'][34] = 0; + _$jscoverage['plugins/source.js'][37] = 0; + _$jscoverage['plugins/source.js'][38] = 0; + _$jscoverage['plugins/source.js'][42] = 0; + _$jscoverage['plugins/source.js'][44] = 0; + _$jscoverage['plugins/source.js'][45] = 0; + _$jscoverage['plugins/source.js'][46] = 0; + _$jscoverage['plugins/source.js'][52] = 0; + _$jscoverage['plugins/source.js'][58] = 0; + _$jscoverage['plugins/source.js'][59] = 0; + _$jscoverage['plugins/source.js'][60] = 0; + _$jscoverage['plugins/source.js'][61] = 0; + _$jscoverage['plugins/source.js'][62] = 0; + _$jscoverage['plugins/source.js'][64] = 0; + _$jscoverage['plugins/source.js'][67] = 0; + _$jscoverage['plugins/source.js'][70] = 0; + _$jscoverage['plugins/source.js'][73] = 0; + _$jscoverage['plugins/source.js'][76] = 0; + _$jscoverage['plugins/source.js'][77] = 0; + _$jscoverage['plugins/source.js'][78] = 0; + _$jscoverage['plugins/source.js'][84] = 0; + _$jscoverage['plugins/source.js'][85] = 0; + _$jscoverage['plugins/source.js'][86] = 0; + _$jscoverage['plugins/source.js'][87] = 0; + _$jscoverage['plugins/source.js'][88] = 0; + _$jscoverage['plugins/source.js'][90] = 0; + _$jscoverage['plugins/source.js'][92] = 0; + _$jscoverage['plugins/source.js'][95] = 0; + _$jscoverage['plugins/source.js'][96] = 0; + _$jscoverage['plugins/source.js'][99] = 0; + _$jscoverage['plugins/source.js'][101] = 0; + _$jscoverage['plugins/source.js'][127] = 0; + _$jscoverage['plugins/source.js'][130] = 0; + _$jscoverage['plugins/source.js'][131] = 0; + _$jscoverage['plugins/source.js'][132] = 0; + _$jscoverage['plugins/source.js'][133] = 0; + _$jscoverage['plugins/source.js'][134] = 0; + _$jscoverage['plugins/source.js'][135] = 0; + _$jscoverage['plugins/source.js'][138] = 0; + _$jscoverage['plugins/source.js'][139] = 0; + _$jscoverage['plugins/source.js'][142] = 0; + _$jscoverage['plugins/source.js'][143] = 0; + _$jscoverage['plugins/source.js'][144] = 0; + _$jscoverage['plugins/source.js'][145] = 0; + _$jscoverage['plugins/source.js'][146] = 0; + _$jscoverage['plugins/source.js'][147] = 0; + _$jscoverage['plugins/source.js'][151] = 0; + _$jscoverage['plugins/source.js'][152] = 0; + _$jscoverage['plugins/source.js'][153] = 0; + _$jscoverage['plugins/source.js'][155] = 0; + _$jscoverage['plugins/source.js'][156] = 0; + _$jscoverage['plugins/source.js'][158] = 0; + _$jscoverage['plugins/source.js'][164] = 0; + _$jscoverage['plugins/source.js'][166] = 0; + _$jscoverage['plugins/source.js'][168] = 0; + _$jscoverage['plugins/source.js'][170] = 0; + _$jscoverage['plugins/source.js'][171] = 0; + _$jscoverage['plugins/source.js'][172] = 0; + _$jscoverage['plugins/source.js'][173] = 0; + _$jscoverage['plugins/source.js'][174] = 0; + _$jscoverage['plugins/source.js'][175] = 0; + _$jscoverage['plugins/source.js'][180] = 0; + _$jscoverage['plugins/source.js'][181] = 0; + _$jscoverage['plugins/source.js'][184] = 0; + _$jscoverage['plugins/source.js'][185] = 0; + _$jscoverage['plugins/source.js'][187] = 0; + _$jscoverage['plugins/source.js'][188] = 0; + _$jscoverage['plugins/source.js'][189] = 0; + _$jscoverage['plugins/source.js'][191] = 0; + _$jscoverage['plugins/source.js'][193] = 0; + _$jscoverage['plugins/source.js'][194] = 0; + _$jscoverage['plugins/source.js'][195] = 0; + _$jscoverage['plugins/source.js'][197] = 0; + _$jscoverage['plugins/source.js'][198] = 0; + _$jscoverage['plugins/source.js'][200] = 0; + _$jscoverage['plugins/source.js'][201] = 0; + _$jscoverage['plugins/source.js'][202] = 0; + _$jscoverage['plugins/source.js'][206] = 0; + _$jscoverage['plugins/source.js'][208] = 0; + _$jscoverage['plugins/source.js'][210] = 0; + _$jscoverage['plugins/source.js'][211] = 0; + _$jscoverage['plugins/source.js'][213] = 0; + _$jscoverage['plugins/source.js'][215] = 0; + _$jscoverage['plugins/source.js'][216] = 0; + _$jscoverage['plugins/source.js'][217] = 0; + _$jscoverage['plugins/source.js'][218] = 0; + _$jscoverage['plugins/source.js'][219] = 0; + _$jscoverage['plugins/source.js'][220] = 0; + _$jscoverage['plugins/source.js'][221] = 0; + _$jscoverage['plugins/source.js'][222] = 0; + _$jscoverage['plugins/source.js'][228] = 0; + _$jscoverage['plugins/source.js'][229] = 0; + _$jscoverage['plugins/source.js'][234] = 0; + _$jscoverage['plugins/source.js'][237] = 0; + _$jscoverage['plugins/source.js'][241] = 0; + _$jscoverage['plugins/source.js'][243] = 0; + _$jscoverage['plugins/source.js'][244] = 0; + _$jscoverage['plugins/source.js'][245] = 0; + _$jscoverage['plugins/source.js'][247] = 0; + _$jscoverage['plugins/source.js'][252] = 0; + _$jscoverage['plugins/source.js'][255] = 0; + _$jscoverage['plugins/source.js'][257] = 0; + _$jscoverage['plugins/source.js'][258] = 0; + _$jscoverage['plugins/source.js'][264] = 0; + _$jscoverage['plugins/source.js'][265] = 0; + _$jscoverage['plugins/source.js'][266] = 0; + _$jscoverage['plugins/source.js'][270] = 0; +} +_$jscoverage['plugins/source.js'].source = ["/**"," * 源码编辑插件"," * @file"," * @since 1.2.6.1"," */","","(function (){"," var sourceEditors = {"," textarea: function (editor, holder){"," var textarea = holder.ownerDocument.createElement('textarea');"," textarea.style.cssText = 'position:absolute;resize:none;width:100%;height:100%;border:0;padding:0;margin:0;overflow-y:auto;';"," // todo: IE下只有onresize属性可用... 很纠结"," if (browser.ie && browser.version < 8) {"," textarea.style.width = holder.offsetWidth + 'px';"," textarea.style.height = holder.offsetHeight + 'px';"," holder.onresize = function (){"," textarea.style.width = holder.offsetWidth + 'px';"," textarea.style.height = holder.offsetHeight + 'px';"," };"," }"," holder.appendChild(textarea);"," return {"," setContent: function (content){"," textarea.value = content;"," },"," getContent: function (){"," return textarea.value;"," },"," select: function (){"," var range;"," if (browser.ie) {"," range = textarea.createTextRange();"," range.collapse(true);"," range.select();"," } else {"," //todo: chrome下无法设置焦点"," textarea.setSelectionRange(0, 0);"," textarea.focus();"," }"," },"," dispose: function (){"," holder.removeChild(textarea);"," // todo"," holder.onresize = null;"," textarea = null;"," holder = null;"," }"," };"," },"," codemirror: function (editor, holder){",""," var codeEditor = window.CodeMirror(holder, {"," mode: \"text/html\","," tabMode: \"indent\","," lineNumbers: true,"," lineWrapping:true"," });"," var dom = codeEditor.getWrapperElement();"," dom.style.cssText = 'position:absolute;left:0;top:0;width:100%;height:100%;font-family:consolas,\"Courier new\",monospace;font-size:13px;';"," codeEditor.getScrollerElement().style.cssText = 'position:absolute;left:0;top:0;width:100%;height:100%;';"," codeEditor.refresh();"," return {"," getCodeMirror:function(){"," return codeEditor;"," },"," setContent: function (content){"," codeEditor.setValue(content);"," },"," getContent: function (){"," return codeEditor.getValue();"," },"," select: function (){"," codeEditor.focus();"," },"," dispose: function (){"," holder.removeChild(dom);"," dom = null;"," codeEditor = null;"," }"," };"," }"," };",""," UE.plugins['source'] = function (){"," var me = this;"," var opt = this.options;"," var sourceMode = false;"," var sourceEditor;",""," opt.sourceEditor = browser.ie ? 'textarea' : (opt.sourceEditor || 'codemirror');",""," me.setOpt({"," sourceEditorFirst:false"," });"," function createSourceEditor(holder){"," return sourceEditors[opt.sourceEditor == 'codemirror' && window.CodeMirror ? 'codemirror' : 'textarea'](me, holder);"," }",""," var bakCssText;"," //解决在源码模式下getContent不能得到最新的内容问题"," var oldGetContent = me.getContent,"," bakAddress;","",""," /**"," * 切换源码编辑模式和可视化编辑模式"," * @command source"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'source');"," * ```"," */",""," /**"," * 查询当前编辑区域的状态是源码模式还是可视化模式"," * @command source"," * @method queryCommandState"," * @param { String } cmd 命令字符串"," * @return { int } 如果当前是源码编辑模式,返回1,否则返回0"," * @example"," * ```javascript"," * editor.queryCommandState( 'source' );"," * ```"," */"," me.commands['source'] = {"," execCommand: function (){",""," sourceMode = !sourceMode;"," if (sourceMode) {"," bakAddress = me.selection.getRange().createAddress(false,true);"," me.undoManger && me.undoManger.save(true);"," if(browser.gecko){"," me.body.contentEditable = false;"," }",""," bakCssText = me.iframe.style.cssText;"," me.iframe.style.cssText += 'position:absolute;left:-32768px;top:-32768px;';","",""," me.fireEvent('beforegetcontent');"," var root = UE.htmlparser(me.body.innerHTML);"," me.filterOutputRule(root);"," root.traversal(function (node) {"," if (node.type == 'element') {"," switch (node.tagName) {"," case 'td':"," case 'th':"," case 'caption':"," if(node.children && node.children.length == 1){"," if(node.firstChild().tagName == 'br' ){"," node.removeChild(node.firstChild())"," }"," };"," break;"," case 'pre':"," node.innerText(node.innerText().replace(/&nbsp;/g,' '))",""," }"," }"," });",""," me.fireEvent('aftergetcontent');",""," var content = root.toHtml(true);",""," sourceEditor = createSourceEditor(me.iframe.parentNode);",""," sourceEditor.setContent(content);"," setTimeout(function (){"," sourceEditor.select();"," me.addListener('fullscreenchanged', function(){"," try{"," sourceEditor.getCodeMirror().refresh()"," }catch(e){}"," });"," });"," //重置getContent,源码模式下取值也能是最新的数据"," me.getContent = function (){"," return sourceEditor.getContent() || '<p>' + (browser.ie ? '' : '<br/>')+'</p>';"," };"," } else {"," me.iframe.style.cssText = bakCssText;"," var cont = sourceEditor.getContent() || '<p>' + (browser.ie ? '' : '<br/>')+'</p>';"," //处理掉block节点前后的空格,有可能会误命中,暂时不考虑"," cont = cont.replace(new RegExp('[\\\\r\\\\t\\\\n ]*<\\/?(\\\\w+)\\\\s*(?:[^>]*)>','g'), function(a,b){"," if(b && !dtd.$inlineWithA[b.toLowerCase()]){"," return a.replace(/(^[\\n\\r\\t ]*)|([\\n\\r\\t ]*$)/g,'');"," }"," return a.replace(/(^[\\n\\r\\t]*)|([\\n\\r\\t]*$)/g,'')"," });"," me.setContent(cont);"," sourceEditor.dispose();"," sourceEditor = null;"," //还原getContent方法"," me.getContent = oldGetContent;"," var first = me.body.firstChild;"," //trace:1106 都删除空了,下边会报错,所以补充一个p占位"," if(!first){"," me.body.innerHTML = '<p>'+(browser.ie?'':'<br/>')+'</p>';"," first = me.body.firstChild;"," }"," //要在ifm为显示时ff才能取到selection,否则报错"," //这里不能比较位置了"," me.undoManger && me.undoManger.save(true);",""," if(browser.gecko){",""," var input = document.createElement('input');"," input.style.cssText = 'position:absolute;left:0;top:-32768px';",""," document.body.appendChild(input);",""," me.body.contentEditable = false;"," setTimeout(function(){"," domUtils.setViewportOffset(input, { left: -32768, top: 0 });"," input.focus();"," setTimeout(function(){"," me.body.contentEditable = true;"," me.selection.getRange().moveToAddress(bakAddress).select(true);"," domUtils.remove(input);"," });",""," });"," }else{"," //ie下有可能报错,比如在代码顶头的情况"," try{"," me.selection.getRange().moveToAddress(bakAddress).select(true);"," }catch(e){}",""," }"," }"," this.fireEvent('sourcemodechanged', sourceMode);"," },"," queryCommandState: function (){"," return sourceMode|0;"," },"," notNeedUndo : 1"," };"," var oldQueryCommandState = me.queryCommandState;",""," me.queryCommandState = function (cmdName){"," cmdName = cmdName.toLowerCase();"," if (sourceMode) {"," //源码模式下可以开启的命令"," return cmdName in {"," 'source' : 1,"," 'fullscreen' : 1"," } ? 1 : -1"," }"," return oldQueryCommandState.apply(this, arguments);"," };",""," if(opt.sourceEditor == \"codemirror\"){",""," me.addListener(\"ready\",function(){"," utils.loadFile(document,{"," src : opt.codeMirrorJsUrl || opt.UEDITOR_HOME_URL + \"third-party/codemirror/codemirror.js\","," tag : \"script\","," type : \"text/javascript\","," defer : \"defer\""," },function(){"," if(opt.sourceEditorFirst){"," setTimeout(function(){"," me.execCommand(\"source\");"," },0);"," }"," });"," utils.loadFile(document,{"," tag : \"link\","," rel : \"stylesheet\","," type : \"text/css\","," href : opt.codeMirrorCssUrl || opt.UEDITOR_HOME_URL + \"third-party/codemirror/codemirror.css\""," });",""," });"," }",""," };","","})();"]; +_$jscoverage['plugins/source.js'][7]++; +(function () { + _$jscoverage['plugins/source.js'][8]++; + var sourceEditors = {textarea: (function (editor, holder) { + _$jscoverage['plugins/source.js'][10]++; + var textarea = holder.ownerDocument.createElement("textarea"); + _$jscoverage['plugins/source.js'][11]++; + textarea.style.cssText = "position:absolute;resize:none;width:100%;height:100%;border:0;padding:0;margin:0;overflow-y:auto;"; + _$jscoverage['plugins/source.js'][13]++; + if ((browser.ie && (browser.version < 8))) { + _$jscoverage['plugins/source.js'][14]++; + textarea.style.width = (holder.offsetWidth + "px"); + _$jscoverage['plugins/source.js'][15]++; + textarea.style.height = (holder.offsetHeight + "px"); + _$jscoverage['plugins/source.js'][16]++; + holder.onresize = (function () { + _$jscoverage['plugins/source.js'][17]++; + textarea.style.width = (holder.offsetWidth + "px"); + _$jscoverage['plugins/source.js'][18]++; + textarea.style.height = (holder.offsetHeight + "px"); +}); + } + _$jscoverage['plugins/source.js'][21]++; + holder.appendChild(textarea); + _$jscoverage['plugins/source.js'][22]++; + return ({setContent: (function (content) { + _$jscoverage['plugins/source.js'][24]++; + textarea.value = content; +}), getContent: (function () { + _$jscoverage['plugins/source.js'][27]++; + return textarea.value; +}), select: (function () { + _$jscoverage['plugins/source.js'][30]++; + var range; + _$jscoverage['plugins/source.js'][31]++; + if (browser.ie) { + _$jscoverage['plugins/source.js'][32]++; + range = textarea.createTextRange(); + _$jscoverage['plugins/source.js'][33]++; + range.collapse(true); + _$jscoverage['plugins/source.js'][34]++; + range.select(); + } + else { + _$jscoverage['plugins/source.js'][37]++; + textarea.setSelectionRange(0, 0); + _$jscoverage['plugins/source.js'][38]++; + textarea.focus(); + } +}), dispose: (function () { + _$jscoverage['plugins/source.js'][42]++; + holder.removeChild(textarea); + _$jscoverage['plugins/source.js'][44]++; + holder.onresize = null; + _$jscoverage['plugins/source.js'][45]++; + textarea = null; + _$jscoverage['plugins/source.js'][46]++; + holder = null; +})}); +}), codemirror: (function (editor, holder) { + _$jscoverage['plugins/source.js'][52]++; + var codeEditor = window.CodeMirror(holder, {mode: "text/html", tabMode: "indent", lineNumbers: true, lineWrapping: true}); + _$jscoverage['plugins/source.js'][58]++; + var dom = codeEditor.getWrapperElement(); + _$jscoverage['plugins/source.js'][59]++; + dom.style.cssText = "position:absolute;left:0;top:0;width:100%;height:100%;font-family:consolas,\"Courier new\",monospace;font-size:13px;"; + _$jscoverage['plugins/source.js'][60]++; + codeEditor.getScrollerElement().style.cssText = "position:absolute;left:0;top:0;width:100%;height:100%;"; + _$jscoverage['plugins/source.js'][61]++; + codeEditor.refresh(); + _$jscoverage['plugins/source.js'][62]++; + return ({getCodeMirror: (function () { + _$jscoverage['plugins/source.js'][64]++; + return codeEditor; +}), setContent: (function (content) { + _$jscoverage['plugins/source.js'][67]++; + codeEditor.setValue(content); +}), getContent: (function () { + _$jscoverage['plugins/source.js'][70]++; + return codeEditor.getValue(); +}), select: (function () { + _$jscoverage['plugins/source.js'][73]++; + codeEditor.focus(); +}), dispose: (function () { + _$jscoverage['plugins/source.js'][76]++; + holder.removeChild(dom); + _$jscoverage['plugins/source.js'][77]++; + dom = null; + _$jscoverage['plugins/source.js'][78]++; + codeEditor = null; +})}); +})}; + _$jscoverage['plugins/source.js'][84]++; + UE.plugins.source = (function () { + _$jscoverage['plugins/source.js'][85]++; + var me = this; + _$jscoverage['plugins/source.js'][86]++; + var opt = this.options; + _$jscoverage['plugins/source.js'][87]++; + var sourceMode = false; + _$jscoverage['plugins/source.js'][88]++; + var sourceEditor; + _$jscoverage['plugins/source.js'][90]++; + opt.sourceEditor = (browser.ie? "textarea": (opt.sourceEditor || "codemirror")); + _$jscoverage['plugins/source.js'][92]++; + me.setOpt({sourceEditorFirst: false}); + _$jscoverage['plugins/source.js'][95]++; + function createSourceEditor(holder) { + _$jscoverage['plugins/source.js'][96]++; + return (sourceEditors[(((opt.sourceEditor == "codemirror") && window.CodeMirror)? "codemirror": "textarea")])(me, holder); +} + _$jscoverage['plugins/source.js'][99]++; + var bakCssText; + _$jscoverage['plugins/source.js'][101]++; + var oldGetContent = me.getContent, bakAddress; + _$jscoverage['plugins/source.js'][127]++; + me.commands.source = {execCommand: (function () { + _$jscoverage['plugins/source.js'][130]++; + sourceMode = (! sourceMode); + _$jscoverage['plugins/source.js'][131]++; + if (sourceMode) { + _$jscoverage['plugins/source.js'][132]++; + bakAddress = me.selection.getRange().createAddress(false, true); + _$jscoverage['plugins/source.js'][133]++; + (me.undoManger && me.undoManger.save(true)); + _$jscoverage['plugins/source.js'][134]++; + if (browser.gecko) { + _$jscoverage['plugins/source.js'][135]++; + me.body.contentEditable = false; + } + _$jscoverage['plugins/source.js'][138]++; + bakCssText = me.iframe.style.cssText; + _$jscoverage['plugins/source.js'][139]++; + me.iframe.style.cssText += "position:absolute;left:-32768px;top:-32768px;"; + _$jscoverage['plugins/source.js'][142]++; + me.fireEvent("beforegetcontent"); + _$jscoverage['plugins/source.js'][143]++; + var root = UE.htmlparser(me.body.innerHTML); + _$jscoverage['plugins/source.js'][144]++; + me.filterOutputRule(root); + _$jscoverage['plugins/source.js'][145]++; + root.traversal((function (node) { + _$jscoverage['plugins/source.js'][146]++; + if ((node.type == "element")) { + _$jscoverage['plugins/source.js'][147]++; + switch (node.tagName) { + case "td": + case "th": + case "caption": + _$jscoverage['plugins/source.js'][151]++; + if ((node.children && (node.children.length == 1))) { + _$jscoverage['plugins/source.js'][152]++; + if ((node.firstChild().tagName == "br")) { + _$jscoverage['plugins/source.js'][153]++; + node.removeChild(node.firstChild()); + } + } + _$jscoverage['plugins/source.js'][155]++; + ; + _$jscoverage['plugins/source.js'][156]++; + break; + case "pre": + _$jscoverage['plugins/source.js'][158]++; + node.innerText(node.innerText().replace(/ /g, " ")); + } + } +})); + _$jscoverage['plugins/source.js'][164]++; + me.fireEvent("aftergetcontent"); + _$jscoverage['plugins/source.js'][166]++; + var content = root.toHtml(true); + _$jscoverage['plugins/source.js'][168]++; + sourceEditor = createSourceEditor(me.iframe.parentNode); + _$jscoverage['plugins/source.js'][170]++; + sourceEditor.setContent(content); + _$jscoverage['plugins/source.js'][171]++; + setTimeout((function () { + _$jscoverage['plugins/source.js'][172]++; + sourceEditor.select(); + _$jscoverage['plugins/source.js'][173]++; + me.addListener("fullscreenchanged", (function () { + _$jscoverage['plugins/source.js'][174]++; + try { + _$jscoverage['plugins/source.js'][175]++; + sourceEditor.getCodeMirror().refresh(); + } + catch (e) { + } +})); +})); + _$jscoverage['plugins/source.js'][180]++; + me.getContent = (function () { + _$jscoverage['plugins/source.js'][181]++; + return (sourceEditor.getContent() || ("

    " + (browser.ie? "": "
    ") + "

    ")); +}); + } + else { + _$jscoverage['plugins/source.js'][184]++; + me.iframe.style.cssText = bakCssText; + _$jscoverage['plugins/source.js'][185]++; + var cont = (sourceEditor.getContent() || ("

    " + (browser.ie? "": "
    ") + "

    ")); + _$jscoverage['plugins/source.js'][187]++; + cont = cont.replace(new RegExp("[\\r\\t\\n ]*]*)>", "g"), (function (a, b) { + _$jscoverage['plugins/source.js'][188]++; + if ((b && (! dtd.$inlineWithA[b.toLowerCase()]))) { + _$jscoverage['plugins/source.js'][189]++; + return a.replace(/(^[\n\r\t ]*)|([\n\r\t ]*$)/g, ""); + } + _$jscoverage['plugins/source.js'][191]++; + return a.replace(/(^[\n\r\t]*)|([\n\r\t]*$)/g, ""); +})); + _$jscoverage['plugins/source.js'][193]++; + me.setContent(cont); + _$jscoverage['plugins/source.js'][194]++; + sourceEditor.dispose(); + _$jscoverage['plugins/source.js'][195]++; + sourceEditor = null; + _$jscoverage['plugins/source.js'][197]++; + me.getContent = oldGetContent; + _$jscoverage['plugins/source.js'][198]++; + var first = me.body.firstChild; + _$jscoverage['plugins/source.js'][200]++; + if ((! first)) { + _$jscoverage['plugins/source.js'][201]++; + me.body.innerHTML = ("

    " + (browser.ie? "": "
    ") + "

    "); + _$jscoverage['plugins/source.js'][202]++; + first = me.body.firstChild; + } + _$jscoverage['plugins/source.js'][206]++; + (me.undoManger && me.undoManger.save(true)); + _$jscoverage['plugins/source.js'][208]++; + if (browser.gecko) { + _$jscoverage['plugins/source.js'][210]++; + var input = document.createElement("input"); + _$jscoverage['plugins/source.js'][211]++; + input.style.cssText = "position:absolute;left:0;top:-32768px"; + _$jscoverage['plugins/source.js'][213]++; + document.body.appendChild(input); + _$jscoverage['plugins/source.js'][215]++; + me.body.contentEditable = false; + _$jscoverage['plugins/source.js'][216]++; + setTimeout((function () { + _$jscoverage['plugins/source.js'][217]++; + domUtils.setViewportOffset(input, {left: -32768, top: 0}); + _$jscoverage['plugins/source.js'][218]++; + input.focus(); + _$jscoverage['plugins/source.js'][219]++; + setTimeout((function () { + _$jscoverage['plugins/source.js'][220]++; + me.body.contentEditable = true; + _$jscoverage['plugins/source.js'][221]++; + me.selection.getRange().moveToAddress(bakAddress).select(true); + _$jscoverage['plugins/source.js'][222]++; + domUtils.remove(input); +})); +})); + } + else { + _$jscoverage['plugins/source.js'][228]++; + try { + _$jscoverage['plugins/source.js'][229]++; + me.selection.getRange().moveToAddress(bakAddress).select(true); + } + catch (e) { + } + } + } + _$jscoverage['plugins/source.js'][234]++; + this.fireEvent("sourcemodechanged", sourceMode); +}), queryCommandState: (function () { + _$jscoverage['plugins/source.js'][237]++; + return (sourceMode | 0); +}), notNeedUndo: 1}; + _$jscoverage['plugins/source.js'][241]++; + var oldQueryCommandState = me.queryCommandState; + _$jscoverage['plugins/source.js'][243]++; + me.queryCommandState = (function (cmdName) { + _$jscoverage['plugins/source.js'][244]++; + cmdName = cmdName.toLowerCase(); + _$jscoverage['plugins/source.js'][245]++; + if (sourceMode) { + _$jscoverage['plugins/source.js'][247]++; + return ((cmdName in {"source": 1, "fullscreen": 1})? 1: -1); + } + _$jscoverage['plugins/source.js'][252]++; + return oldQueryCommandState.apply(this, arguments); +}); + _$jscoverage['plugins/source.js'][255]++; + if ((opt.sourceEditor == "codemirror")) { + _$jscoverage['plugins/source.js'][257]++; + me.addListener("ready", (function () { + _$jscoverage['plugins/source.js'][258]++; + utils.loadFile(document, {src: (opt.codeMirrorJsUrl || (opt.UEDITOR_HOME_URL + "third-party/codemirror/codemirror.js")), tag: "script", type: "text/javascript", defer: "defer"}, (function () { + _$jscoverage['plugins/source.js'][264]++; + if (opt.sourceEditorFirst) { + _$jscoverage['plugins/source.js'][265]++; + setTimeout((function () { + _$jscoverage['plugins/source.js'][266]++; + me.execCommand("source"); +}), 0); + } +})); + _$jscoverage['plugins/source.js'][270]++; + utils.loadFile(document, {tag: "link", rel: "stylesheet", type: "text/css", href: (opt.codeMirrorCssUrl || (opt.UEDITOR_HOME_URL + "third-party/codemirror/codemirror.css"))}); +})); + } +}); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/table.action.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/table.action.js new file mode 100644 index 000000000..f42a061c2 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/table.action.js @@ -0,0 +1,3173 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/table.action.js']) { + _$jscoverage['plugins/table.action.js'] = []; + _$jscoverage['plugins/table.action.js'][8] = 0; + _$jscoverage['plugins/table.action.js'][9] = 0; + _$jscoverage['plugins/table.action.js'][29] = 0; + _$jscoverage['plugins/table.action.js'][32] = 0; + _$jscoverage['plugins/table.action.js'][35] = 0; + _$jscoverage['plugins/table.action.js'][38] = 0; + _$jscoverage['plugins/table.action.js'][41] = 0; + _$jscoverage['plugins/table.action.js'][44] = 0; + _$jscoverage['plugins/table.action.js'][45] = 0; + _$jscoverage['plugins/table.action.js'][46] = 0; + _$jscoverage['plugins/table.action.js'][47] = 0; + _$jscoverage['plugins/table.action.js'][48] = 0; + _$jscoverage['plugins/table.action.js'][49] = 0; + _$jscoverage['plugins/table.action.js'][50] = 0; + _$jscoverage['plugins/table.action.js'][51] = 0; + _$jscoverage['plugins/table.action.js'][52] = 0; + _$jscoverage['plugins/table.action.js'][54] = 0; + _$jscoverage['plugins/table.action.js'][56] = 0; + _$jscoverage['plugins/table.action.js'][63] = 0; + _$jscoverage['plugins/table.action.js'][72] = 0; + _$jscoverage['plugins/table.action.js'][76] = 0; + _$jscoverage['plugins/table.action.js'][86] = 0; + _$jscoverage['plugins/table.action.js'][87] = 0; + _$jscoverage['plugins/table.action.js'][115] = 0; + _$jscoverage['plugins/table.action.js'][116] = 0; + _$jscoverage['plugins/table.action.js'][128] = 0; + _$jscoverage['plugins/table.action.js'][130] = 0; + _$jscoverage['plugins/table.action.js'][131] = 0; + _$jscoverage['plugins/table.action.js'][132] = 0; + _$jscoverage['plugins/table.action.js'][134] = 0; + _$jscoverage['plugins/table.action.js'][136] = 0; + _$jscoverage['plugins/table.action.js'][137] = 0; + _$jscoverage['plugins/table.action.js'][139] = 0; + _$jscoverage['plugins/table.action.js'][140] = 0; + _$jscoverage['plugins/table.action.js'][141] = 0; + _$jscoverage['plugins/table.action.js'][142] = 0; + _$jscoverage['plugins/table.action.js'][144] = 0; + _$jscoverage['plugins/table.action.js'][146] = 0; + _$jscoverage['plugins/table.action.js'][149] = 0; + _$jscoverage['plugins/table.action.js'][151] = 0; + _$jscoverage['plugins/table.action.js'][152] = 0; + _$jscoverage['plugins/table.action.js'][153] = 0; + _$jscoverage['plugins/table.action.js'][154] = 0; + _$jscoverage['plugins/table.action.js'][155] = 0; + _$jscoverage['plugins/table.action.js'][156] = 0; + _$jscoverage['plugins/table.action.js'][158] = 0; + _$jscoverage['plugins/table.action.js'][163] = 0; + _$jscoverage['plugins/table.action.js'][165] = 0; + _$jscoverage['plugins/table.action.js'][166] = 0; + _$jscoverage['plugins/table.action.js'][167] = 0; + _$jscoverage['plugins/table.action.js'][168] = 0; + _$jscoverage['plugins/table.action.js'][169] = 0; + _$jscoverage['plugins/table.action.js'][171] = 0; + _$jscoverage['plugins/table.action.js'][172] = 0; + _$jscoverage['plugins/table.action.js'][177] = 0; + _$jscoverage['plugins/table.action.js'][179] = 0; + _$jscoverage['plugins/table.action.js'][181] = 0; + _$jscoverage['plugins/table.action.js'][182] = 0; + _$jscoverage['plugins/table.action.js'][183] = 0; + _$jscoverage['plugins/table.action.js'][185] = 0; + _$jscoverage['plugins/table.action.js'][186] = 0; + _$jscoverage['plugins/table.action.js'][188] = 0; + _$jscoverage['plugins/table.action.js'][189] = 0; + _$jscoverage['plugins/table.action.js'][192] = 0; + _$jscoverage['plugins/table.action.js'][193] = 0; + _$jscoverage['plugins/table.action.js'][195] = 0; + _$jscoverage['plugins/table.action.js'][196] = 0; + _$jscoverage['plugins/table.action.js'][197] = 0; + _$jscoverage['plugins/table.action.js'][198] = 0; + _$jscoverage['plugins/table.action.js'][201] = 0; + _$jscoverage['plugins/table.action.js'][202] = 0; + _$jscoverage['plugins/table.action.js'][203] = 0; + _$jscoverage['plugins/table.action.js'][204] = 0; + _$jscoverage['plugins/table.action.js'][205] = 0; + _$jscoverage['plugins/table.action.js'][213] = 0; + _$jscoverage['plugins/table.action.js'][214] = 0; + _$jscoverage['plugins/table.action.js'][215] = 0; + _$jscoverage['plugins/table.action.js'][216] = 0; + _$jscoverage['plugins/table.action.js'][217] = 0; + _$jscoverage['plugins/table.action.js'][218] = 0; + _$jscoverage['plugins/table.action.js'][219] = 0; + _$jscoverage['plugins/table.action.js'][220] = 0; + _$jscoverage['plugins/table.action.js'][223] = 0; + _$jscoverage['plugins/table.action.js'][224] = 0; + _$jscoverage['plugins/table.action.js'][225] = 0; + _$jscoverage['plugins/table.action.js'][227] = 0; + _$jscoverage['plugins/table.action.js'][234] = 0; + _$jscoverage['plugins/table.action.js'][235] = 0; + _$jscoverage['plugins/table.action.js'][236] = 0; + _$jscoverage['plugins/table.action.js'][239] = 0; + _$jscoverage['plugins/table.action.js'][240] = 0; + _$jscoverage['plugins/table.action.js'][241] = 0; + _$jscoverage['plugins/table.action.js'][242] = 0; + _$jscoverage['plugins/table.action.js'][243] = 0; + _$jscoverage['plugins/table.action.js'][244] = 0; + _$jscoverage['plugins/table.action.js'][245] = 0; + _$jscoverage['plugins/table.action.js'][246] = 0; + _$jscoverage['plugins/table.action.js'][248] = 0; + _$jscoverage['plugins/table.action.js'][249] = 0; + _$jscoverage['plugins/table.action.js'][250] = 0; + _$jscoverage['plugins/table.action.js'][251] = 0; + _$jscoverage['plugins/table.action.js'][252] = 0; + _$jscoverage['plugins/table.action.js'][253] = 0; + _$jscoverage['plugins/table.action.js'][254] = 0; + _$jscoverage['plugins/table.action.js'][255] = 0; + _$jscoverage['plugins/table.action.js'][256] = 0; + _$jscoverage['plugins/table.action.js'][257] = 0; + _$jscoverage['plugins/table.action.js'][258] = 0; + _$jscoverage['plugins/table.action.js'][260] = 0; + _$jscoverage['plugins/table.action.js'][261] = 0; + _$jscoverage['plugins/table.action.js'][262] = 0; + _$jscoverage['plugins/table.action.js'][263] = 0; + _$jscoverage['plugins/table.action.js'][264] = 0; + _$jscoverage['plugins/table.action.js'][265] = 0; + _$jscoverage['plugins/table.action.js'][267] = 0; + _$jscoverage['plugins/table.action.js'][268] = 0; + _$jscoverage['plugins/table.action.js'][269] = 0; + _$jscoverage['plugins/table.action.js'][270] = 0; + _$jscoverage['plugins/table.action.js'][271] = 0; + _$jscoverage['plugins/table.action.js'][273] = 0; + _$jscoverage['plugins/table.action.js'][274] = 0; + _$jscoverage['plugins/table.action.js'][275] = 0; + _$jscoverage['plugins/table.action.js'][276] = 0; + _$jscoverage['plugins/table.action.js'][277] = 0; + _$jscoverage['plugins/table.action.js'][278] = 0; + _$jscoverage['plugins/table.action.js'][279] = 0; + _$jscoverage['plugins/table.action.js'][280] = 0; + _$jscoverage['plugins/table.action.js'][284] = 0; + _$jscoverage['plugins/table.action.js'][285] = 0; + _$jscoverage['plugins/table.action.js'][286] = 0; + _$jscoverage['plugins/table.action.js'][287] = 0; + _$jscoverage['plugins/table.action.js'][288] = 0; + _$jscoverage['plugins/table.action.js'][290] = 0; + _$jscoverage['plugins/table.action.js'][291] = 0; + _$jscoverage['plugins/table.action.js'][292] = 0; + _$jscoverage['plugins/table.action.js'][294] = 0; + _$jscoverage['plugins/table.action.js'][295] = 0; + _$jscoverage['plugins/table.action.js'][296] = 0; + _$jscoverage['plugins/table.action.js'][297] = 0; + _$jscoverage['plugins/table.action.js'][300] = 0; + _$jscoverage['plugins/table.action.js'][301] = 0; + _$jscoverage['plugins/table.action.js'][302] = 0; + _$jscoverage['plugins/table.action.js'][303] = 0; + _$jscoverage['plugins/table.action.js'][304] = 0; + _$jscoverage['plugins/table.action.js'][306] = 0; + _$jscoverage['plugins/table.action.js'][307] = 0; + _$jscoverage['plugins/table.action.js'][308] = 0; + _$jscoverage['plugins/table.action.js'][309] = 0; + _$jscoverage['plugins/table.action.js'][310] = 0; + _$jscoverage['plugins/table.action.js'][311] = 0; + _$jscoverage['plugins/table.action.js'][313] = 0; + _$jscoverage['plugins/table.action.js'][314] = 0; + _$jscoverage['plugins/table.action.js'][316] = 0; + _$jscoverage['plugins/table.action.js'][319] = 0; + _$jscoverage['plugins/table.action.js'][320] = 0; + _$jscoverage['plugins/table.action.js'][321] = 0; + _$jscoverage['plugins/table.action.js'][322] = 0; + _$jscoverage['plugins/table.action.js'][323] = 0; + _$jscoverage['plugins/table.action.js'][324] = 0; + _$jscoverage['plugins/table.action.js'][325] = 0; + _$jscoverage['plugins/table.action.js'][326] = 0; + _$jscoverage['plugins/table.action.js'][330] = 0; + _$jscoverage['plugins/table.action.js'][332] = 0; + _$jscoverage['plugins/table.action.js'][333] = 0; + _$jscoverage['plugins/table.action.js'][334] = 0; + _$jscoverage['plugins/table.action.js'][335] = 0; + _$jscoverage['plugins/table.action.js'][336] = 0; + _$jscoverage['plugins/table.action.js'][337] = 0; + _$jscoverage['plugins/table.action.js'][338] = 0; + _$jscoverage['plugins/table.action.js'][340] = 0; + _$jscoverage['plugins/table.action.js'][341] = 0; + _$jscoverage['plugins/table.action.js'][345] = 0; + _$jscoverage['plugins/table.action.js'][348] = 0; + _$jscoverage['plugins/table.action.js'][352] = 0; + _$jscoverage['plugins/table.action.js'][353] = 0; + _$jscoverage['plugins/table.action.js'][354] = 0; + _$jscoverage['plugins/table.action.js'][355] = 0; + _$jscoverage['plugins/table.action.js'][357] = 0; + _$jscoverage['plugins/table.action.js'][358] = 0; + _$jscoverage['plugins/table.action.js'][359] = 0; + _$jscoverage['plugins/table.action.js'][360] = 0; + _$jscoverage['plugins/table.action.js'][361] = 0; + _$jscoverage['plugins/table.action.js'][362] = 0; + _$jscoverage['plugins/table.action.js'][364] = 0; + _$jscoverage['plugins/table.action.js'][365] = 0; + _$jscoverage['plugins/table.action.js'][368] = 0; + _$jscoverage['plugins/table.action.js'][369] = 0; + _$jscoverage['plugins/table.action.js'][370] = 0; + _$jscoverage['plugins/table.action.js'][371] = 0; + _$jscoverage['plugins/table.action.js'][372] = 0; + _$jscoverage['plugins/table.action.js'][373] = 0; + _$jscoverage['plugins/table.action.js'][375] = 0; + _$jscoverage['plugins/table.action.js'][380] = 0; + _$jscoverage['plugins/table.action.js'][384] = 0; + _$jscoverage['plugins/table.action.js'][385] = 0; + _$jscoverage['plugins/table.action.js'][386] = 0; + _$jscoverage['plugins/table.action.js'][387] = 0; + _$jscoverage['plugins/table.action.js'][388] = 0; + _$jscoverage['plugins/table.action.js'][392] = 0; + _$jscoverage['plugins/table.action.js'][393] = 0; + _$jscoverage['plugins/table.action.js'][395] = 0; + _$jscoverage['plugins/table.action.js'][396] = 0; + _$jscoverage['plugins/table.action.js'][397] = 0; + _$jscoverage['plugins/table.action.js'][398] = 0; + _$jscoverage['plugins/table.action.js'][399] = 0; + _$jscoverage['plugins/table.action.js'][401] = 0; + _$jscoverage['plugins/table.action.js'][402] = 0; + _$jscoverage['plugins/table.action.js'][403] = 0; + _$jscoverage['plugins/table.action.js'][404] = 0; + _$jscoverage['plugins/table.action.js'][410] = 0; + _$jscoverage['plugins/table.action.js'][411] = 0; + _$jscoverage['plugins/table.action.js'][417] = 0; + _$jscoverage['plugins/table.action.js'][418] = 0; + _$jscoverage['plugins/table.action.js'][420] = 0; + _$jscoverage['plugins/table.action.js'][421] = 0; + _$jscoverage['plugins/table.action.js'][422] = 0; + _$jscoverage['plugins/table.action.js'][423] = 0; + _$jscoverage['plugins/table.action.js'][424] = 0; + _$jscoverage['plugins/table.action.js'][425] = 0; + _$jscoverage['plugins/table.action.js'][426] = 0; + _$jscoverage['plugins/table.action.js'][427] = 0; + _$jscoverage['plugins/table.action.js'][428] = 0; + _$jscoverage['plugins/table.action.js'][430] = 0; + _$jscoverage['plugins/table.action.js'][431] = 0; + _$jscoverage['plugins/table.action.js'][432] = 0; + _$jscoverage['plugins/table.action.js'][433] = 0; + _$jscoverage['plugins/table.action.js'][437] = 0; + _$jscoverage['plugins/table.action.js'][438] = 0; + _$jscoverage['plugins/table.action.js'][439] = 0; + _$jscoverage['plugins/table.action.js'][440] = 0; + _$jscoverage['plugins/table.action.js'][441] = 0; + _$jscoverage['plugins/table.action.js'][445] = 0; + _$jscoverage['plugins/table.action.js'][446] = 0; + _$jscoverage['plugins/table.action.js'][448] = 0; + _$jscoverage['plugins/table.action.js'][449] = 0; + _$jscoverage['plugins/table.action.js'][450] = 0; + _$jscoverage['plugins/table.action.js'][452] = 0; + _$jscoverage['plugins/table.action.js'][453] = 0; + _$jscoverage['plugins/table.action.js'][454] = 0; + _$jscoverage['plugins/table.action.js'][455] = 0; + _$jscoverage['plugins/table.action.js'][457] = 0; + _$jscoverage['plugins/table.action.js'][458] = 0; + _$jscoverage['plugins/table.action.js'][459] = 0; + _$jscoverage['plugins/table.action.js'][460] = 0; + _$jscoverage['plugins/table.action.js'][461] = 0; + _$jscoverage['plugins/table.action.js'][475] = 0; + _$jscoverage['plugins/table.action.js'][476] = 0; + _$jscoverage['plugins/table.action.js'][477] = 0; + _$jscoverage['plugins/table.action.js'][478] = 0; + _$jscoverage['plugins/table.action.js'][479] = 0; + _$jscoverage['plugins/table.action.js'][480] = 0; + _$jscoverage['plugins/table.action.js'][482] = 0; + _$jscoverage['plugins/table.action.js'][485] = 0; + _$jscoverage['plugins/table.action.js'][486] = 0; + _$jscoverage['plugins/table.action.js'][487] = 0; + _$jscoverage['plugins/table.action.js'][489] = 0; + _$jscoverage['plugins/table.action.js'][492] = 0; + _$jscoverage['plugins/table.action.js'][494] = 0; + _$jscoverage['plugins/table.action.js'][495] = 0; + _$jscoverage['plugins/table.action.js'][496] = 0; + _$jscoverage['plugins/table.action.js'][497] = 0; + _$jscoverage['plugins/table.action.js'][498] = 0; + _$jscoverage['plugins/table.action.js'][499] = 0; + _$jscoverage['plugins/table.action.js'][501] = 0; + _$jscoverage['plugins/table.action.js'][504] = 0; + _$jscoverage['plugins/table.action.js'][505] = 0; + _$jscoverage['plugins/table.action.js'][506] = 0; + _$jscoverage['plugins/table.action.js'][508] = 0; + _$jscoverage['plugins/table.action.js'][515] = 0; + _$jscoverage['plugins/table.action.js'][518] = 0; + _$jscoverage['plugins/table.action.js'][520] = 0; + _$jscoverage['plugins/table.action.js'][521] = 0; + _$jscoverage['plugins/table.action.js'][522] = 0; + _$jscoverage['plugins/table.action.js'][523] = 0; + _$jscoverage['plugins/table.action.js'][529] = 0; + _$jscoverage['plugins/table.action.js'][530] = 0; + _$jscoverage['plugins/table.action.js'][531] = 0; + _$jscoverage['plugins/table.action.js'][535] = 0; + _$jscoverage['plugins/table.action.js'][537] = 0; + _$jscoverage['plugins/table.action.js'][538] = 0; + _$jscoverage['plugins/table.action.js'][541] = 0; + _$jscoverage['plugins/table.action.js'][542] = 0; + _$jscoverage['plugins/table.action.js'][543] = 0; + _$jscoverage['plugins/table.action.js'][547] = 0; + _$jscoverage['plugins/table.action.js'][548] = 0; + _$jscoverage['plugins/table.action.js'][552] = 0; + _$jscoverage['plugins/table.action.js'][553] = 0; + _$jscoverage['plugins/table.action.js'][555] = 0; + _$jscoverage['plugins/table.action.js'][556] = 0; + _$jscoverage['plugins/table.action.js'][559] = 0; + _$jscoverage['plugins/table.action.js'][560] = 0; + _$jscoverage['plugins/table.action.js'][561] = 0; + _$jscoverage['plugins/table.action.js'][563] = 0; + _$jscoverage['plugins/table.action.js'][564] = 0; + _$jscoverage['plugins/table.action.js'][567] = 0; + _$jscoverage['plugins/table.action.js'][568] = 0; + _$jscoverage['plugins/table.action.js'][569] = 0; + _$jscoverage['plugins/table.action.js'][570] = 0; + _$jscoverage['plugins/table.action.js'][571] = 0; + _$jscoverage['plugins/table.action.js'][574] = 0; + _$jscoverage['plugins/table.action.js'][576] = 0; + _$jscoverage['plugins/table.action.js'][577] = 0; + _$jscoverage['plugins/table.action.js'][578] = 0; + _$jscoverage['plugins/table.action.js'][579] = 0; + _$jscoverage['plugins/table.action.js'][580] = 0; + _$jscoverage['plugins/table.action.js'][582] = 0; + _$jscoverage['plugins/table.action.js'][585] = 0; + _$jscoverage['plugins/table.action.js'][586] = 0; + _$jscoverage['plugins/table.action.js'][587] = 0; + _$jscoverage['plugins/table.action.js'][588] = 0; + _$jscoverage['plugins/table.action.js'][589] = 0; + _$jscoverage['plugins/table.action.js'][590] = 0; + _$jscoverage['plugins/table.action.js'][591] = 0; + _$jscoverage['plugins/table.action.js'][594] = 0; + _$jscoverage['plugins/table.action.js'][598] = 0; + _$jscoverage['plugins/table.action.js'][599] = 0; + _$jscoverage['plugins/table.action.js'][601] = 0; + _$jscoverage['plugins/table.action.js'][602] = 0; + _$jscoverage['plugins/table.action.js'][604] = 0; + _$jscoverage['plugins/table.action.js'][605] = 0; + _$jscoverage['plugins/table.action.js'][606] = 0; + _$jscoverage['plugins/table.action.js'][608] = 0; + _$jscoverage['plugins/table.action.js'][609] = 0; + _$jscoverage['plugins/table.action.js'][610] = 0; + _$jscoverage['plugins/table.action.js'][611] = 0; + _$jscoverage['plugins/table.action.js'][612] = 0; + _$jscoverage['plugins/table.action.js'][615] = 0; + _$jscoverage['plugins/table.action.js'][616] = 0; + _$jscoverage['plugins/table.action.js'][617] = 0; + _$jscoverage['plugins/table.action.js'][618] = 0; + _$jscoverage['plugins/table.action.js'][619] = 0; + _$jscoverage['plugins/table.action.js'][623] = 0; + _$jscoverage['plugins/table.action.js'][624] = 0; + _$jscoverage['plugins/table.action.js'][626] = 0; + _$jscoverage['plugins/table.action.js'][627] = 0; + _$jscoverage['plugins/table.action.js'][630] = 0; + _$jscoverage['plugins/table.action.js'][631] = 0; + _$jscoverage['plugins/table.action.js'][632] = 0; + _$jscoverage['plugins/table.action.js'][634] = 0; + _$jscoverage['plugins/table.action.js'][635] = 0; + _$jscoverage['plugins/table.action.js'][636] = 0; + _$jscoverage['plugins/table.action.js'][638] = 0; + _$jscoverage['plugins/table.action.js'][639] = 0; + _$jscoverage['plugins/table.action.js'][641] = 0; + _$jscoverage['plugins/table.action.js'][642] = 0; + _$jscoverage['plugins/table.action.js'][644] = 0; + _$jscoverage['plugins/table.action.js'][650] = 0; + _$jscoverage['plugins/table.action.js'][651] = 0; + _$jscoverage['plugins/table.action.js'][653] = 0; + _$jscoverage['plugins/table.action.js'][656] = 0; + _$jscoverage['plugins/table.action.js'][657] = 0; + _$jscoverage['plugins/table.action.js'][661] = 0; + _$jscoverage['plugins/table.action.js'][662] = 0; + _$jscoverage['plugins/table.action.js'][663] = 0; + _$jscoverage['plugins/table.action.js'][664] = 0; + _$jscoverage['plugins/table.action.js'][665] = 0; + _$jscoverage['plugins/table.action.js'][666] = 0; + _$jscoverage['plugins/table.action.js'][667] = 0; + _$jscoverage['plugins/table.action.js'][668] = 0; + _$jscoverage['plugins/table.action.js'][669] = 0; + _$jscoverage['plugins/table.action.js'][671] = 0; + _$jscoverage['plugins/table.action.js'][673] = 0; + _$jscoverage['plugins/table.action.js'][674] = 0; + _$jscoverage['plugins/table.action.js'][675] = 0; + _$jscoverage['plugins/table.action.js'][676] = 0; + _$jscoverage['plugins/table.action.js'][677] = 0; + _$jscoverage['plugins/table.action.js'][678] = 0; + _$jscoverage['plugins/table.action.js'][679] = 0; + _$jscoverage['plugins/table.action.js'][682] = 0; + _$jscoverage['plugins/table.action.js'][683] = 0; + _$jscoverage['plugins/table.action.js'][684] = 0; + _$jscoverage['plugins/table.action.js'][685] = 0; + _$jscoverage['plugins/table.action.js'][689] = 0; + _$jscoverage['plugins/table.action.js'][690] = 0; + _$jscoverage['plugins/table.action.js'][691] = 0; + _$jscoverage['plugins/table.action.js'][692] = 0; + _$jscoverage['plugins/table.action.js'][693] = 0; + _$jscoverage['plugins/table.action.js'][695] = 0; + _$jscoverage['plugins/table.action.js'][697] = 0; + _$jscoverage['plugins/table.action.js'][707] = 0; + _$jscoverage['plugins/table.action.js'][708] = 0; + _$jscoverage['plugins/table.action.js'][709] = 0; + _$jscoverage['plugins/table.action.js'][712] = 0; + _$jscoverage['plugins/table.action.js'][713] = 0; + _$jscoverage['plugins/table.action.js'][714] = 0; + _$jscoverage['plugins/table.action.js'][715] = 0; + _$jscoverage['plugins/table.action.js'][719] = 0; + _$jscoverage['plugins/table.action.js'][720] = 0; + _$jscoverage['plugins/table.action.js'][721] = 0; + _$jscoverage['plugins/table.action.js'][722] = 0; + _$jscoverage['plugins/table.action.js'][723] = 0; + _$jscoverage['plugins/table.action.js'][726] = 0; + _$jscoverage['plugins/table.action.js'][727] = 0; + _$jscoverage['plugins/table.action.js'][728] = 0; + _$jscoverage['plugins/table.action.js'][729] = 0; + _$jscoverage['plugins/table.action.js'][731] = 0; + _$jscoverage['plugins/table.action.js'][732] = 0; + _$jscoverage['plugins/table.action.js'][733] = 0; + _$jscoverage['plugins/table.action.js'][736] = 0; + _$jscoverage['plugins/table.action.js'][740] = 0; + _$jscoverage['plugins/table.action.js'][741] = 0; + _$jscoverage['plugins/table.action.js'][742] = 0; + _$jscoverage['plugins/table.action.js'][744] = 0; + _$jscoverage['plugins/table.action.js'][750] = 0; + _$jscoverage['plugins/table.action.js'][752] = 0; + _$jscoverage['plugins/table.action.js'][753] = 0; + _$jscoverage['plugins/table.action.js'][756] = 0; + _$jscoverage['plugins/table.action.js'][759] = 0; + _$jscoverage['plugins/table.action.js'][763] = 0; + _$jscoverage['plugins/table.action.js'][765] = 0; + _$jscoverage['plugins/table.action.js'][767] = 0; + _$jscoverage['plugins/table.action.js'][768] = 0; + _$jscoverage['plugins/table.action.js'][769] = 0; + _$jscoverage['plugins/table.action.js'][770] = 0; + _$jscoverage['plugins/table.action.js'][772] = 0; + _$jscoverage['plugins/table.action.js'][777] = 0; + _$jscoverage['plugins/table.action.js'][778] = 0; + _$jscoverage['plugins/table.action.js'][779] = 0; + _$jscoverage['plugins/table.action.js'][780] = 0; + _$jscoverage['plugins/table.action.js'][781] = 0; + _$jscoverage['plugins/table.action.js'][782] = 0; + _$jscoverage['plugins/table.action.js'][783] = 0; + _$jscoverage['plugins/table.action.js'][784] = 0; + _$jscoverage['plugins/table.action.js'][785] = 0; + _$jscoverage['plugins/table.action.js'][786] = 0; + _$jscoverage['plugins/table.action.js'][788] = 0; + _$jscoverage['plugins/table.action.js'][791] = 0; + _$jscoverage['plugins/table.action.js'][793] = 0; + _$jscoverage['plugins/table.action.js'][794] = 0; + _$jscoverage['plugins/table.action.js'][795] = 0; + _$jscoverage['plugins/table.action.js'][796] = 0; + _$jscoverage['plugins/table.action.js'][799] = 0; + _$jscoverage['plugins/table.action.js'][800] = 0; + _$jscoverage['plugins/table.action.js'][801] = 0; + _$jscoverage['plugins/table.action.js'][802] = 0; + _$jscoverage['plugins/table.action.js'][803] = 0; + _$jscoverage['plugins/table.action.js'][804] = 0; + _$jscoverage['plugins/table.action.js'][806] = 0; + _$jscoverage['plugins/table.action.js'][807] = 0; + _$jscoverage['plugins/table.action.js'][808] = 0; + _$jscoverage['plugins/table.action.js'][809] = 0; + _$jscoverage['plugins/table.action.js'][810] = 0; + _$jscoverage['plugins/table.action.js'][813] = 0; + _$jscoverage['plugins/table.action.js'][817] = 0; + _$jscoverage['plugins/table.action.js'][821] = 0; + _$jscoverage['plugins/table.action.js'][825] = 0; + _$jscoverage['plugins/table.action.js'][827] = 0; + _$jscoverage['plugins/table.action.js'][828] = 0; + _$jscoverage['plugins/table.action.js'][829] = 0; + _$jscoverage['plugins/table.action.js'][830] = 0; + _$jscoverage['plugins/table.action.js'][831] = 0; + _$jscoverage['plugins/table.action.js'][834] = 0; + _$jscoverage['plugins/table.action.js'][838] = 0; + _$jscoverage['plugins/table.action.js'][839] = 0; + _$jscoverage['plugins/table.action.js'][841] = 0; + _$jscoverage['plugins/table.action.js'][842] = 0; + _$jscoverage['plugins/table.action.js'][843] = 0; + _$jscoverage['plugins/table.action.js'][844] = 0; + _$jscoverage['plugins/table.action.js'][845] = 0; + _$jscoverage['plugins/table.action.js'][846] = 0; + _$jscoverage['plugins/table.action.js'][847] = 0; + _$jscoverage['plugins/table.action.js'][848] = 0; + _$jscoverage['plugins/table.action.js'][850] = 0; + _$jscoverage['plugins/table.action.js'][851] = 0; + _$jscoverage['plugins/table.action.js'][853] = 0; + _$jscoverage['plugins/table.action.js'][854] = 0; + _$jscoverage['plugins/table.action.js'][856] = 0; + _$jscoverage['plugins/table.action.js'][857] = 0; + _$jscoverage['plugins/table.action.js'][859] = 0; + _$jscoverage['plugins/table.action.js'][860] = 0; + _$jscoverage['plugins/table.action.js'][862] = 0; + _$jscoverage['plugins/table.action.js'][864] = 0; + _$jscoverage['plugins/table.action.js'][866] = 0; + _$jscoverage['plugins/table.action.js'][867] = 0; + _$jscoverage['plugins/table.action.js'][868] = 0; + _$jscoverage['plugins/table.action.js'][872] = 0; + _$jscoverage['plugins/table.action.js'][873] = 0; + _$jscoverage['plugins/table.action.js'][874] = 0; + _$jscoverage['plugins/table.action.js'][878] = 0; + _$jscoverage['plugins/table.action.js'][879] = 0; + _$jscoverage['plugins/table.action.js'][882] = 0; + _$jscoverage['plugins/table.action.js'][897] = 0; + _$jscoverage['plugins/table.action.js'][898] = 0; + _$jscoverage['plugins/table.action.js'][901] = 0; + _$jscoverage['plugins/table.action.js'][902] = 0; + _$jscoverage['plugins/table.action.js'][904] = 0; + _$jscoverage['plugins/table.action.js'][906] = 0; + _$jscoverage['plugins/table.action.js'][915] = 0; + _$jscoverage['plugins/table.action.js'][916] = 0; + _$jscoverage['plugins/table.action.js'][917] = 0; + _$jscoverage['plugins/table.action.js'][918] = 0; + _$jscoverage['plugins/table.action.js'][924] = 0; + _$jscoverage['plugins/table.action.js'][925] = 0; + _$jscoverage['plugins/table.action.js'][927] = 0; + _$jscoverage['plugins/table.action.js'][934] = 0; + _$jscoverage['plugins/table.action.js'][935] = 0; + _$jscoverage['plugins/table.action.js'][936] = 0; + _$jscoverage['plugins/table.action.js'][938] = 0; + _$jscoverage['plugins/table.action.js'][940] = 0; + _$jscoverage['plugins/table.action.js'][947] = 0; + _$jscoverage['plugins/table.action.js'][948] = 0; + _$jscoverage['plugins/table.action.js'][949] = 0; + _$jscoverage['plugins/table.action.js'][950] = 0; + _$jscoverage['plugins/table.action.js'][951] = 0; + _$jscoverage['plugins/table.action.js'][952] = 0; + _$jscoverage['plugins/table.action.js'][953] = 0; + _$jscoverage['plugins/table.action.js'][955] = 0; + _$jscoverage['plugins/table.action.js'][958] = 0; + _$jscoverage['plugins/table.action.js'][960] = 0; + _$jscoverage['plugins/table.action.js'][968] = 0; + _$jscoverage['plugins/table.action.js'][970] = 0; + _$jscoverage['plugins/table.action.js'][973] = 0; + _$jscoverage['plugins/table.action.js'][974] = 0; + _$jscoverage['plugins/table.action.js'][975] = 0; + _$jscoverage['plugins/table.action.js'][976] = 0; + _$jscoverage['plugins/table.action.js'][977] = 0; + _$jscoverage['plugins/table.action.js'][979] = 0; + _$jscoverage['plugins/table.action.js'][989] = 0; + _$jscoverage['plugins/table.action.js'][990] = 0; + _$jscoverage['plugins/table.action.js'][993] = 0; + _$jscoverage['plugins/table.action.js'][995] = 0; + _$jscoverage['plugins/table.action.js'][999] = 0; + _$jscoverage['plugins/table.action.js'][1006] = 0; + _$jscoverage['plugins/table.action.js'][1008] = 0; + _$jscoverage['plugins/table.action.js'][1017] = 0; + _$jscoverage['plugins/table.action.js'][1024] = 0; + _$jscoverage['plugins/table.action.js'][1026] = 0; + _$jscoverage['plugins/table.action.js'][1028] = 0; + _$jscoverage['plugins/table.action.js'][1037] = 0; + _$jscoverage['plugins/table.action.js'][1038] = 0; + _$jscoverage['plugins/table.action.js'][1040] = 0; + _$jscoverage['plugins/table.action.js'][1041] = 0; + _$jscoverage['plugins/table.action.js'][1044] = 0; + _$jscoverage['plugins/table.action.js'][1045] = 0; + _$jscoverage['plugins/table.action.js'][1047] = 0; + _$jscoverage['plugins/table.action.js'][1048] = 0; + _$jscoverage['plugins/table.action.js'][1050] = 0; + _$jscoverage['plugins/table.action.js'][1051] = 0; + _$jscoverage['plugins/table.action.js'][1053] = 0; + _$jscoverage['plugins/table.action.js'][1054] = 0; + _$jscoverage['plugins/table.action.js'][1056] = 0; + _$jscoverage['plugins/table.action.js'][1059] = 0; + _$jscoverage['plugins/table.action.js'][1061] = 0; + _$jscoverage['plugins/table.action.js'][1062] = 0; + _$jscoverage['plugins/table.action.js'][1065] = 0; + _$jscoverage['plugins/table.action.js'][1071] = 0; + _$jscoverage['plugins/table.action.js'][1072] = 0; + _$jscoverage['plugins/table.action.js'][1075] = 0; + _$jscoverage['plugins/table.action.js'][1076] = 0; + _$jscoverage['plugins/table.action.js'][1077] = 0; + _$jscoverage['plugins/table.action.js'][1078] = 0; + _$jscoverage['plugins/table.action.js'][1079] = 0; + _$jscoverage['plugins/table.action.js'][1082] = 0; + _$jscoverage['plugins/table.action.js'][1083] = 0; + _$jscoverage['plugins/table.action.js'][1084] = 0; + _$jscoverage['plugins/table.action.js'][1086] = 0; + _$jscoverage['plugins/table.action.js'][1087] = 0; + _$jscoverage['plugins/table.action.js'][1088] = 0; + _$jscoverage['plugins/table.action.js'][1094] = 0; + _$jscoverage['plugins/table.action.js'][1100] = 0; + _$jscoverage['plugins/table.action.js'][1101] = 0; + _$jscoverage['plugins/table.action.js'][1102] = 0; + _$jscoverage['plugins/table.action.js'][1106] = 0; + _$jscoverage['plugins/table.action.js'][1107] = 0; + _$jscoverage['plugins/table.action.js'][1108] = 0; + _$jscoverage['plugins/table.action.js'][1109] = 0; + _$jscoverage['plugins/table.action.js'][1110] = 0; + _$jscoverage['plugins/table.action.js'][1111] = 0; + _$jscoverage['plugins/table.action.js'][1112] = 0; + _$jscoverage['plugins/table.action.js'][1114] = 0; + _$jscoverage['plugins/table.action.js'][1116] = 0; + _$jscoverage['plugins/table.action.js'][1117] = 0; + _$jscoverage['plugins/table.action.js'][1118] = 0; + _$jscoverage['plugins/table.action.js'][1119] = 0; + _$jscoverage['plugins/table.action.js'][1121] = 0; + _$jscoverage['plugins/table.action.js'][1122] = 0; + _$jscoverage['plugins/table.action.js'][1123] = 0; + _$jscoverage['plugins/table.action.js'][1124] = 0; + _$jscoverage['plugins/table.action.js'][1128] = 0; + _$jscoverage['plugins/table.action.js'][1129] = 0; + _$jscoverage['plugins/table.action.js'][1133] = 0; + _$jscoverage['plugins/table.action.js'][1135] = 0; + _$jscoverage['plugins/table.action.js'][1137] = 0; + _$jscoverage['plugins/table.action.js'][1140] = 0; + _$jscoverage['plugins/table.action.js'][1142] = 0; + _$jscoverage['plugins/table.action.js'][1146] = 0; + _$jscoverage['plugins/table.action.js'][1148] = 0; + _$jscoverage['plugins/table.action.js'][1152] = 0; + _$jscoverage['plugins/table.action.js'][1155] = 0; + _$jscoverage['plugins/table.action.js'][1157] = 0; + _$jscoverage['plugins/table.action.js'][1159] = 0; + _$jscoverage['plugins/table.action.js'][1161] = 0; + _$jscoverage['plugins/table.action.js'][1162] = 0; + _$jscoverage['plugins/table.action.js'][1163] = 0; + _$jscoverage['plugins/table.action.js'][1166] = 0; + _$jscoverage['plugins/table.action.js'][1170] = 0; + _$jscoverage['plugins/table.action.js'][1172] = 0; + _$jscoverage['plugins/table.action.js'][1174] = 0; + _$jscoverage['plugins/table.action.js'][1194] = 0; + _$jscoverage['plugins/table.action.js'][1196] = 0; + _$jscoverage['plugins/table.action.js'][1199] = 0; + _$jscoverage['plugins/table.action.js'][1200] = 0; + _$jscoverage['plugins/table.action.js'][1202] = 0; + _$jscoverage['plugins/table.action.js'][1203] = 0; + _$jscoverage['plugins/table.action.js'][1204] = 0; + _$jscoverage['plugins/table.action.js'][1205] = 0; + _$jscoverage['plugins/table.action.js'][1206] = 0; + _$jscoverage['plugins/table.action.js'][1209] = 0; + _$jscoverage['plugins/table.action.js'][1210] = 0; + _$jscoverage['plugins/table.action.js'][1211] = 0; + _$jscoverage['plugins/table.action.js'][1212] = 0; + _$jscoverage['plugins/table.action.js'][1215] = 0; + _$jscoverage['plugins/table.action.js'][1222] = 0; + _$jscoverage['plugins/table.action.js'][1224] = 0; + _$jscoverage['plugins/table.action.js'][1225] = 0; + _$jscoverage['plugins/table.action.js'][1228] = 0; + _$jscoverage['plugins/table.action.js'][1231] = 0; + _$jscoverage['plugins/table.action.js'][1233] = 0; + _$jscoverage['plugins/table.action.js'][1234] = 0; + _$jscoverage['plugins/table.action.js'][1239] = 0; + _$jscoverage['plugins/table.action.js'][1241] = 0; + _$jscoverage['plugins/table.action.js'][1244] = 0; + _$jscoverage['plugins/table.action.js'][1246] = 0; + _$jscoverage['plugins/table.action.js'][1248] = 0; + _$jscoverage['plugins/table.action.js'][1249] = 0; + _$jscoverage['plugins/table.action.js'][1254] = 0; + _$jscoverage['plugins/table.action.js'][1258] = 0; + _$jscoverage['plugins/table.action.js'][1259] = 0; + _$jscoverage['plugins/table.action.js'][1260] = 0; + _$jscoverage['plugins/table.action.js'][1263] = 0; + _$jscoverage['plugins/table.action.js'][1265] = 0; + _$jscoverage['plugins/table.action.js'][1268] = 0; + _$jscoverage['plugins/table.action.js'][1270] = 0; + _$jscoverage['plugins/table.action.js'][1271] = 0; + _$jscoverage['plugins/table.action.js'][1272] = 0; + _$jscoverage['plugins/table.action.js'][1277] = 0; + _$jscoverage['plugins/table.action.js'][1282] = 0; + _$jscoverage['plugins/table.action.js'][1284] = 0; + _$jscoverage['plugins/table.action.js'][1286] = 0; + _$jscoverage['plugins/table.action.js'][1287] = 0; + _$jscoverage['plugins/table.action.js'][1289] = 0; + _$jscoverage['plugins/table.action.js'][1290] = 0; + _$jscoverage['plugins/table.action.js'][1291] = 0; + _$jscoverage['plugins/table.action.js'][1293] = 0; + _$jscoverage['plugins/table.action.js'][1294] = 0; + _$jscoverage['plugins/table.action.js'][1295] = 0; + _$jscoverage['plugins/table.action.js'][1296] = 0; + _$jscoverage['plugins/table.action.js'][1297] = 0; + _$jscoverage['plugins/table.action.js'][1299] = 0; + _$jscoverage['plugins/table.action.js'][1300] = 0; + _$jscoverage['plugins/table.action.js'][1303] = 0; + _$jscoverage['plugins/table.action.js'][1305] = 0; + _$jscoverage['plugins/table.action.js'][1306] = 0; + _$jscoverage['plugins/table.action.js'][1309] = 0; + _$jscoverage['plugins/table.action.js'][1311] = 0; + _$jscoverage['plugins/table.action.js'][1313] = 0; + _$jscoverage['plugins/table.action.js'][1314] = 0; + _$jscoverage['plugins/table.action.js'][1316] = 0; + _$jscoverage['plugins/table.action.js'][1321] = 0; + _$jscoverage['plugins/table.action.js'][1322] = 0; + _$jscoverage['plugins/table.action.js'][1325] = 0; + _$jscoverage['plugins/table.action.js'][1327] = 0; + _$jscoverage['plugins/table.action.js'][1328] = 0; + _$jscoverage['plugins/table.action.js'][1329] = 0; + _$jscoverage['plugins/table.action.js'][1335] = 0; + _$jscoverage['plugins/table.action.js'][1336] = 0; + _$jscoverage['plugins/table.action.js'][1338] = 0; + _$jscoverage['plugins/table.action.js'][1342] = 0; + _$jscoverage['plugins/table.action.js'][1343] = 0; + _$jscoverage['plugins/table.action.js'][1344] = 0; + _$jscoverage['plugins/table.action.js'][1345] = 0; + _$jscoverage['plugins/table.action.js'][1346] = 0; + _$jscoverage['plugins/table.action.js'][1347] = 0; + _$jscoverage['plugins/table.action.js'][1350] = 0; + _$jscoverage['plugins/table.action.js'][1353] = 0; + _$jscoverage['plugins/table.action.js'][1354] = 0; + _$jscoverage['plugins/table.action.js'][1356] = 0; + _$jscoverage['plugins/table.action.js'][1358] = 0; + _$jscoverage['plugins/table.action.js'][1360] = 0; + _$jscoverage['plugins/table.action.js'][1361] = 0; + _$jscoverage['plugins/table.action.js'][1363] = 0; + _$jscoverage['plugins/table.action.js'][1366] = 0; + _$jscoverage['plugins/table.action.js'][1368] = 0; + _$jscoverage['plugins/table.action.js'][1369] = 0; + _$jscoverage['plugins/table.action.js'][1371] = 0; + _$jscoverage['plugins/table.action.js'][1372] = 0; + _$jscoverage['plugins/table.action.js'][1375] = 0; + _$jscoverage['plugins/table.action.js'][1376] = 0; + _$jscoverage['plugins/table.action.js'][1378] = 0; + _$jscoverage['plugins/table.action.js'][1379] = 0; + _$jscoverage['plugins/table.action.js'][1380] = 0; + _$jscoverage['plugins/table.action.js'][1383] = 0; + _$jscoverage['plugins/table.action.js'][1384] = 0; + _$jscoverage['plugins/table.action.js'][1385] = 0; + _$jscoverage['plugins/table.action.js'][1386] = 0; + _$jscoverage['plugins/table.action.js'][1387] = 0; + _$jscoverage['plugins/table.action.js'][1388] = 0; + _$jscoverage['plugins/table.action.js'][1389] = 0; + _$jscoverage['plugins/table.action.js'][1392] = 0; + _$jscoverage['plugins/table.action.js'][1394] = 0; + _$jscoverage['plugins/table.action.js'][1395] = 0; + _$jscoverage['plugins/table.action.js'][1396] = 0; + _$jscoverage['plugins/table.action.js'][1397] = 0; + _$jscoverage['plugins/table.action.js'][1399] = 0; + _$jscoverage['plugins/table.action.js'][1402] = 0; + _$jscoverage['plugins/table.action.js'][1403] = 0; + _$jscoverage['plugins/table.action.js'][1404] = 0; + _$jscoverage['plugins/table.action.js'][1407] = 0; + _$jscoverage['plugins/table.action.js'][1408] = 0; + _$jscoverage['plugins/table.action.js'][1412] = 0; + _$jscoverage['plugins/table.action.js'][1413] = 0; + _$jscoverage['plugins/table.action.js'][1415] = 0; + _$jscoverage['plugins/table.action.js'][1418] = 0; + _$jscoverage['plugins/table.action.js'][1420] = 0; + _$jscoverage['plugins/table.action.js'][1421] = 0; + _$jscoverage['plugins/table.action.js'][1424] = 0; + _$jscoverage['plugins/table.action.js'][1426] = 0; + _$jscoverage['plugins/table.action.js'][1428] = 0; + _$jscoverage['plugins/table.action.js'][1431] = 0; + _$jscoverage['plugins/table.action.js'][1432] = 0; + _$jscoverage['plugins/table.action.js'][1433] = 0; + _$jscoverage['plugins/table.action.js'][1434] = 0; + _$jscoverage['plugins/table.action.js'][1435] = 0; + _$jscoverage['plugins/table.action.js'][1436] = 0; + _$jscoverage['plugins/table.action.js'][1438] = 0; + _$jscoverage['plugins/table.action.js'][1439] = 0; + _$jscoverage['plugins/table.action.js'][1443] = 0; + _$jscoverage['plugins/table.action.js'][1446] = 0; + _$jscoverage['plugins/table.action.js'][1447] = 0; + _$jscoverage['plugins/table.action.js'][1449] = 0; + _$jscoverage['plugins/table.action.js'][1450] = 0; + _$jscoverage['plugins/table.action.js'][1451] = 0; + _$jscoverage['plugins/table.action.js'][1454] = 0; + _$jscoverage['plugins/table.action.js'][1455] = 0; + _$jscoverage['plugins/table.action.js'][1456] = 0; + _$jscoverage['plugins/table.action.js'][1459] = 0; + _$jscoverage['plugins/table.action.js'][1461] = 0; + _$jscoverage['plugins/table.action.js'][1462] = 0; + _$jscoverage['plugins/table.action.js'][1465] = 0; + _$jscoverage['plugins/table.action.js'][1468] = 0; + _$jscoverage['plugins/table.action.js'][1469] = 0; + _$jscoverage['plugins/table.action.js'][1472] = 0; + _$jscoverage['plugins/table.action.js'][1474] = 0; + _$jscoverage['plugins/table.action.js'][1476] = 0; + _$jscoverage['plugins/table.action.js'][1478] = 0; + _$jscoverage['plugins/table.action.js'][1480] = 0; + _$jscoverage['plugins/table.action.js'][1481] = 0; + _$jscoverage['plugins/table.action.js'][1487] = 0; + _$jscoverage['plugins/table.action.js'][1488] = 0; + _$jscoverage['plugins/table.action.js'][1496] = 0; + _$jscoverage['plugins/table.action.js'][1497] = 0; + _$jscoverage['plugins/table.action.js'][1500] = 0; + _$jscoverage['plugins/table.action.js'][1501] = 0; + _$jscoverage['plugins/table.action.js'][1502] = 0; + _$jscoverage['plugins/table.action.js'][1503] = 0; + _$jscoverage['plugins/table.action.js'][1504] = 0; + _$jscoverage['plugins/table.action.js'][1507] = 0; + _$jscoverage['plugins/table.action.js'][1508] = 0; + _$jscoverage['plugins/table.action.js'][1518] = 0; + _$jscoverage['plugins/table.action.js'][1520] = 0; + _$jscoverage['plugins/table.action.js'][1521] = 0; + _$jscoverage['plugins/table.action.js'][1524] = 0; + _$jscoverage['plugins/table.action.js'][1525] = 0; + _$jscoverage['plugins/table.action.js'][1529] = 0; + _$jscoverage['plugins/table.action.js'][1534] = 0; + _$jscoverage['plugins/table.action.js'][1536] = 0; + _$jscoverage['plugins/table.action.js'][1537] = 0; + _$jscoverage['plugins/table.action.js'][1539] = 0; + _$jscoverage['plugins/table.action.js'][1542] = 0; + _$jscoverage['plugins/table.action.js'][1545] = 0; + _$jscoverage['plugins/table.action.js'][1547] = 0; + _$jscoverage['plugins/table.action.js'][1549] = 0; + _$jscoverage['plugins/table.action.js'][1552] = 0; + _$jscoverage['plugins/table.action.js'][1554] = 0; + _$jscoverage['plugins/table.action.js'][1556] = 0; + _$jscoverage['plugins/table.action.js'][1558] = 0; + _$jscoverage['plugins/table.action.js'][1563] = 0; + _$jscoverage['plugins/table.action.js'][1565] = 0; + _$jscoverage['plugins/table.action.js'][1567] = 0; + _$jscoverage['plugins/table.action.js'][1568] = 0; + _$jscoverage['plugins/table.action.js'][1573] = 0; + _$jscoverage['plugins/table.action.js'][1581] = 0; + _$jscoverage['plugins/table.action.js'][1589] = 0; + _$jscoverage['plugins/table.action.js'][1591] = 0; + _$jscoverage['plugins/table.action.js'][1593] = 0; + _$jscoverage['plugins/table.action.js'][1595] = 0; + _$jscoverage['plugins/table.action.js'][1599] = 0; + _$jscoverage['plugins/table.action.js'][1603] = 0; + _$jscoverage['plugins/table.action.js'][1606] = 0; + _$jscoverage['plugins/table.action.js'][1608] = 0; + _$jscoverage['plugins/table.action.js'][1609] = 0; + _$jscoverage['plugins/table.action.js'][1612] = 0; + _$jscoverage['plugins/table.action.js'][1615] = 0; + _$jscoverage['plugins/table.action.js'][1617] = 0; + _$jscoverage['plugins/table.action.js'][1620] = 0; + _$jscoverage['plugins/table.action.js'][1622] = 0; + _$jscoverage['plugins/table.action.js'][1625] = 0; + _$jscoverage['plugins/table.action.js'][1626] = 0; + _$jscoverage['plugins/table.action.js'][1634] = 0; + _$jscoverage['plugins/table.action.js'][1636] = 0; + _$jscoverage['plugins/table.action.js'][1640] = 0; + _$jscoverage['plugins/table.action.js'][1642] = 0; + _$jscoverage['plugins/table.action.js'][1648] = 0; + _$jscoverage['plugins/table.action.js'][1650] = 0; + _$jscoverage['plugins/table.action.js'][1654] = 0; + _$jscoverage['plugins/table.action.js'][1656] = 0; + _$jscoverage['plugins/table.action.js'][1657] = 0; + _$jscoverage['plugins/table.action.js'][1661] = 0; + _$jscoverage['plugins/table.action.js'][1668] = 0; + _$jscoverage['plugins/table.action.js'][1670] = 0; + _$jscoverage['plugins/table.action.js'][1672] = 0; + _$jscoverage['plugins/table.action.js'][1674] = 0; + _$jscoverage['plugins/table.action.js'][1676] = 0; + _$jscoverage['plugins/table.action.js'][1679] = 0; + _$jscoverage['plugins/table.action.js'][1682] = 0; + _$jscoverage['plugins/table.action.js'][1687] = 0; + _$jscoverage['plugins/table.action.js'][1691] = 0; + _$jscoverage['plugins/table.action.js'][1693] = 0; + _$jscoverage['plugins/table.action.js'][1695] = 0; + _$jscoverage['plugins/table.action.js'][1702] = 0; + _$jscoverage['plugins/table.action.js'][1703] = 0; + _$jscoverage['plugins/table.action.js'][1705] = 0; + _$jscoverage['plugins/table.action.js'][1706] = 0; + _$jscoverage['plugins/table.action.js'][1708] = 0; + _$jscoverage['plugins/table.action.js'][1710] = 0; + _$jscoverage['plugins/table.action.js'][1712] = 0; + _$jscoverage['plugins/table.action.js'][1714] = 0; + _$jscoverage['plugins/table.action.js'][1716] = 0; + _$jscoverage['plugins/table.action.js'][1718] = 0; + _$jscoverage['plugins/table.action.js'][1720] = 0; + _$jscoverage['plugins/table.action.js'][1721] = 0; + _$jscoverage['plugins/table.action.js'][1723] = 0; + _$jscoverage['plugins/table.action.js'][1725] = 0; + _$jscoverage['plugins/table.action.js'][1727] = 0; + _$jscoverage['plugins/table.action.js'][1731] = 0; + _$jscoverage['plugins/table.action.js'][1733] = 0; + _$jscoverage['plugins/table.action.js'][1737] = 0; + _$jscoverage['plugins/table.action.js'][1738] = 0; + _$jscoverage['plugins/table.action.js'][1739] = 0; + _$jscoverage['plugins/table.action.js'][1740] = 0; + _$jscoverage['plugins/table.action.js'][1749] = 0; + _$jscoverage['plugins/table.action.js'][1752] = 0; + _$jscoverage['plugins/table.action.js'][1753] = 0; + _$jscoverage['plugins/table.action.js'][1754] = 0; + _$jscoverage['plugins/table.action.js'][1755] = 0; + _$jscoverage['plugins/table.action.js'][1756] = 0; + _$jscoverage['plugins/table.action.js'][1765] = 0; + _$jscoverage['plugins/table.action.js'][1766] = 0; + _$jscoverage['plugins/table.action.js'][1767] = 0; + _$jscoverage['plugins/table.action.js'][1773] = 0; + _$jscoverage['plugins/table.action.js'][1775] = 0; + _$jscoverage['plugins/table.action.js'][1776] = 0; + _$jscoverage['plugins/table.action.js'][1777] = 0; + _$jscoverage['plugins/table.action.js'][1779] = 0; + _$jscoverage['plugins/table.action.js'][1781] = 0; + _$jscoverage['plugins/table.action.js'][1782] = 0; + _$jscoverage['plugins/table.action.js'][1792] = 0; + _$jscoverage['plugins/table.action.js'][1793] = 0; + _$jscoverage['plugins/table.action.js'][1794] = 0; + _$jscoverage['plugins/table.action.js'][1795] = 0; + _$jscoverage['plugins/table.action.js'][1796] = 0; + _$jscoverage['plugins/table.action.js'][1797] = 0; + _$jscoverage['plugins/table.action.js'][1798] = 0; + _$jscoverage['plugins/table.action.js'][1799] = 0; + _$jscoverage['plugins/table.action.js'][1800] = 0; + _$jscoverage['plugins/table.action.js'][1802] = 0; + _$jscoverage['plugins/table.action.js'][1809] = 0; + _$jscoverage['plugins/table.action.js'][1810] = 0; + _$jscoverage['plugins/table.action.js'][1811] = 0; + _$jscoverage['plugins/table.action.js'][1817] = 0; + _$jscoverage['plugins/table.action.js'][1819] = 0; + _$jscoverage['plugins/table.action.js'][1822] = 0; + _$jscoverage['plugins/table.action.js'][1823] = 0; + _$jscoverage['plugins/table.action.js'][1826] = 0; + _$jscoverage['plugins/table.action.js'][1830] = 0; + _$jscoverage['plugins/table.action.js'][1831] = 0; + _$jscoverage['plugins/table.action.js'][1834] = 0; + _$jscoverage['plugins/table.action.js'][1836] = 0; + _$jscoverage['plugins/table.action.js'][1839] = 0; + _$jscoverage['plugins/table.action.js'][1840] = 0; + _$jscoverage['plugins/table.action.js'][1843] = 0; + _$jscoverage['plugins/table.action.js'][1845] = 0; + _$jscoverage['plugins/table.action.js'][1848] = 0; + _$jscoverage['plugins/table.action.js'][1849] = 0; + _$jscoverage['plugins/table.action.js'][1856] = 0; +} +_$jscoverage['plugins/table.action.js'].source = ["/*"," * Created with JetBrains PhpStorm."," * User: taoqili"," * Date: 12-10-12"," * Time: 上午10:05"," * To change this template use File | Settings | File Templates."," */","UE.plugins['table'] = function () {"," var me = this,"," tabTimer = null,"," //拖动计时器"," tableDragTimer = null,"," //双击计时器"," tableResizeTimer = null,"," //单元格最小宽度"," cellMinWidth = 5,"," isInResizeBuffer = false,"," //单元格边框大小"," cellBorderWidth = 5,"," //鼠标偏移距离"," offsetOfTableCell = 10,"," //记录在有限时间内的点击状态, 共有3个取值, 0, 1, 2。 0代表未初始化, 1代表单击了1次,2代表2次"," singleClickState = 0,"," userActionStatus = null,"," //双击允许的时间范围"," dblclickTime = 360,"," UT = UE.UETable,"," getUETable = function (tdOrTable) {"," return UT.getUETable(tdOrTable);"," },"," getUETableBySelected = function (editor) {"," return UT.getUETableBySelected(editor);"," },"," getDefaultValue = function (editor, table) {"," return UT.getDefaultValue(editor, table);"," },"," removeSelectedClass = function (cells) {"," return UT.removeSelectedClass(cells);"," };",""," function showError(e) {","// throw e;"," }"," me.ready(function(){"," var me = this;"," var orgGetText = me.selection.getText;"," me.selection.getText = function(){"," var table = getUETableBySelected(me);"," if(table){"," var str = '';"," utils.each(table.selectedTds,function(td){"," str += td[browser.ie?'innerText':'textContent'];"," })"," return str;"," }else{"," return orgGetText.call(me.selection)"," }",""," }"," })",""," //处理拖动及框选相关方法"," var startTd = null, //鼠标按下时的锚点td"," currentTd = null, //当前鼠标经过时的td"," onDrag = \"\", //指示当前拖动状态,其值可为\"\",\"h\",\"v\" ,分别表示未拖动状态,横向拖动状态,纵向拖动状态,用于鼠标移动过程中的判断"," onBorder = false, //检测鼠标按下时是否处在单元格边缘位置"," dragButton = null,"," dragOver = false,"," dragLine = null, //模拟的拖动线"," dragTd = null; //发生拖动的目标td",""," var mousedown = false,"," //todo 判断混乱模式"," needIEHack = true;",""," me.setOpt({"," 'maxColNum':20,"," 'maxRowNum':100,"," 'defaultCols':5,"," 'defaultRows':5,"," 'tdvalign':'top',"," 'cursorpath':me.options.UEDITOR_HOME_URL + \"themes/default/images/cursor_\","," 'tableDragable':false,"," 'classList':[\"ue-table-interlace-color-single\",\"ue-table-interlace-color-double\"]"," });"," me.getUETable = getUETable;"," var commands = {"," 'deletetable':1,"," 'inserttable':1,"," 'cellvalign':1,"," 'insertcaption':1,"," 'deletecaption':1,"," 'inserttitle':1,"," 'deletetitle':1,"," \"mergeright\":1,"," \"mergedown\":1,"," \"mergecells\":1,"," \"insertrow\":1,"," \"insertrownext\":1,"," \"deleterow\":1,"," \"insertcol\":1,"," \"insertcolnext\":1,"," \"deletecol\":1,"," \"splittocells\":1,"," \"splittorows\":1,"," \"splittocols\":1,"," \"adaptbytext\":1,"," \"adaptbywindow\":1,"," \"adaptbycustomer\":1,"," \"insertparagraph\":1,"," \"insertparagraphbeforetable\":1,"," \"averagedistributecol\":1,"," \"averagedistributerow\":1"," };"," me.ready(function () {"," utils.cssRule('table',"," //选中的td上的样式"," '.selectTdClass{background-color:#edf5fa !important}' +"," 'table.noBorderTable td,table.noBorderTable th,table.noBorderTable caption{border:1px dashed #ddd !important}' +"," //插入的表格的默认样式"," 'table{margin-bottom:10px;border-collapse:collapse;display:table;}' +"," 'td,th{padding: 5px 10px;border: 1px solid #DDD;}' +"," 'caption{border:1px dashed #DDD;border-bottom:0;padding:3px;text-align:center;}' +"," 'th{border-top:2px solid #BBB;background:#F7F7F7;}' +"," '.ue-table-interlace-color-single{ background-color: #fcfcfc; } .ue-table-interlace-color-double{ background-color: #f7faff; }' +"," 'td p{margin:0;padding:0;}', me.document);",""," var tableCopyList, isFullCol, isFullRow;"," //注册del/backspace事件"," me.addListener('keydown', function (cmd, evt) {"," var me = this;"," var keyCode = evt.keyCode || evt.which;",""," if (keyCode == 8) {",""," var ut = getUETableBySelected(me);"," if (ut && ut.selectedTds.length) {",""," if (ut.isFullCol()) {"," me.execCommand('deletecol')"," } else if (ut.isFullRow()) {"," me.execCommand('deleterow')"," } else {"," me.fireEvent('delcells');"," }"," domUtils.preventDefault(evt);"," }",""," var caption = domUtils.findParentByTagName(me.selection.getStart(), 'caption', true),"," range = me.selection.getRange();"," if (range.collapsed && caption && isEmptyBlock(caption)) {"," me.fireEvent('saveScene');"," var table = caption.parentNode;"," domUtils.remove(caption);"," if (table) {"," range.setStart(table.rows[0].cells[0], 0).setCursor(false, true);"," }"," me.fireEvent('saveScene');"," }",""," }",""," if (keyCode == 46) {",""," ut = getUETableBySelected(me);"," if (ut) {"," me.fireEvent('saveScene');"," for (var i = 0, ci; ci = ut.selectedTds[i++];) {"," domUtils.fillNode(me.document, ci)"," }"," me.fireEvent('saveScene');"," domUtils.preventDefault(evt);",""," }",""," }"," if (keyCode == 13) {",""," var rng = me.selection.getRange(),"," caption = domUtils.findParentByTagName(rng.startContainer, 'caption', true);"," if (caption) {"," var table = domUtils.findParentByTagName(caption, 'table');"," if (!rng.collapsed) {",""," rng.deleteContents();"," me.fireEvent('saveScene');"," } else {"," if (caption) {"," rng.setStart(table.rows[0].cells[0], 0).setCursor(false, true);"," }"," }"," domUtils.preventDefault(evt);"," return;"," }"," if (rng.collapsed) {"," var table = domUtils.findParentByTagName(rng.startContainer, 'table');"," if (table) {"," var cell = table.rows[0].cells[0],"," start = domUtils.findParentByTagName(me.selection.getStart(), ['td', 'th'], true),"," preNode = table.previousSibling;"," if (cell === start && (!preNode || preNode.nodeType == 1 && preNode.tagName == 'TABLE' ) && domUtils.isStartInblock(rng)) {"," var first = domUtils.findParent(me.selection.getStart(), function(n){return domUtils.isBlockElm(n)}, true);"," if(first && ( /t(h|d)/i.test(first.tagName) || first === start.firstChild )){"," me.execCommand('insertparagraphbeforetable');"," domUtils.preventDefault(evt);"," }",""," }"," }"," }"," }",""," if ((evt.ctrlKey || evt.metaKey) && evt.keyCode == '67') {"," tableCopyList = null;"," var ut = getUETableBySelected(me);"," if (ut) {"," var tds = ut.selectedTds;"," isFullCol = ut.isFullCol();"," isFullRow = ut.isFullRow();"," tableCopyList = ["," [ut.cloneCell(tds[0],null,true)]"," ];"," for (var i = 1, ci; ci = tds[i]; i++) {"," if (ci.parentNode !== tds[i - 1].parentNode) {"," tableCopyList.push([ut.cloneCell(ci,null,true)]);"," } else {"," tableCopyList[tableCopyList.length - 1].push(ut.cloneCell(ci,null,true));"," }",""," }"," }"," }"," });"," me.addListener(\"tablehasdeleted\",function(){"," toggleDraggableState(this, false, \"\", null);"," if (dragButton)domUtils.remove(dragButton);"," });",""," me.addListener('beforepaste', function (cmd, html) {"," var me = this;"," var rng = me.selection.getRange();"," if (domUtils.findParentByTagName(rng.startContainer, 'caption', true)) {"," var div = me.document.createElement(\"div\");"," div.innerHTML = html.html;"," html.html = div[browser.ie ? 'innerText' : 'textContent'];"," return;"," }"," var table = getUETableBySelected(me);"," if (tableCopyList) {"," me.fireEvent('saveScene');"," var rng = me.selection.getRange();"," var td = domUtils.findParentByTagName(rng.startContainer, ['td', 'th'], true), tmpNode, preNode;"," if (td) {"," var ut = getUETable(td);"," if (isFullRow) {"," var rowIndex = ut.getCellInfo(td).rowIndex;"," if (td.tagName == 'TH') {"," rowIndex++;"," }"," for (var i = 0, ci; ci = tableCopyList[i++];) {"," var tr = ut.insertRow(rowIndex++, \"td\");"," for (var j = 0, cj; cj = ci[j]; j++) {"," var cell = tr.cells[j];"," if (!cell) {"," cell = tr.insertCell(j)"," }"," cell.innerHTML = cj.innerHTML;"," cj.getAttribute('width') && cell.setAttribute('width', cj.getAttribute('width'));"," cj.getAttribute('vAlign') && cell.setAttribute('vAlign', cj.getAttribute('vAlign'));"," cj.getAttribute('align') && cell.setAttribute('align', cj.getAttribute('align'));"," cj.style.cssText && (cell.style.cssText = cj.style.cssText)"," }"," for (var j = 0, cj; cj = tr.cells[j]; j++) {"," if (!ci[j])"," break;"," cj.innerHTML = ci[j].innerHTML;"," ci[j].getAttribute('width') && cj.setAttribute('width', ci[j].getAttribute('width'));"," ci[j].getAttribute('vAlign') && cj.setAttribute('vAlign', ci[j].getAttribute('vAlign'));"," ci[j].getAttribute('align') && cj.setAttribute('align', ci[j].getAttribute('align'));"," ci[j].style.cssText && (cj.style.cssText = ci[j].style.cssText)"," }"," }"," } else {"," if (isFullCol) {"," cellInfo = ut.getCellInfo(td);"," var maxColNum = 0;"," for (var j = 0, ci = tableCopyList[0], cj; cj = ci[j++];) {"," maxColNum += cj.colSpan || 1;"," }"," me.__hasEnterExecCommand = true;"," for (i = 0; i < maxColNum; i++) {"," me.execCommand('insertcol');"," }"," me.__hasEnterExecCommand = false;"," td = ut.table.rows[0].cells[cellInfo.cellIndex];"," if (td.tagName == 'TH') {"," td = ut.table.rows[1].cells[cellInfo.cellIndex];"," }"," }"," for (var i = 0, ci; ci = tableCopyList[i++];) {"," tmpNode = td;"," for (var j = 0, cj; cj = ci[j++];) {"," if (td) {"," td.innerHTML = cj.innerHTML;"," //todo 定制处理"," cj.getAttribute('width') && td.setAttribute('width', cj.getAttribute('width'));"," cj.getAttribute('vAlign') && td.setAttribute('vAlign', cj.getAttribute('vAlign'));"," cj.getAttribute('align') && td.setAttribute('align', cj.getAttribute('align'));"," cj.style.cssText && (td.style.cssText = cj.style.cssText);"," preNode = td;"," td = td.nextSibling;"," } else {"," var cloneTd = cj.cloneNode(true);"," domUtils.removeAttributes(cloneTd, ['class', 'rowSpan', 'colSpan']);",""," preNode.parentNode.appendChild(cloneTd)"," }"," }"," td = ut.getNextCell(tmpNode, true, true);"," if (!tableCopyList[i])"," break;"," if (!td) {"," var cellInfo = ut.getCellInfo(tmpNode);"," ut.table.insertRow(ut.table.rows.length);"," ut.update();"," td = ut.getVSideCell(tmpNode, true);"," }"," }"," }"," ut.update();"," } else {"," table = me.document.createElement('table');"," for (var i = 0, ci; ci = tableCopyList[i++];) {"," var tr = table.insertRow(table.rows.length);"," for (var j = 0, cj; cj = ci[j++];) {"," cloneTd = UT.cloneCell(cj,null,true);"," domUtils.removeAttributes(cloneTd, ['class']);"," tr.appendChild(cloneTd)"," }"," if (j == 2 && cloneTd.rowSpan > 1) {"," cloneTd.rowSpan = 1;"," }"," }",""," var defaultValue = getDefaultValue(me),"," width = me.body.offsetWidth -"," (needIEHack ? parseInt(domUtils.getComputedStyle(me.body, 'margin-left'), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (me.options.offsetWidth || 0);"," me.execCommand('insertHTML', '<table ' +"," ( isFullCol && isFullRow ? 'width=\"' + width + '\"' : '') +"," '>' + table.innerHTML.replace(/>\\s*</g, '><').replace(/\\bth\\b/gi, \"td\") + '</table>')"," }"," me.fireEvent('contentchange');"," me.fireEvent('saveScene');"," html.html = '';"," return true;"," } else {"," var div = me.document.createElement(\"div\"), tables;"," div.innerHTML = html.html;"," tables = div.getElementsByTagName(\"table\");"," if (domUtils.findParentByTagName(me.selection.getStart(), 'table')) {"," utils.each(tables, function (t) {"," domUtils.remove(t)"," });"," if (domUtils.findParentByTagName(me.selection.getStart(), 'caption', true)) {"," div.innerHTML = div[browser.ie ? 'innerText' : 'textContent'];"," }"," } else {"," utils.each(tables, function (table) {"," removeStyleSize(table, true);"," domUtils.removeAttributes(table, ['style', 'border']);"," utils.each(domUtils.getElementsByTagName(table, \"td\"), function (td) {"," if (isEmptyBlock(td)) {"," domUtils.fillNode(me.document, td);"," }"," removeStyleSize(td, true);","// domUtils.removeAttributes(td, ['style'])"," });"," });"," }"," html.html = div.innerHTML;"," }"," });",""," me.addListener('afterpaste', function () {"," utils.each(domUtils.getElementsByTagName(me.body, \"table\"), function (table) {"," if (table.offsetWidth > me.body.offsetWidth) {"," var defaultValue = getDefaultValue(me, table);"," table.style.width = me.body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(me.body, 'margin-left'), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (me.options.offsetWidth || 0) + 'px'"," }"," })"," });"," me.addListener('blur', function () {"," tableCopyList = null;"," });"," var timer;"," me.addListener('keydown', function () {"," clearTimeout(timer);"," timer = setTimeout(function () {"," var rng = me.selection.getRange(),"," cell = domUtils.findParentByTagName(rng.startContainer, ['th', 'td'], true);"," if (cell) {"," var table = cell.parentNode.parentNode.parentNode;"," if (table.offsetWidth > table.getAttribute(\"width\")) {"," cell.style.wordBreak = \"break-all\";"," }"," }",""," }, 100);"," });"," me.addListener(\"selectionchange\", function () {"," toggleDraggableState(me, false, \"\", null);"," });","",""," //内容变化时触发索引更新"," //todo 可否考虑标记检测,如果不涉及表格的变化就不进行索引重建和更新"," me.addListener(\"contentchange\", function () {"," var me = this;"," //尽可能排除一些不需要更新的状况"," hideDragLine(me);"," if (getUETableBySelected(me))return;"," var rng = me.selection.getRange();"," var start = rng.startContainer;"," start = domUtils.findParentByTagName(start, ['td', 'th'], true);"," utils.each(domUtils.getElementsByTagName(me.document, 'table'), function (table) {"," if (me.fireEvent(\"excludetable\", table) === true) return;"," table.ueTable = new UT(table);"," utils.each(domUtils.getElementsByTagName(me.document, 'td'), function (td) {",""," if (domUtils.isEmptyBlock(td) && td !== start) {"," domUtils.fillNode(me.document, td);"," if (browser.ie && browser.version == 6) {"," td.innerHTML = '&nbsp;'"," }"," }"," });"," utils.each(domUtils.getElementsByTagName(me.document, 'th'), function (th) {"," if (domUtils.isEmptyBlock(th) && th !== start) {"," domUtils.fillNode(me.document, th);"," if (browser.ie && browser.version == 6) {"," th.innerHTML = '&nbsp;'"," }"," }"," });"," table.onmouseover = function () {"," me.fireEvent('tablemouseover', table);"," };"," table.onmousemove = function () {"," me.fireEvent('tablemousemove', table);"," me.options.tableDragable && toggleDragButton(true, this, me);"," };"," table.onmouseout = function () {"," me.fireEvent('tablemouseout', table);"," toggleDraggableState(me, false, \"\", null);"," hideDragLine(me);"," };"," table.onclick = function (evt) {"," evt = me.window.event || evt;"," var target = getParentTdOrTh(evt.target || evt.srcElement);"," if (!target)return;"," var ut = getUETable(target),"," table = ut.table,"," cellInfo = ut.getCellInfo(target),"," cellsRange,"," rng = me.selection.getRange();","// if (\"topLeft\" == inPosition(table, mouseCoords(evt))) {","// cellsRange = ut.getCellsRange(ut.table.rows[0].cells[0], ut.getLastCell());","// ut.setSelected(cellsRange);","// return;","// }","// if (\"bottomRight\" == inPosition(table, mouseCoords(evt))) {","//","// return;","// }"," if (inTableSide(table, target, evt, true)) {"," var endTdCol = ut.getCell(ut.indexTable[ut.rowsNum - 1][cellInfo.colIndex].rowIndex, ut.indexTable[ut.rowsNum - 1][cellInfo.colIndex].cellIndex);"," if (evt.shiftKey && ut.selectedTds.length) {"," if (ut.selectedTds[0] !== endTdCol) {"," cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdCol);"," ut.setSelected(cellsRange);"," } else {"," rng && rng.selectNodeContents(endTdCol).select();"," }"," } else {"," if (target !== endTdCol) {"," cellsRange = ut.getCellsRange(target, endTdCol);"," ut.setSelected(cellsRange);"," } else {"," rng && rng.selectNodeContents(endTdCol).select();"," }"," }"," return;"," }"," if (inTableSide(table, target, evt)) {"," var endTdRow = ut.getCell(ut.indexTable[cellInfo.rowIndex][ut.colsNum - 1].rowIndex, ut.indexTable[cellInfo.rowIndex][ut.colsNum - 1].cellIndex);"," if (evt.shiftKey && ut.selectedTds.length) {"," if (ut.selectedTds[0] !== endTdRow) {"," cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdRow);"," ut.setSelected(cellsRange);"," } else {"," rng && rng.selectNodeContents(endTdRow).select();"," }"," } else {"," if (target !== endTdRow) {"," cellsRange = ut.getCellsRange(target, endTdRow);"," ut.setSelected(cellsRange);"," } else {"," rng && rng.selectNodeContents(endTdRow).select();"," }"," }"," }"," };"," });",""," switchBorderColor(me, true);"," });",""," domUtils.on(me.document, \"mousemove\", mouseMoveEvent);",""," domUtils.on(me.document, \"mouseout\", function (evt) {"," var target = evt.target || evt.srcElement;"," if (target.tagName == \"TABLE\") {"," toggleDraggableState(me, false, \"\", null);"," }"," });"," /*"," * 表格隔行变色"," */"," me.addListener(\"interlacetable\",function(type,table,classList){"," if(!table) return;"," var me = this,"," rows = table.rows,"," len = rows.length,"," getClass = function(list,index,repeat){"," return list[index] ? list[index] : repeat ? list[index % list.length]: \"\";"," };"," for(var i = 0;i<len;i++){"," rows[i].className = getClass( classList|| me.options.classList,i,true);"," }"," });"," me.addListener(\"uninterlacetable\",function(type,table){"," if(!table) return;"," var me = this,"," rows = table.rows,"," classList = me.options.classList,"," len = rows.length;"," for(var i = 0;i<len;i++){"," domUtils.removeClasses( rows[i], classList );"," }"," });",""," me.addListener(\"mousedown\", mouseDownEvent);"," me.addListener(\"mouseup\", mouseUpEvent);"," //拖动的时候不出发mouseup"," domUtils.on( me.body, 'dragstart', function( evt ){"," mouseUpEvent.call( me, 'dragstart', evt );"," });",""," var currentRowIndex = 0;"," me.addListener(\"mousedown\", function () {"," currentRowIndex = 0;"," });"," me.addListener('tabkeydown', function () {"," var range = this.selection.getRange(),"," common = range.getCommonAncestor(true, true),"," table = domUtils.findParentByTagName(common, 'table');"," if (table) {"," if (domUtils.findParentByTagName(common, 'caption', true)) {"," var cell = domUtils.getElementsByTagName(table, 'th td');"," if (cell && cell.length) {"," range.setStart(cell[0], 0).setCursor(false, true)"," }"," } else {"," var cell = domUtils.findParentByTagName(common, ['td', 'th'], true),"," ua = getUETable(cell);"," currentRowIndex = cell.rowSpan > 1 ? currentRowIndex : ua.getCellInfo(cell).rowIndex;"," var nextCell = ua.getTabNextCell(cell, currentRowIndex);"," if (nextCell) {"," if (isEmptyBlock(nextCell)) {"," range.setStart(nextCell, 0).setCursor(false, true)"," } else {"," range.selectNodeContents(nextCell).select()"," }"," } else {"," me.fireEvent('saveScene');"," me.__hasEnterExecCommand = true;"," this.execCommand('insertrownext');"," me.__hasEnterExecCommand = false;"," range = this.selection.getRange();"," range.setStart(table.rows[table.rows.length - 1].cells[0], 0).setCursor();"," me.fireEvent('saveScene');"," }"," }"," return true;"," }",""," });"," browser.ie && me.addListener('selectionchange', function () {"," toggleDraggableState(this, false, \"\", null);"," });"," me.addListener(\"keydown\", function (type, evt) {"," var me = this;"," //处理在表格的最后一个输入tab产生新的表格"," var keyCode = evt.keyCode || evt.which;"," if (keyCode == 8 || keyCode == 46) {"," return;"," }"," var notCtrlKey = !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey;"," notCtrlKey && removeSelectedClass(domUtils.getElementsByTagName(me.body, \"td\"));"," var ut = getUETableBySelected(me);"," if (!ut) return;"," notCtrlKey && ut.clearSelected();"," });",""," me.addListener(\"beforegetcontent\", function () {"," switchBorderColor(this, false);"," browser.ie && utils.each(this.document.getElementsByTagName('caption'), function (ci) {"," if (domUtils.isEmptyNode(ci)) {"," ci.innerHTML = '&nbsp;'"," }"," });"," });"," me.addListener(\"aftergetcontent\", function () {"," switchBorderColor(this, true);"," });"," me.addListener(\"getAllHtml\", function () {"," removeSelectedClass(me.document.getElementsByTagName(\"td\"));"," });"," //修正全屏状态下插入的表格宽度在非全屏状态下撑开编辑器的情况"," me.addListener(\"fullscreenchanged\", function (type, fullscreen) {"," if (!fullscreen) {"," var ratio = this.body.offsetWidth / document.body.offsetWidth,"," tables = domUtils.getElementsByTagName(this.body, \"table\");"," utils.each(tables, function (table) {"," if (table.offsetWidth < me.body.offsetWidth) return false;"," var tds = domUtils.getElementsByTagName(table, \"td\"),"," backWidths = [];"," utils.each(tds, function (td) {"," backWidths.push(td.offsetWidth);"," });"," for (var i = 0, td; td = tds[i]; i++) {"," td.setAttribute(\"width\", Math.floor(backWidths[i] * ratio));"," }"," table.setAttribute(\"width\", Math.floor(getTableWidth(me, needIEHack, getDefaultValue(me))))"," });"," }"," });",""," //重写execCommand命令,用于处理框选时的处理"," var oldExecCommand = me.execCommand;"," me.execCommand = function (cmd, datatat) {",""," var me = this,"," args = arguments;",""," cmd = cmd.toLowerCase();"," var ut = getUETableBySelected(me), tds,"," range = new dom.Range(me.document),"," cmdFun = me.commands[cmd] || UE.commands[cmd],"," result;"," if (!cmdFun) return;"," if (ut && !commands[cmd] && !cmdFun.notNeedUndo && !me.__hasEnterExecCommand) {"," me.__hasEnterExecCommand = true;"," me.fireEvent(\"beforeexeccommand\", cmd);"," tds = ut.selectedTds;"," var lastState = -2, lastValue = -2, value, state;"," for (var i = 0, td; td = tds[i]; i++) {"," if (isEmptyBlock(td)) {"," range.setStart(td, 0).setCursor(false, true)"," } else {"," range.selectNode(td).select(true);"," }"," state = me.queryCommandState(cmd);"," value = me.queryCommandValue(cmd);"," if (state != -1) {"," if (lastState !== state || lastValue !== value) {"," me._ignoreContentChange = true;"," result = oldExecCommand.apply(me, arguments);"," me._ignoreContentChange = false;",""," }"," lastState = me.queryCommandState(cmd);"," lastValue = me.queryCommandValue(cmd);"," if (domUtils.isEmptyBlock(td)) {"," domUtils.fillNode(me.document, td)"," }"," }"," }"," range.setStart(tds[0], 0).shrinkBoundary(true).setCursor(false, true);"," me.fireEvent('contentchange');"," me.fireEvent(\"afterexeccommand\", cmd);"," me.__hasEnterExecCommand = false;"," me._selectionChange();"," } else {"," result = oldExecCommand.apply(me, arguments);"," }"," return result;"," };","",""," });"," /*"," * 删除obj的宽高style,改成属性宽高"," * @param obj"," * @param replaceToProperty"," */"," function removeStyleSize(obj, replaceToProperty) {"," removeStyle(obj, \"width\", true);"," removeStyle(obj, \"height\", true);"," }",""," function removeStyle(obj, styleName, replaceToProperty) {"," if (obj.style[styleName]) {"," replaceToProperty && obj.setAttribute(styleName, parseInt(obj.style[styleName], 10));"," obj.style[styleName] = \"\";"," }"," }",""," function getParentTdOrTh(ele) {"," if (ele.tagName == \"TD\" || ele.tagName == \"TH\") return ele;"," var td;"," if (td = domUtils.findParentByTagName(ele, \"td\", true) || domUtils.findParentByTagName(ele, \"th\", true)) return td;"," return null;"," }",""," function isEmptyBlock(node) {"," var reg = new RegExp(domUtils.fillChar, 'g');"," if (node[browser.ie ? 'innerText' : 'textContent'].replace(/^\\s*$/, '').replace(reg, '').length > 0) {"," return 0;"," }"," for (var n in dtd.$isNotEmpty) {"," if (node.getElementsByTagName(n).length) {"," return 0;"," }"," }"," return 1;"," }","",""," function mouseCoords(evt) {"," if (evt.pageX || evt.pageY) {"," return { x:evt.pageX, y:evt.pageY };"," }"," return {"," x:evt.clientX + me.document.body.scrollLeft - me.document.body.clientLeft,"," y:evt.clientY + me.document.body.scrollTop - me.document.body.clientTop"," };"," }",""," function mouseMoveEvent(evt) {",""," if( isEditorDisabled() ) {"," return;"," }",""," try {",""," //普通状态下鼠标移动"," var target = getParentTdOrTh(evt.target || evt.srcElement),"," pos;",""," //区分用户的行为是拖动还是双击"," if( isInResizeBuffer ) {",""," me.body.style.webkitUserSelect = 'none';",""," if( Math.abs( userActionStatus.x - evt.clientX ) > offsetOfTableCell || Math.abs( userActionStatus.y - evt.clientY ) > offsetOfTableCell ) {"," clearTableDragTimer();"," isInResizeBuffer = false;"," singleClickState = 0;"," //drag action"," tableBorderDrag(evt);"," }"," }",""," //修改单元格大小时的鼠标移动"," if (onDrag && dragTd) {"," singleClickState = 0;"," me.body.style.webkitUserSelect = 'none';"," me.selection.getNative()[browser.ie ? 'empty' : 'removeAllRanges']();"," pos = mouseCoords(evt);"," toggleDraggableState(me, true, onDrag, pos, target);"," if (onDrag == \"h\") {"," dragLine.style.left = getPermissionX(dragTd, evt) + \"px\";"," } else if (onDrag == \"v\") {"," dragLine.style.top = getPermissionY(dragTd, evt) + \"px\";"," }"," return;"," }"," //当鼠标处于table上时,修改移动过程中的光标状态"," if (target) {"," //针对使用table作为容器的组件不触发拖拽效果"," if (me.fireEvent('excludetable', target) === true)"," return;"," pos = mouseCoords(evt);"," var state = getRelation(target, pos),"," table = domUtils.findParentByTagName(target, \"table\", true);",""," if (inTableSide(table, target, evt, true)) {"," if (me.fireEvent(\"excludetable\", table) === true) return;"," me.body.style.cursor = \"url(\" + me.options.cursorpath + \"h.png),pointer\";"," } else if (inTableSide(table, target, evt)) {"," if (me.fireEvent(\"excludetable\", table) === true) return;"," me.body.style.cursor = \"url(\" + me.options.cursorpath + \"v.png),pointer\";"," } else {"," me.body.style.cursor = \"text\";"," var curCell = target;"," if (/\\d/.test(state)) {"," state = state.replace(/\\d/, '');"," target = getUETable(target).getPreviewCell(target, state == \"v\");"," }"," //位于第一行的顶部或者第一列的左边时不可拖动"," toggleDraggableState(me, target ? !!state : false, target ? state : '', pos, target);",""," }"," } else {"," toggleDragButton(false, table, me);"," }",""," } catch (e) {"," showError(e);"," }"," }",""," var dragButtonTimer;",""," function toggleDragButton(show, table, editor) {"," if (!show) {"," if (dragOver)return;"," dragButtonTimer = setTimeout(function () {"," !dragOver && dragButton && dragButton.parentNode && dragButton.parentNode.removeChild(dragButton);"," }, 2000);"," } else {"," createDragButton(table, editor);"," }"," }",""," function createDragButton(table, editor) {"," var pos = domUtils.getXY(table),"," doc = table.ownerDocument;"," if (dragButton && dragButton.parentNode)return dragButton;"," dragButton = doc.createElement(\"div\");"," dragButton.contentEditable = false;"," dragButton.innerHTML = \"\";"," dragButton.style.cssText = \"width:15px;height:15px;background-image:url(\" + editor.options.UEDITOR_HOME_URL + \"dialogs/table/dragicon.png);position: absolute;cursor:move;top:\" + (pos.y - 15) + \"px;left:\" + (pos.x) + \"px;\";"," domUtils.unSelectable(dragButton);"," dragButton.onmouseover = function (evt) {"," dragOver = true;"," };"," dragButton.onmouseout = function (evt) {"," dragOver = false;"," };"," domUtils.on(dragButton, 'click', function (type, evt) {"," doClick(evt, this);"," });"," domUtils.on(dragButton, 'dblclick', function (type, evt) {"," doDblClick(evt);"," });"," domUtils.on(dragButton, 'dragstart', function (type, evt) {"," domUtils.preventDefault(evt);"," });"," var timer;",""," function doClick(evt, button) {"," // 部分浏览器下需要清理"," clearTimeout(timer);"," timer = setTimeout(function () {"," editor.fireEvent(\"tableClicked\", table, button);"," }, 300);"," }",""," function doDblClick(evt) {"," clearTimeout(timer);"," var ut = getUETable(table),"," start = table.rows[0].cells[0],"," end = ut.getLastCell(),"," range = ut.getCellsRange(start, end);"," editor.selection.getRange().setStart(start, 0).setCursor(false, true);"," ut.setSelected(range);"," }",""," doc.body.appendChild(dragButton);"," }","","","// function inPosition(table, pos) {","// var tablePos = domUtils.getXY(table),","// width = table.offsetWidth,","// height = table.offsetHeight;","// if (pos.x - tablePos.x < 5 && pos.y - tablePos.y < 5) {","// return \"topLeft\";","// } else if (tablePos.x + width - pos.x < 5 && tablePos.y + height - pos.y < 5) {","// return \"bottomRight\";","// }","// }",""," function inTableSide(table, cell, evt, top) {"," var pos = mouseCoords(evt),"," state = getRelation(cell, pos);",""," if (top) {"," var caption = table.getElementsByTagName(\"caption\")[0],"," capHeight = caption ? caption.offsetHeight : 0;"," return (state == \"v1\") && ((pos.y - domUtils.getXY(table).y - capHeight) < 8);"," } else {"," return (state == \"h1\") && ((pos.x - domUtils.getXY(table).x) < 8);"," }"," }",""," /*"," * 获取拖动时允许的X轴坐标"," * @param dragTd"," * @param evt"," */"," function getPermissionX(dragTd, evt) {"," var ut = getUETable(dragTd);"," if (ut) {"," var preTd = ut.getSameEndPosCells(dragTd, \"x\")[0],"," nextTd = ut.getSameStartPosXCells(dragTd)[0],"," mouseX = mouseCoords(evt).x,"," left = (preTd ? domUtils.getXY(preTd).x : domUtils.getXY(ut.table).x) + 20 ,"," right = nextTd ? domUtils.getXY(nextTd).x + nextTd.offsetWidth - 20 : (me.body.offsetWidth + 5 || parseInt(domUtils.getComputedStyle(me.body, \"width\"), 10));",""," left += cellMinWidth;"," right -= cellMinWidth;",""," return mouseX < left ? left : mouseX > right ? right : mouseX;"," }"," }",""," /*"," * 获取拖动时允许的Y轴坐标"," */"," function getPermissionY(dragTd, evt) {"," try {"," var top = domUtils.getXY(dragTd).y,"," mousePosY = mouseCoords(evt).y;"," return mousePosY < top ? top : mousePosY;"," } catch (e) {"," showError(e);"," }"," }",""," /*"," * 移动状态切换"," */"," function toggleDraggableState(editor, draggable, dir, mousePos, cell) {"," try {"," editor.body.style.cursor = dir == \"h\" ? \"col-resize\" : dir == \"v\" ? \"row-resize\" : \"text\";"," if (browser.ie) {"," if (dir && !mousedown && !getUETableBySelected(editor)) {"," getDragLine(editor, editor.document);"," showDragLineAt(dir, cell);"," } else {"," hideDragLine(editor)"," }"," }"," onBorder = draggable;"," } catch (e) {"," showError(e);"," }"," }",""," /*"," * 获取与UETable相关的resize line"," * @param uetable UETable对象"," */"," function getResizeLineByUETable() {",""," var lineId = '_UETableResizeLine',"," line = this.document.getElementById( lineId );",""," if( !line ) {"," line = this.document.createElement(\"div\");"," line.id = lineId;"," line.contnetEditable = false;"," line.setAttribute(\"unselectable\", \"on\");",""," var styles = {"," width: 2*cellBorderWidth + 1 + 'px',"," position: 'absolute',"," 'z-index': 100000,"," cursor: 'col-resize',"," background: 'red',"," display: 'none'"," };",""," //切换状态"," line.onmouseout = function(){"," this.style.display = 'none';"," };",""," utils.extend( line.style, styles );",""," this.document.body.appendChild( line );",""," }",""," return line;",""," }",""," /*"," * 更新resize-line"," */"," function updateResizeLine( cell, uetable ) {",""," var line = getResizeLineByUETable.call( this ),"," table = uetable.table,"," styles = {"," top: domUtils.getXY( table ).y + 'px',"," left: domUtils.getXY( cell).x + cell.offsetWidth - cellBorderWidth + 'px',"," display: 'block',"," height: table.offsetHeight + 'px'"," };",""," utils.extend( line.style, styles );",""," }",""," /*"," * 显示resize-line"," */"," function showResizeLine( cell ) {",""," var uetable = getUETable( cell );",""," updateResizeLine.call( this, cell, uetable );",""," }",""," /*"," * 获取鼠标与当前单元格的相对位置"," * @param ele"," * @param mousePos"," */"," function getRelation(ele, mousePos) {"," var elePos = domUtils.getXY(ele);",""," if( !elePos ) {"," return '';"," }",""," if (elePos.x + ele.offsetWidth - mousePos.x < cellBorderWidth) {"," return \"h\";"," }"," if (mousePos.x - elePos.x < cellBorderWidth) {"," return 'h1'"," }"," if (elePos.y + ele.offsetHeight - mousePos.y < cellBorderWidth) {"," return \"v\";"," }"," if (mousePos.y - elePos.y < cellBorderWidth) {"," return 'v1'"," }"," return '';"," }",""," function mouseDownEvent(type, evt) {",""," if( isEditorDisabled() ) {"," return ;"," }",""," userActionStatus = {"," x: evt.clientX,"," y: evt.clientY"," };",""," //右键菜单单独处理"," if (evt.button == 2) {"," var ut = getUETableBySelected(me),"," flag = false;",""," if (ut) {"," var td = getTargetTd(me, evt);"," utils.each(ut.selectedTds, function (ti) {"," if (ti === td) {"," flag = true;"," }"," });"," if (!flag) {"," removeSelectedClass(domUtils.getElementsByTagName(me.body, \"th td\"));"," ut.clearSelected()"," } else {"," td = ut.selectedTds[0];"," setTimeout(function () {"," me.selection.getRange().setStart(td, 0).setCursor(false, true);"," }, 0);",""," }"," }"," } else {"," tableClickHander( evt );"," }",""," }",""," //清除表格的计时器"," function clearTableTimer() {"," tabTimer && clearTimeout( tabTimer );"," tabTimer = null;"," }",""," //双击收缩"," function tableDbclickHandler(evt) {"," singleClickState = 0;"," evt = evt || me.window.event;"," var target = getParentTdOrTh(evt.target || evt.srcElement);"," if (target) {"," var h;"," if (h = getRelation(target, mouseCoords(evt))) {",""," hideDragLine( me );",""," if (h == 'h1') {"," h = 'h';"," if (inTableSide(domUtils.findParentByTagName(target, \"table\"), target, evt)) {"," me.execCommand('adaptbywindow');"," } else {"," target = getUETable(target).getPreviewCell(target);"," if (target) {"," var rng = me.selection.getRange();"," rng.selectNodeContents(target).setCursor(true, true)"," }"," }"," }"," if (h == 'h') {"," var ut = getUETable(target),"," table = ut.table,"," cells = getCellsByMoveBorder( target, table, true );",""," cells = extractArray( cells, 'left' );",""," ut.width = ut.offsetWidth;",""," var oldWidth = [],"," newWidth = [];",""," utils.each( cells, function( cell ){",""," oldWidth.push( cell.offsetWidth );",""," } );",""," utils.each( cells, function( cell ){",""," cell.removeAttribute(\"width\");",""," } );",""," window.setTimeout( function(){",""," //是否允许改变"," var changeable = true;",""," utils.each( cells, function( cell, index ){",""," var width = cell.offsetWidth;",""," if( width > oldWidth[index] ) {"," changeable = false;"," return false;"," }",""," newWidth.push( width );",""," } );",""," var change = changeable ? newWidth : oldWidth;",""," utils.each( cells, function( cell, index ){",""," cell.width = change[index] - getTabcellSpace();",""," } );","",""," }, 0 );","","// minWidth -= cellMinWidth;","//","// table.removeAttribute(\"width\");","// utils.each(cells, function (cell) {","// cell.style.width = \"\";","// cell.width -= minWidth;","// });",""," }"," }"," }"," }",""," function tableClickHander( evt ) {",""," removeSelectedClass(domUtils.getElementsByTagName(me.body, \"td th\"));"," //trace:3113"," //选中单元格,点击table外部,不会清掉table上挂的ueTable,会引起getUETableBySelected方法返回值"," utils.each(me.document.getElementsByTagName('table'), function (t) {"," t.ueTable = null;"," });"," startTd = getTargetTd(me, evt);"," if( !startTd ) return;"," var table = domUtils.findParentByTagName(startTd, \"table\", true);"," ut = getUETable(table);"," ut && ut.clearSelected();",""," //判断当前鼠标状态"," if (!onBorder) {"," me.document.body.style.webkitUserSelect = '';"," mousedown = true;"," me.addListener('mouseover', mouseOverEvent);"," } else {"," //边框上的动作处理"," borderActionHandler( evt );"," }","",""," }",""," //处理表格边框上的动作, 这里做延时处理,避免两种动作互相影响"," function borderActionHandler( evt ) {",""," if ( browser.ie ) {"," evt = reconstruct(evt );"," }",""," clearTableDragTimer();",""," //是否正在等待resize的缓冲中"," isInResizeBuffer = true;",""," tableDragTimer = setTimeout(function(){"," tableBorderDrag( evt );"," }, dblclickTime);",""," }",""," function extractArray( originArr, key ) {",""," var result = [],"," tmp = null;",""," for( var i = 0, len = originArr.length; i<len; i++ ) {",""," tmp = originArr[ i ][ key ];",""," if( tmp ) {"," result.push( tmp );"," }",""," }",""," return result;",""," }",""," function clearTableDragTimer() {"," tableDragTimer && clearTimeout(tableDragTimer);"," tableDragTimer = null;"," }",""," function reconstruct( obj ) {",""," var attrs = ['pageX', 'pageY', 'clientX', 'clientY', 'srcElement', 'target'],"," newObj = {};",""," if( obj ) {",""," for( var i = 0, key, val; key = attrs[i]; i++ ) {"," val=obj[ key ];"," val && (newObj[ key ] = val);"," }",""," }",""," return newObj;",""," }",""," //边框拖动"," function tableBorderDrag( evt ) {",""," isInResizeBuffer = false;",""," if( !startTd ) return;"," var state = Math.abs( userActionStatus.x - evt.clientX ) >= Math.abs( userActionStatus.y - evt.clientY ) ? 'h' : 'v';","// var state = getRelation(startTd, mouseCoords(evt));"," if (/\\d/.test(state)) {"," state = state.replace(/\\d/, '');"," startTd = getUETable(startTd).getPreviewCell(startTd, state == 'v');"," }"," hideDragLine(me);"," getDragLine(me, me.document);"," me.fireEvent('saveScene');"," showDragLineAt(state, startTd);"," mousedown = true;"," //拖动开始"," onDrag = state;"," dragTd = startTd;"," }",""," function mouseUpEvent(type, evt) {",""," if( isEditorDisabled() ) {"," return ;"," }",""," clearTableDragTimer();",""," isInResizeBuffer = false;",""," if( onBorder ) {"," singleClickState = ++singleClickState % 3;",""," userActionStatus = {"," x: evt.clientX,"," y: evt.clientY"," };",""," tableResizeTimer = setTimeout(function(){"," singleClickState > 0 && singleClickState--;"," }, dblclickTime );",""," if( singleClickState === 2 ) {",""," singleClickState = 0;"," tableDbclickHandler(evt);"," return;",""," }",""," }",""," if (evt.button == 2)return;"," var me = this;"," //清除表格上原生跨选问题"," var range = me.selection.getRange(),"," start = domUtils.findParentByTagName(range.startContainer, 'table', true),"," end = domUtils.findParentByTagName(range.endContainer, 'table', true);",""," if (start || end) {"," if (start === end) {"," start = domUtils.findParentByTagName(range.startContainer, ['td', 'th', 'caption'], true);"," end = domUtils.findParentByTagName(range.endContainer, ['td', 'th', 'caption'], true);"," if (start !== end) {"," me.selection.clearRange()"," }"," } else {"," me.selection.clearRange()"," }"," }"," mousedown = false;"," me.document.body.style.webkitUserSelect = '';"," //拖拽状态下的mouseUP"," if ( onDrag && dragTd ) {",""," me.selection.getNative()[browser.ie ? 'empty' : 'removeAllRanges']();",""," singleClickState = 0;"," dragLine = me.document.getElementById('ue_tableDragLine');",""," var dragTdPos = domUtils.getXY(dragTd),"," dragLinePos = domUtils.getXY(dragLine);",""," switch (onDrag) {"," case \"h\":"," changeColWidth(dragTd, dragLinePos.x - dragTdPos.x);"," break;"," case \"v\":"," changeRowHeight(dragTd, dragLinePos.y - dragTdPos.y - dragTd.offsetHeight);"," break;"," default:"," }"," onDrag = \"\";"," dragTd = null;",""," hideDragLine(me);"," me.fireEvent('saveScene');"," return;"," }"," //正常状态下的mouseup"," if (!startTd) {"," var target = domUtils.findParentByTagName(evt.target || evt.srcElement, \"td\", true);"," if (!target) target = domUtils.findParentByTagName(evt.target || evt.srcElement, \"th\", true);"," if (target && (target.tagName == \"TD\" || target.tagName == \"TH\")) {"," if (me.fireEvent(\"excludetable\", target) === true) return;"," range = new dom.Range(me.document);"," range.setStart(target, 0).setCursor(false, true);"," }"," } else {"," var ut = getUETable(startTd),"," cell = ut ? ut.selectedTds[0] : null;"," if (cell) {"," range = new dom.Range(me.document);"," if (domUtils.isEmptyBlock(cell)) {"," range.setStart(cell, 0).setCursor(false, true);"," } else {"," range.selectNodeContents(cell).shrinkBoundary().setCursor(false, true);"," }"," } else {"," range = me.selection.getRange().shrinkBoundary();"," if (!range.collapsed) {"," var start = domUtils.findParentByTagName(range.startContainer, ['td', 'th'], true),"," end = domUtils.findParentByTagName(range.endContainer, ['td', 'th'], true);"," //在table里边的不能清除"," if (start && !end || !start && end || start && end && start !== end) {"," range.setCursor(false, true);"," }"," }"," }"," startTd = null;"," me.removeListener('mouseover', mouseOverEvent);"," }"," me._selectionChange(250, evt);"," }",""," function mouseOverEvent(type, evt) {",""," if( isEditorDisabled() ) {"," return;"," }",""," var me = this,"," tar = evt.target || evt.srcElement;"," currentTd = domUtils.findParentByTagName(tar, \"td\", true) || domUtils.findParentByTagName(tar, \"th\", true);"," //需要判断两个TD是否位于同一个表格内"," if (startTd && currentTd &&"," ((startTd.tagName == \"TD\" && currentTd.tagName == \"TD\") || (startTd.tagName == \"TH\" && currentTd.tagName == \"TH\")) &&"," domUtils.findParentByTagName(startTd, 'table') == domUtils.findParentByTagName(currentTd, 'table')) {"," var ut = getUETable(currentTd);"," if (startTd != currentTd) {"," me.document.body.style.webkitUserSelect = 'none';"," me.selection.getNative()[browser.ie ? 'empty' : 'removeAllRanges']();"," var range = ut.getCellsRange(startTd, currentTd);"," ut.setSelected(range);"," } else {"," me.document.body.style.webkitUserSelect = '';"," ut.clearSelected();"," }",""," }"," evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);"," }",""," function setCellHeight(cell, height, backHeight) {"," var lineHight = parseInt(domUtils.getComputedStyle(cell, \"line-height\"), 10),"," tmpHeight = backHeight + height;"," height = tmpHeight < lineHight ? lineHight : tmpHeight;"," if (cell.style.height) cell.style.height = \"\";"," cell.rowSpan == 1 ? cell.setAttribute(\"height\", height) : (cell.removeAttribute && cell.removeAttribute(\"height\"));"," }",""," function getWidth(cell) {"," if (!cell)return 0;"," return parseInt(domUtils.getComputedStyle(cell, \"width\"), 10);"," }",""," function changeColWidth(cell, changeValue) {",""," var ut = getUETable(cell);"," if (ut) {",""," //根据当前移动的边框获取相关的单元格"," var table = ut.table,"," cells = getCellsByMoveBorder( cell, table );",""," table.style.width = \"\";"," table.removeAttribute(\"width\");",""," //修正改变量"," changeValue = correctChangeValue( changeValue, cell, cells );",""," if (cell.nextSibling) {",""," var i=0;",""," utils.each( cells, function( cellGroup ){",""," cellGroup.left.width = (+cellGroup.left.width)+changeValue;"," cellGroup.right && ( cellGroup.right.width = (+cellGroup.right.width)-changeValue );",""," } );",""," } else {",""," utils.each( cells, function( cellGroup ){"," cellGroup.left.width -= -changeValue;"," } );",""," }"," }",""," }",""," function isEditorDisabled() {"," return me.body.contentEditable === \"false\";"," }",""," function changeRowHeight(td, changeValue) {"," if (Math.abs(changeValue) < 10) return;"," var ut = getUETable(td);"," if (ut) {"," var cells = ut.getSameEndPosCells(td, \"y\"),"," //备份需要连带变化的td的原始高度,否则后期无法获取正确的值"," backHeight = cells[0] ? cells[0].offsetHeight : 0;"," for (var i = 0, cell; cell = cells[i++];) {"," setCellHeight(cell, changeValue, backHeight);"," }"," }",""," }",""," /*"," * 获取调整单元格大小的相关单元格"," * @isContainMergeCell 返回的结果中是否包含发生合并后的单元格"," */"," function getCellsByMoveBorder( cell, table, isContainMergeCell ) {",""," if( !table ) {"," table = domUtils.findParentByTagName( cell, 'table' );"," }",""," if( !table ) {"," return null;"," }",""," //获取到该单元格所在行的序列号"," var index = domUtils.getNodeIndex( cell ),"," temp = cell,"," rows = table.rows,"," colIndex = 0;",""," while( temp ) {"," //获取到当前单元格在未发生单元格合并时的序列"," if( temp.nodeType === 1 ) {"," colIndex += (temp.colSpan || 1);"," }"," temp = temp.previousSibling;"," }",""," temp = null;",""," //记录想关的单元格"," var borderCells = [];",""," utils.each(rows, function( tabRow ){",""," var cells = tabRow.cells,"," currIndex = 0;",""," utils.each( cells, function( tabCell ){",""," currIndex += (tabCell.colSpan || 1);",""," if( currIndex === colIndex ) {",""," borderCells.push({"," left: tabCell,"," right: tabCell.nextSibling || null"," });",""," return false;",""," } else if( currIndex > colIndex ) {",""," if( isContainMergeCell ) {"," borderCells.push({"," left: tabCell"," });"," }",""," return false;"," }","",""," } );",""," });",""," return borderCells;",""," }","",""," /*"," * 通过给定的单元格集合获取最小的单元格width"," */"," function getMinWidthByTableCells( cells ) {",""," var minWidth = Number.MAX_VALUE;",""," for( var i = 0, curCell; curCell = cells[ i ] ; i++ ) {",""," minWidth = Math.min( minWidth, curCell.width || getTableCellWidth( curCell ) );",""," }",""," return minWidth;",""," }",""," function correctChangeValue( changeValue, relatedCell, cells ) {",""," //为单元格的paading预留空间"," changeValue -= getTabcellSpace();",""," if( changeValue < 0 ) {"," return 0;"," }",""," changeValue -= getTableCellWidth( relatedCell );",""," //确定方向"," var direction = changeValue < 0 ? 'left':'right';",""," changeValue = Math.abs(changeValue);",""," //只关心非最后一个单元格就可以"," utils.each( cells, function( cellGroup ){",""," var curCell = cellGroup[direction];",""," //为单元格保留最小空间"," if( curCell ) {"," changeValue = Math.min( changeValue, getTableCellWidth( curCell )-cellMinWidth );"," }","",""," } );","",""," //修正越界"," changeValue = changeValue < 0 ? 0 : changeValue;",""," return direction === 'left' ? -changeValue : changeValue;",""," }",""," function getTableCellWidth( cell ) {",""," var width = 0,"," //偏移纠正量"," offset = 0,"," width = cell.offsetWidth - getTabcellSpace();",""," //最后一个节点纠正一下"," if( !cell.nextSibling ) {",""," width -= getTableCellOffset( cell );",""," }",""," width = width < 0 ? 0 : width;",""," try {"," cell.width = width;"," } catch(e) {"," }",""," return width;",""," }",""," /*"," * 获取单元格所在表格的最末单元格的偏移量"," */"," function getTableCellOffset( cell ) {",""," tab = domUtils.findParentByTagName( cell, \"table\", false);",""," if( tab.offsetVal === undefined ) {",""," var prev = cell.previousSibling;",""," if( prev ) {",""," //最后一个单元格和前一个单元格的width diff结果 如果恰好为一个border width, 则条件成立"," tab.offsetVal = cell.offsetWidth - prev.offsetWidth === UT.borderWidth ? UT.borderWidth : 0;",""," } else {"," tab.offsetVal = 0;"," }",""," }",""," return tab.offsetVal;",""," }",""," function getTabcellSpace() {",""," if( UT.tabcellSpace === undefined ) {",""," var cell = null,"," tab = me.document.createElement(\"table\"),"," tbody = me.document.createElement(\"tbody\"),"," trow = me.document.createElement(\"tr\"),"," tabcell = me.document.createElement(\"td\"),"," mirror = null;",""," tabcell.style.cssText = 'border: 0;';"," tabcell.width = 1;",""," trow.appendChild( tabcell );"," trow.appendChild( mirror = tabcell.cloneNode( false ) );",""," tbody.appendChild( trow );",""," tab.appendChild( tbody );",""," tab.style.cssText = \"visibility: hidden;\";",""," me.body.appendChild( tab );",""," UT.paddingSpace = tabcell.offsetWidth - 1;",""," var tmpTabWidth = tab.offsetWidth;",""," tabcell.style.cssText = '';"," mirror.style.cssText = '';",""," UT.borderWidth = ( tab.offsetWidth - tmpTabWidth ) / 3;",""," UT.tabcellSpace = UT.paddingSpace + UT.borderWidth;",""," me.body.removeChild( tab );",""," }",""," getTabcellSpace = function(){ return UT.tabcellSpace; };",""," return UT.tabcellSpace;",""," }",""," function getDragLine(editor, doc) {"," if (mousedown)return;"," dragLine = editor.document.createElement(\"div\");"," domUtils.setAttributes(dragLine, {"," id:\"ue_tableDragLine\","," unselectable:'on',"," contenteditable:false,"," 'onresizestart':'return false',"," 'ondragstart':'return false',"," 'onselectstart':'return false',"," style:\"background-color:blue;position:absolute;padding:0;margin:0;background-image:none;border:0px none;opacity:0;filter:alpha(opacity=0)\""," });"," editor.body.appendChild(dragLine);"," }",""," function hideDragLine(editor) {"," if (mousedown)return;"," var line;"," while (line = editor.document.getElementById('ue_tableDragLine')) {"," domUtils.remove(line)"," }"," }",""," /*"," * 依据state(v|h)在cell位置显示横线"," * @param state"," * @param cell"," */"," function showDragLineAt(state, cell) {"," if (!cell) return;"," var table = domUtils.findParentByTagName(cell, \"table\"),"," caption = table.getElementsByTagName('caption'),"," width = table.offsetWidth,"," height = table.offsetHeight - (caption.length > 0 ? caption[0].offsetHeight : 0),"," tablePos = domUtils.getXY(table),"," cellPos = domUtils.getXY(cell), css;"," switch (state) {"," case \"h\":"," css = 'height:' + height + 'px;top:' + (tablePos.y + (caption.length > 0 ? caption[0].offsetHeight : 0)) + 'px;left:' + (cellPos.x + cell.offsetWidth);"," dragLine.style.cssText = css + 'px;position: absolute;display:block;background-color:blue;width:1px;border:0; color:blue;opacity:.3;filter:alpha(opacity=30)';"," break;"," case \"v\":"," css = 'width:' + width + 'px;left:' + tablePos.x + 'px;top:' + (cellPos.y + cell.offsetHeight );"," //必须加上border:0和color:blue,否则低版ie不支持背景色显示"," dragLine.style.cssText = css + 'px;overflow:hidden;position: absolute;display:block;background-color:blue;height:1px;border:0;color:blue;opacity:.2;filter:alpha(opacity=20)';"," break;"," default:"," }"," }",""," /*"," * 当表格边框颜色为白色时设置为虚线,true为添加虚线"," * @param editor"," * @param flag"," */"," function switchBorderColor(editor, flag) {"," var tableArr = domUtils.getElementsByTagName(editor.body, \"table\"), color;"," for (var i = 0, node; node = tableArr[i++];) {"," var td = domUtils.getElementsByTagName(node, \"td\");"," if (td[0]) {"," if (flag) {"," color = (td[0].style.borderColor).replace(/\\s/g, \"\");"," if (/(#ffffff)|(rgb\\(255,f55,255\\))/ig.test(color))"," domUtils.addClass(node, \"noBorderTable\")"," } else {"," domUtils.removeClasses(node, \"noBorderTable\")"," }"," }",""," }"," }",""," function getTableWidth(editor, needIEHack, defaultValue) {"," var body = editor.body;"," return body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(body, 'margin-left'), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (editor.options.offsetWidth || 0);"," }",""," /*"," * 获取当前拖动的单元格"," */"," function getTargetTd(editor, evt) {",""," var target = domUtils.findParentByTagName(evt.target || evt.srcElement, [\"td\", \"th\"], true),"," dir = null;",""," if( !target ) {"," return null;"," }",""," dir = getRelation( target, mouseCoords( evt ) );",""," //如果有前一个节点, 需要做一个修正, 否则可能会得到一个错误的td",""," if( !target ) {"," return null;"," }",""," if( dir === 'h1' && target.previousSibling ) {",""," var position = domUtils.getXY( target),"," cellWidth = target.offsetWidth;",""," if( Math.abs( position.x + cellWidth - evt.clientX ) > cellWidth / 3 ) {"," target = target.previousSibling;"," }",""," } else if( dir === 'v1' && target.parentNode.previousSibling ) {",""," var position = domUtils.getXY( target),"," cellHeight = target.offsetHeight;",""," if( Math.abs( position.y + cellHeight - evt.clientY ) > cellHeight / 3 ) {"," target = target.parentNode.previousSibling.firstChild;"," }",""," }","",""," //排除了非td内部以及用于代码高亮部分的td"," return target && !(editor.fireEvent(\"excludetable\", target) === true) ? target : null;"," }","","};"]; +_$jscoverage['plugins/table.action.js'][8]++; +UE.plugins.table = (function () { + _$jscoverage['plugins/table.action.js'][9]++; + var me = this, tabTimer = null, tableDragTimer = null, tableResizeTimer = null, cellMinWidth = 5, isInResizeBuffer = false, cellBorderWidth = 5, offsetOfTableCell = 10, singleClickState = 0, userActionStatus = null, dblclickTime = 360, UT = UE.UETable, getUETable = (function (tdOrTable) { + _$jscoverage['plugins/table.action.js'][29]++; + return UT.getUETable(tdOrTable); +}), getUETableBySelected = (function (editor) { + _$jscoverage['plugins/table.action.js'][32]++; + return UT.getUETableBySelected(editor); +}), getDefaultValue = (function (editor, table) { + _$jscoverage['plugins/table.action.js'][35]++; + return UT.getDefaultValue(editor, table); +}), removeSelectedClass = (function (cells) { + _$jscoverage['plugins/table.action.js'][38]++; + return UT.removeSelectedClass(cells); +}); + _$jscoverage['plugins/table.action.js'][41]++; + function showError(e) { +} + _$jscoverage['plugins/table.action.js'][44]++; + me.ready((function () { + _$jscoverage['plugins/table.action.js'][45]++; + var me = this; + _$jscoverage['plugins/table.action.js'][46]++; + var orgGetText = me.selection.getText; + _$jscoverage['plugins/table.action.js'][47]++; + me.selection.getText = (function () { + _$jscoverage['plugins/table.action.js'][48]++; + var table = getUETableBySelected(me); + _$jscoverage['plugins/table.action.js'][49]++; + if (table) { + _$jscoverage['plugins/table.action.js'][50]++; + var str = ""; + _$jscoverage['plugins/table.action.js'][51]++; + utils.each(table.selectedTds, (function (td) { + _$jscoverage['plugins/table.action.js'][52]++; + str += td[(browser.ie? "innerText": "textContent")]; +})); + _$jscoverage['plugins/table.action.js'][54]++; + return str; + } + else { + _$jscoverage['plugins/table.action.js'][56]++; + return orgGetText.call(me.selection); + } +}); +})); + _$jscoverage['plugins/table.action.js'][63]++; + var startTd = null, currentTd = null, onDrag = "", onBorder = false, dragButton = null, dragOver = false, dragLine = null, dragTd = null; + _$jscoverage['plugins/table.action.js'][72]++; + var mousedown = false, needIEHack = true; + _$jscoverage['plugins/table.action.js'][76]++; + me.setOpt({"maxColNum": 20, "maxRowNum": 100, "defaultCols": 5, "defaultRows": 5, "tdvalign": "top", "cursorpath": (me.options.UEDITOR_HOME_URL + "themes/default/images/cursor_"), "tableDragable": false, "classList": ["ue-table-interlace-color-single", "ue-table-interlace-color-double"]}); + _$jscoverage['plugins/table.action.js'][86]++; + me.getUETable = getUETable; + _$jscoverage['plugins/table.action.js'][87]++; + var commands = {"deletetable": 1, "inserttable": 1, "cellvalign": 1, "insertcaption": 1, "deletecaption": 1, "inserttitle": 1, "deletetitle": 1, "mergeright": 1, "mergedown": 1, "mergecells": 1, "insertrow": 1, "insertrownext": 1, "deleterow": 1, "insertcol": 1, "insertcolnext": 1, "deletecol": 1, "splittocells": 1, "splittorows": 1, "splittocols": 1, "adaptbytext": 1, "adaptbywindow": 1, "adaptbycustomer": 1, "insertparagraph": 1, "insertparagraphbeforetable": 1, "averagedistributecol": 1, "averagedistributerow": 1}; + _$jscoverage['plugins/table.action.js'][115]++; + me.ready((function () { + _$jscoverage['plugins/table.action.js'][116]++; + utils.cssRule("table", ".selectTdClass{background-color:#edf5fa !important}table.noBorderTable td,table.noBorderTable th,table.noBorderTable caption{border:1px dashed #ddd !important}table{margin-bottom:10px;border-collapse:collapse;display:table;}td,th{padding: 5px 10px;border: 1px solid #DDD;}caption{border:1px dashed #DDD;border-bottom:0;padding:3px;text-align:center;}th{border-top:2px solid #BBB;background:#F7F7F7;}.ue-table-interlace-color-single{ background-color: #fcfcfc; } .ue-table-interlace-color-double{ background-color: #f7faff; }td p{margin:0;padding:0;}", me.document); + _$jscoverage['plugins/table.action.js'][128]++; + var tableCopyList, isFullCol, isFullRow; + _$jscoverage['plugins/table.action.js'][130]++; + me.addListener("keydown", (function (cmd, evt) { + _$jscoverage['plugins/table.action.js'][131]++; + var me = this; + _$jscoverage['plugins/table.action.js'][132]++; + var keyCode = (evt.keyCode || evt.which); + _$jscoverage['plugins/table.action.js'][134]++; + if ((keyCode == 8)) { + _$jscoverage['plugins/table.action.js'][136]++; + var ut = getUETableBySelected(me); + _$jscoverage['plugins/table.action.js'][137]++; + if ((ut && ut.selectedTds.length)) { + _$jscoverage['plugins/table.action.js'][139]++; + if (ut.isFullCol()) { + _$jscoverage['plugins/table.action.js'][140]++; + me.execCommand("deletecol"); + } + else { + _$jscoverage['plugins/table.action.js'][141]++; + if (ut.isFullRow()) { + _$jscoverage['plugins/table.action.js'][142]++; + me.execCommand("deleterow"); + } + else { + _$jscoverage['plugins/table.action.js'][144]++; + me.fireEvent("delcells"); + } + } + _$jscoverage['plugins/table.action.js'][146]++; + domUtils.preventDefault(evt); + } + _$jscoverage['plugins/table.action.js'][149]++; + var caption = domUtils.findParentByTagName(me.selection.getStart(), "caption", true), range = me.selection.getRange(); + _$jscoverage['plugins/table.action.js'][151]++; + if ((range.collapsed && caption && isEmptyBlock(caption))) { + _$jscoverage['plugins/table.action.js'][152]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/table.action.js'][153]++; + var table = caption.parentNode; + _$jscoverage['plugins/table.action.js'][154]++; + domUtils.remove(caption); + _$jscoverage['plugins/table.action.js'][155]++; + if (table) { + _$jscoverage['plugins/table.action.js'][156]++; + range.setStart(table.rows[0].cells[0], 0).setCursor(false, true); + } + _$jscoverage['plugins/table.action.js'][158]++; + me.fireEvent("saveScene"); + } + } + _$jscoverage['plugins/table.action.js'][163]++; + if ((keyCode == 46)) { + _$jscoverage['plugins/table.action.js'][165]++; + ut = getUETableBySelected(me); + _$jscoverage['plugins/table.action.js'][166]++; + if (ut) { + _$jscoverage['plugins/table.action.js'][167]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/table.action.js'][168]++; + for (var i = 0, ci; (ci = ut.selectedTds[(i++)]);) { + _$jscoverage['plugins/table.action.js'][169]++; + domUtils.fillNode(me.document, ci); +} + _$jscoverage['plugins/table.action.js'][171]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/table.action.js'][172]++; + domUtils.preventDefault(evt); + } + } + _$jscoverage['plugins/table.action.js'][177]++; + if ((keyCode == 13)) { + _$jscoverage['plugins/table.action.js'][179]++; + var rng = me.selection.getRange(), caption = domUtils.findParentByTagName(rng.startContainer, "caption", true); + _$jscoverage['plugins/table.action.js'][181]++; + if (caption) { + _$jscoverage['plugins/table.action.js'][182]++; + var table = domUtils.findParentByTagName(caption, "table"); + _$jscoverage['plugins/table.action.js'][183]++; + if ((! rng.collapsed)) { + _$jscoverage['plugins/table.action.js'][185]++; + rng.deleteContents(); + _$jscoverage['plugins/table.action.js'][186]++; + me.fireEvent("saveScene"); + } + else { + _$jscoverage['plugins/table.action.js'][188]++; + if (caption) { + _$jscoverage['plugins/table.action.js'][189]++; + rng.setStart(table.rows[0].cells[0], 0).setCursor(false, true); + } + } + _$jscoverage['plugins/table.action.js'][192]++; + domUtils.preventDefault(evt); + _$jscoverage['plugins/table.action.js'][193]++; + return; + } + _$jscoverage['plugins/table.action.js'][195]++; + if (rng.collapsed) { + _$jscoverage['plugins/table.action.js'][196]++; + var table = domUtils.findParentByTagName(rng.startContainer, "table"); + _$jscoverage['plugins/table.action.js'][197]++; + if (table) { + _$jscoverage['plugins/table.action.js'][198]++; + var cell = table.rows[0].cells[0], start = domUtils.findParentByTagName(me.selection.getStart(), ["td", "th"], true), preNode = table.previousSibling; + _$jscoverage['plugins/table.action.js'][201]++; + if (((cell === start) && ((! preNode) || ((preNode.nodeType == 1) && (preNode.tagName == "TABLE"))) && domUtils.isStartInblock(rng))) { + _$jscoverage['plugins/table.action.js'][202]++; + var first = domUtils.findParent(me.selection.getStart(), (function (n) { + _$jscoverage['plugins/table.action.js'][202]++; + return domUtils.isBlockElm(n); +}), true); + _$jscoverage['plugins/table.action.js'][203]++; + if ((first && (/t(h|d)/i.test(first.tagName) || (first === start.firstChild)))) { + _$jscoverage['plugins/table.action.js'][204]++; + me.execCommand("insertparagraphbeforetable"); + _$jscoverage['plugins/table.action.js'][205]++; + domUtils.preventDefault(evt); + } + } + } + } + } + _$jscoverage['plugins/table.action.js'][213]++; + if (((evt.ctrlKey || evt.metaKey) && (evt.keyCode == "67"))) { + _$jscoverage['plugins/table.action.js'][214]++; + tableCopyList = null; + _$jscoverage['plugins/table.action.js'][215]++; + var ut = getUETableBySelected(me); + _$jscoverage['plugins/table.action.js'][216]++; + if (ut) { + _$jscoverage['plugins/table.action.js'][217]++; + var tds = ut.selectedTds; + _$jscoverage['plugins/table.action.js'][218]++; + isFullCol = ut.isFullCol(); + _$jscoverage['plugins/table.action.js'][219]++; + isFullRow = ut.isFullRow(); + _$jscoverage['plugins/table.action.js'][220]++; + tableCopyList = [[ut.cloneCell(tds[0], null, true)]]; + _$jscoverage['plugins/table.action.js'][223]++; + for (var i = 1, ci = ci; (ci = tds[i]); (i++)) { + _$jscoverage['plugins/table.action.js'][224]++; + if ((ci.parentNode !== tds[(i - 1)].parentNode)) { + _$jscoverage['plugins/table.action.js'][225]++; + tableCopyList.push([ut.cloneCell(ci, null, true)]); + } + else { + _$jscoverage['plugins/table.action.js'][227]++; + tableCopyList[(tableCopyList.length - 1)].push(ut.cloneCell(ci, null, true)); + } +} + } + } +})); + _$jscoverage['plugins/table.action.js'][234]++; + me.addListener("tablehasdeleted", (function () { + _$jscoverage['plugins/table.action.js'][235]++; + toggleDraggableState(this, false, "", null); + _$jscoverage['plugins/table.action.js'][236]++; + if (dragButton) { + _$jscoverage['plugins/table.action.js'][236]++; + domUtils.remove(dragButton); + } +})); + _$jscoverage['plugins/table.action.js'][239]++; + me.addListener("beforepaste", (function (cmd, html) { + _$jscoverage['plugins/table.action.js'][240]++; + var me = this; + _$jscoverage['plugins/table.action.js'][241]++; + var rng = me.selection.getRange(); + _$jscoverage['plugins/table.action.js'][242]++; + if (domUtils.findParentByTagName(rng.startContainer, "caption", true)) { + _$jscoverage['plugins/table.action.js'][243]++; + var div = me.document.createElement("div"); + _$jscoverage['plugins/table.action.js'][244]++; + div.innerHTML = html.html; + _$jscoverage['plugins/table.action.js'][245]++; + html.html = div[(browser.ie? "innerText": "textContent")]; + _$jscoverage['plugins/table.action.js'][246]++; + return; + } + _$jscoverage['plugins/table.action.js'][248]++; + var table = getUETableBySelected(me); + _$jscoverage['plugins/table.action.js'][249]++; + if (tableCopyList) { + _$jscoverage['plugins/table.action.js'][250]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/table.action.js'][251]++; + var rng = me.selection.getRange(); + _$jscoverage['plugins/table.action.js'][252]++; + var td = domUtils.findParentByTagName(rng.startContainer, ["td", "th"], true), tmpNode, preNode; + _$jscoverage['plugins/table.action.js'][253]++; + if (td) { + _$jscoverage['plugins/table.action.js'][254]++; + var ut = getUETable(td); + _$jscoverage['plugins/table.action.js'][255]++; + if (isFullRow) { + _$jscoverage['plugins/table.action.js'][256]++; + var rowIndex = ut.getCellInfo(td).rowIndex; + _$jscoverage['plugins/table.action.js'][257]++; + if ((td.tagName == "TH")) { + _$jscoverage['plugins/table.action.js'][258]++; + (rowIndex++); + } + _$jscoverage['plugins/table.action.js'][260]++; + for (var i = 0, ci; (ci = tableCopyList[(i++)]);) { + _$jscoverage['plugins/table.action.js'][261]++; + var tr = ut.insertRow((rowIndex++), "td"); + _$jscoverage['plugins/table.action.js'][262]++; + for (var j = 0, cj; (cj = ci[j]); (j++)) { + _$jscoverage['plugins/table.action.js'][263]++; + var cell = tr.cells[j]; + _$jscoverage['plugins/table.action.js'][264]++; + if ((! cell)) { + _$jscoverage['plugins/table.action.js'][265]++; + cell = tr.insertCell(j); + } + _$jscoverage['plugins/table.action.js'][267]++; + cell.innerHTML = cj.innerHTML; + _$jscoverage['plugins/table.action.js'][268]++; + (cj.getAttribute("width") && cell.setAttribute("width", cj.getAttribute("width"))); + _$jscoverage['plugins/table.action.js'][269]++; + (cj.getAttribute("vAlign") && cell.setAttribute("vAlign", cj.getAttribute("vAlign"))); + _$jscoverage['plugins/table.action.js'][270]++; + (cj.getAttribute("align") && cell.setAttribute("align", cj.getAttribute("align"))); + _$jscoverage['plugins/table.action.js'][271]++; + (cj.style.cssText && (cell.style.cssText = cj.style.cssText)); +} + _$jscoverage['plugins/table.action.js'][273]++; + for (var j = 0, cj = cj; (cj = tr.cells[j]); (j++)) { + _$jscoverage['plugins/table.action.js'][274]++; + if ((! ci[j])) { + _$jscoverage['plugins/table.action.js'][275]++; + break; + } + _$jscoverage['plugins/table.action.js'][276]++; + cj.innerHTML = ci[j].innerHTML; + _$jscoverage['plugins/table.action.js'][277]++; + (ci[j].getAttribute("width") && cj.setAttribute("width", ci[j].getAttribute("width"))); + _$jscoverage['plugins/table.action.js'][278]++; + (ci[j].getAttribute("vAlign") && cj.setAttribute("vAlign", ci[j].getAttribute("vAlign"))); + _$jscoverage['plugins/table.action.js'][279]++; + (ci[j].getAttribute("align") && cj.setAttribute("align", ci[j].getAttribute("align"))); + _$jscoverage['plugins/table.action.js'][280]++; + (ci[j].style.cssText && (cj.style.cssText = ci[j].style.cssText)); +} +} + } + else { + _$jscoverage['plugins/table.action.js'][284]++; + if (isFullCol) { + _$jscoverage['plugins/table.action.js'][285]++; + cellInfo = ut.getCellInfo(td); + _$jscoverage['plugins/table.action.js'][286]++; + var maxColNum = 0; + _$jscoverage['plugins/table.action.js'][287]++; + for (var j = 0, ci = tableCopyList[0], cj = cj; (cj = ci[(j++)]);) { + _$jscoverage['plugins/table.action.js'][288]++; + maxColNum += (cj.colSpan || 1); +} + _$jscoverage['plugins/table.action.js'][290]++; + me.__hasEnterExecCommand = true; + _$jscoverage['plugins/table.action.js'][291]++; + for (i = 0; (i < maxColNum); (i++)) { + _$jscoverage['plugins/table.action.js'][292]++; + me.execCommand("insertcol"); +} + _$jscoverage['plugins/table.action.js'][294]++; + me.__hasEnterExecCommand = false; + _$jscoverage['plugins/table.action.js'][295]++; + td = ut.table.rows[0].cells[cellInfo.cellIndex]; + _$jscoverage['plugins/table.action.js'][296]++; + if ((td.tagName == "TH")) { + _$jscoverage['plugins/table.action.js'][297]++; + td = ut.table.rows[1].cells[cellInfo.cellIndex]; + } + } + _$jscoverage['plugins/table.action.js'][300]++; + for (var i = 0, ci = ci; (ci = tableCopyList[(i++)]);) { + _$jscoverage['plugins/table.action.js'][301]++; + tmpNode = td; + _$jscoverage['plugins/table.action.js'][302]++; + for (var j = 0, cj = cj; (cj = ci[(j++)]);) { + _$jscoverage['plugins/table.action.js'][303]++; + if (td) { + _$jscoverage['plugins/table.action.js'][304]++; + td.innerHTML = cj.innerHTML; + _$jscoverage['plugins/table.action.js'][306]++; + (cj.getAttribute("width") && td.setAttribute("width", cj.getAttribute("width"))); + _$jscoverage['plugins/table.action.js'][307]++; + (cj.getAttribute("vAlign") && td.setAttribute("vAlign", cj.getAttribute("vAlign"))); + _$jscoverage['plugins/table.action.js'][308]++; + (cj.getAttribute("align") && td.setAttribute("align", cj.getAttribute("align"))); + _$jscoverage['plugins/table.action.js'][309]++; + (cj.style.cssText && (td.style.cssText = cj.style.cssText)); + _$jscoverage['plugins/table.action.js'][310]++; + preNode = td; + _$jscoverage['plugins/table.action.js'][311]++; + td = td.nextSibling; + } + else { + _$jscoverage['plugins/table.action.js'][313]++; + var cloneTd = cj.cloneNode(true); + _$jscoverage['plugins/table.action.js'][314]++; + domUtils.removeAttributes(cloneTd, ["class", "rowSpan", "colSpan"]); + _$jscoverage['plugins/table.action.js'][316]++; + preNode.parentNode.appendChild(cloneTd); + } +} + _$jscoverage['plugins/table.action.js'][319]++; + td = ut.getNextCell(tmpNode, true, true); + _$jscoverage['plugins/table.action.js'][320]++; + if ((! tableCopyList[i])) { + _$jscoverage['plugins/table.action.js'][321]++; + break; + } + _$jscoverage['plugins/table.action.js'][322]++; + if ((! td)) { + _$jscoverage['plugins/table.action.js'][323]++; + var cellInfo = ut.getCellInfo(tmpNode); + _$jscoverage['plugins/table.action.js'][324]++; + ut.table.insertRow(ut.table.rows.length); + _$jscoverage['plugins/table.action.js'][325]++; + ut.update(); + _$jscoverage['plugins/table.action.js'][326]++; + td = ut.getVSideCell(tmpNode, true); + } +} + } + _$jscoverage['plugins/table.action.js'][330]++; + ut.update(); + } + else { + _$jscoverage['plugins/table.action.js'][332]++; + table = me.document.createElement("table"); + _$jscoverage['plugins/table.action.js'][333]++; + for (var i = 0, ci = ci; (ci = tableCopyList[(i++)]);) { + _$jscoverage['plugins/table.action.js'][334]++; + var tr = table.insertRow(table.rows.length); + _$jscoverage['plugins/table.action.js'][335]++; + for (var j = 0, cj = cj; (cj = ci[(j++)]);) { + _$jscoverage['plugins/table.action.js'][336]++; + cloneTd = UT.cloneCell(cj, null, true); + _$jscoverage['plugins/table.action.js'][337]++; + domUtils.removeAttributes(cloneTd, ["class"]); + _$jscoverage['plugins/table.action.js'][338]++; + tr.appendChild(cloneTd); +} + _$jscoverage['plugins/table.action.js'][340]++; + if (((j == 2) && (cloneTd.rowSpan > 1))) { + _$jscoverage['plugins/table.action.js'][341]++; + cloneTd.rowSpan = 1; + } +} + _$jscoverage['plugins/table.action.js'][345]++; + var defaultValue = getDefaultValue(me), width = (me.body.offsetWidth - (needIEHack? (parseInt(domUtils.getComputedStyle(me.body, "margin-left"), 10) * 2): 0) - (defaultValue.tableBorder * 2) - (me.options.offsetWidth || 0)); + _$jscoverage['plugins/table.action.js'][348]++; + me.execCommand("insertHTML", ("" + table.innerHTML.replace(/>\s*<").replace(/\bth\b/gi, "td") + "
    ")); + } + _$jscoverage['plugins/table.action.js'][352]++; + me.fireEvent("contentchange"); + _$jscoverage['plugins/table.action.js'][353]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/table.action.js'][354]++; + html.html = ""; + _$jscoverage['plugins/table.action.js'][355]++; + return true; + } + else { + _$jscoverage['plugins/table.action.js'][357]++; + var div = me.document.createElement("div"), tables; + _$jscoverage['plugins/table.action.js'][358]++; + div.innerHTML = html.html; + _$jscoverage['plugins/table.action.js'][359]++; + tables = div.getElementsByTagName("table"); + _$jscoverage['plugins/table.action.js'][360]++; + if (domUtils.findParentByTagName(me.selection.getStart(), "table")) { + _$jscoverage['plugins/table.action.js'][361]++; + utils.each(tables, (function (t) { + _$jscoverage['plugins/table.action.js'][362]++; + domUtils.remove(t); +})); + _$jscoverage['plugins/table.action.js'][364]++; + if (domUtils.findParentByTagName(me.selection.getStart(), "caption", true)) { + _$jscoverage['plugins/table.action.js'][365]++; + div.innerHTML = div[(browser.ie? "innerText": "textContent")]; + } + } + else { + _$jscoverage['plugins/table.action.js'][368]++; + utils.each(tables, (function (table) { + _$jscoverage['plugins/table.action.js'][369]++; + removeStyleSize(table, true); + _$jscoverage['plugins/table.action.js'][370]++; + domUtils.removeAttributes(table, ["style", "border"]); + _$jscoverage['plugins/table.action.js'][371]++; + utils.each(domUtils.getElementsByTagName(table, "td"), (function (td) { + _$jscoverage['plugins/table.action.js'][372]++; + if (isEmptyBlock(td)) { + _$jscoverage['plugins/table.action.js'][373]++; + domUtils.fillNode(me.document, td); + } + _$jscoverage['plugins/table.action.js'][375]++; + removeStyleSize(td, true); +})); +})); + } + _$jscoverage['plugins/table.action.js'][380]++; + html.html = div.innerHTML; + } +})); + _$jscoverage['plugins/table.action.js'][384]++; + me.addListener("afterpaste", (function () { + _$jscoverage['plugins/table.action.js'][385]++; + utils.each(domUtils.getElementsByTagName(me.body, "table"), (function (table) { + _$jscoverage['plugins/table.action.js'][386]++; + if ((table.offsetWidth > me.body.offsetWidth)) { + _$jscoverage['plugins/table.action.js'][387]++; + var defaultValue = getDefaultValue(me, table); + _$jscoverage['plugins/table.action.js'][388]++; + table.style.width = ((me.body.offsetWidth - (needIEHack? (parseInt(domUtils.getComputedStyle(me.body, "margin-left"), 10) * 2): 0) - (defaultValue.tableBorder * 2) - (me.options.offsetWidth || 0)) + "px"); + } +})); +})); + _$jscoverage['plugins/table.action.js'][392]++; + me.addListener("blur", (function () { + _$jscoverage['plugins/table.action.js'][393]++; + tableCopyList = null; +})); + _$jscoverage['plugins/table.action.js'][395]++; + var timer; + _$jscoverage['plugins/table.action.js'][396]++; + me.addListener("keydown", (function () { + _$jscoverage['plugins/table.action.js'][397]++; + clearTimeout(timer); + _$jscoverage['plugins/table.action.js'][398]++; + timer = setTimeout((function () { + _$jscoverage['plugins/table.action.js'][399]++; + var rng = me.selection.getRange(), cell = domUtils.findParentByTagName(rng.startContainer, ["th", "td"], true); + _$jscoverage['plugins/table.action.js'][401]++; + if (cell) { + _$jscoverage['plugins/table.action.js'][402]++; + var table = cell.parentNode.parentNode.parentNode; + _$jscoverage['plugins/table.action.js'][403]++; + if ((table.offsetWidth > table.getAttribute("width"))) { + _$jscoverage['plugins/table.action.js'][404]++; + cell.style.wordBreak = "break-all"; + } + } +}), 100); +})); + _$jscoverage['plugins/table.action.js'][410]++; + me.addListener("selectionchange", (function () { + _$jscoverage['plugins/table.action.js'][411]++; + toggleDraggableState(me, false, "", null); +})); + _$jscoverage['plugins/table.action.js'][417]++; + me.addListener("contentchange", (function () { + _$jscoverage['plugins/table.action.js'][418]++; + var me = this; + _$jscoverage['plugins/table.action.js'][420]++; + hideDragLine(me); + _$jscoverage['plugins/table.action.js'][421]++; + if (getUETableBySelected(me)) { + _$jscoverage['plugins/table.action.js'][421]++; + return; + } + _$jscoverage['plugins/table.action.js'][422]++; + var rng = me.selection.getRange(); + _$jscoverage['plugins/table.action.js'][423]++; + var start = rng.startContainer; + _$jscoverage['plugins/table.action.js'][424]++; + start = domUtils.findParentByTagName(start, ["td", "th"], true); + _$jscoverage['plugins/table.action.js'][425]++; + utils.each(domUtils.getElementsByTagName(me.document, "table"), (function (table) { + _$jscoverage['plugins/table.action.js'][426]++; + if ((me.fireEvent("excludetable", table) === true)) { + _$jscoverage['plugins/table.action.js'][426]++; + return; + } + _$jscoverage['plugins/table.action.js'][427]++; + table.ueTable = new UT(table); + _$jscoverage['plugins/table.action.js'][428]++; + utils.each(domUtils.getElementsByTagName(me.document, "td"), (function (td) { + _$jscoverage['plugins/table.action.js'][430]++; + if ((domUtils.isEmptyBlock(td) && (td !== start))) { + _$jscoverage['plugins/table.action.js'][431]++; + domUtils.fillNode(me.document, td); + _$jscoverage['plugins/table.action.js'][432]++; + if ((browser.ie && (browser.version == 6))) { + _$jscoverage['plugins/table.action.js'][433]++; + td.innerHTML = " "; + } + } +})); + _$jscoverage['plugins/table.action.js'][437]++; + utils.each(domUtils.getElementsByTagName(me.document, "th"), (function (th) { + _$jscoverage['plugins/table.action.js'][438]++; + if ((domUtils.isEmptyBlock(th) && (th !== start))) { + _$jscoverage['plugins/table.action.js'][439]++; + domUtils.fillNode(me.document, th); + _$jscoverage['plugins/table.action.js'][440]++; + if ((browser.ie && (browser.version == 6))) { + _$jscoverage['plugins/table.action.js'][441]++; + th.innerHTML = " "; + } + } +})); + _$jscoverage['plugins/table.action.js'][445]++; + table.onmouseover = (function () { + _$jscoverage['plugins/table.action.js'][446]++; + me.fireEvent("tablemouseover", table); +}); + _$jscoverage['plugins/table.action.js'][448]++; + table.onmousemove = (function () { + _$jscoverage['plugins/table.action.js'][449]++; + me.fireEvent("tablemousemove", table); + _$jscoverage['plugins/table.action.js'][450]++; + (me.options.tableDragable && toggleDragButton(true, this, me)); +}); + _$jscoverage['plugins/table.action.js'][452]++; + table.onmouseout = (function () { + _$jscoverage['plugins/table.action.js'][453]++; + me.fireEvent("tablemouseout", table); + _$jscoverage['plugins/table.action.js'][454]++; + toggleDraggableState(me, false, "", null); + _$jscoverage['plugins/table.action.js'][455]++; + hideDragLine(me); +}); + _$jscoverage['plugins/table.action.js'][457]++; + table.onclick = (function (evt) { + _$jscoverage['plugins/table.action.js'][458]++; + evt = (me.window.event || evt); + _$jscoverage['plugins/table.action.js'][459]++; + var target = getParentTdOrTh((evt.target || evt.srcElement)); + _$jscoverage['plugins/table.action.js'][460]++; + if ((! target)) { + _$jscoverage['plugins/table.action.js'][460]++; + return; + } + _$jscoverage['plugins/table.action.js'][461]++; + var ut = getUETable(target), table = ut.table, cellInfo = ut.getCellInfo(target), cellsRange, rng = me.selection.getRange(); + _$jscoverage['plugins/table.action.js'][475]++; + if (inTableSide(table, target, evt, true)) { + _$jscoverage['plugins/table.action.js'][476]++; + var endTdCol = ut.getCell(ut.indexTable[(ut.rowsNum - 1)][cellInfo.colIndex].rowIndex, ut.indexTable[(ut.rowsNum - 1)][cellInfo.colIndex].cellIndex); + _$jscoverage['plugins/table.action.js'][477]++; + if ((evt.shiftKey && ut.selectedTds.length)) { + _$jscoverage['plugins/table.action.js'][478]++; + if ((ut.selectedTds[0] !== endTdCol)) { + _$jscoverage['plugins/table.action.js'][479]++; + cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdCol); + _$jscoverage['plugins/table.action.js'][480]++; + ut.setSelected(cellsRange); + } + else { + _$jscoverage['plugins/table.action.js'][482]++; + (rng && rng.selectNodeContents(endTdCol).select()); + } + } + else { + _$jscoverage['plugins/table.action.js'][485]++; + if ((target !== endTdCol)) { + _$jscoverage['plugins/table.action.js'][486]++; + cellsRange = ut.getCellsRange(target, endTdCol); + _$jscoverage['plugins/table.action.js'][487]++; + ut.setSelected(cellsRange); + } + else { + _$jscoverage['plugins/table.action.js'][489]++; + (rng && rng.selectNodeContents(endTdCol).select()); + } + } + _$jscoverage['plugins/table.action.js'][492]++; + return; + } + _$jscoverage['plugins/table.action.js'][494]++; + if (inTableSide(table, target, evt)) { + _$jscoverage['plugins/table.action.js'][495]++; + var endTdRow = ut.getCell(ut.indexTable[cellInfo.rowIndex][(ut.colsNum - 1)].rowIndex, ut.indexTable[cellInfo.rowIndex][(ut.colsNum - 1)].cellIndex); + _$jscoverage['plugins/table.action.js'][496]++; + if ((evt.shiftKey && ut.selectedTds.length)) { + _$jscoverage['plugins/table.action.js'][497]++; + if ((ut.selectedTds[0] !== endTdRow)) { + _$jscoverage['plugins/table.action.js'][498]++; + cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdRow); + _$jscoverage['plugins/table.action.js'][499]++; + ut.setSelected(cellsRange); + } + else { + _$jscoverage['plugins/table.action.js'][501]++; + (rng && rng.selectNodeContents(endTdRow).select()); + } + } + else { + _$jscoverage['plugins/table.action.js'][504]++; + if ((target !== endTdRow)) { + _$jscoverage['plugins/table.action.js'][505]++; + cellsRange = ut.getCellsRange(target, endTdRow); + _$jscoverage['plugins/table.action.js'][506]++; + ut.setSelected(cellsRange); + } + else { + _$jscoverage['plugins/table.action.js'][508]++; + (rng && rng.selectNodeContents(endTdRow).select()); + } + } + } +}); +})); + _$jscoverage['plugins/table.action.js'][515]++; + switchBorderColor(me, true); +})); + _$jscoverage['plugins/table.action.js'][518]++; + domUtils.on(me.document, "mousemove", mouseMoveEvent); + _$jscoverage['plugins/table.action.js'][520]++; + domUtils.on(me.document, "mouseout", (function (evt) { + _$jscoverage['plugins/table.action.js'][521]++; + var target = (evt.target || evt.srcElement); + _$jscoverage['plugins/table.action.js'][522]++; + if ((target.tagName == "TABLE")) { + _$jscoverage['plugins/table.action.js'][523]++; + toggleDraggableState(me, false, "", null); + } +})); + _$jscoverage['plugins/table.action.js'][529]++; + me.addListener("interlacetable", (function (type, table, classList) { + _$jscoverage['plugins/table.action.js'][530]++; + if ((! table)) { + _$jscoverage['plugins/table.action.js'][530]++; + return; + } + _$jscoverage['plugins/table.action.js'][531]++; + var me = this, rows = table.rows, len = rows.length, getClass = (function (list, index, repeat) { + _$jscoverage['plugins/table.action.js'][535]++; + return (list[index]? list[index]: (repeat? list[(index % list.length)]: "")); +}); + _$jscoverage['plugins/table.action.js'][537]++; + for (var i = 0; (i < len); (i++)) { + _$jscoverage['plugins/table.action.js'][538]++; + rows[i].className = getClass((classList || me.options.classList), i, true); +} +})); + _$jscoverage['plugins/table.action.js'][541]++; + me.addListener("uninterlacetable", (function (type, table) { + _$jscoverage['plugins/table.action.js'][542]++; + if ((! table)) { + _$jscoverage['plugins/table.action.js'][542]++; + return; + } + _$jscoverage['plugins/table.action.js'][543]++; + var me = this, rows = table.rows, classList = me.options.classList, len = rows.length; + _$jscoverage['plugins/table.action.js'][547]++; + for (var i = 0; (i < len); (i++)) { + _$jscoverage['plugins/table.action.js'][548]++; + domUtils.removeClasses(rows[i], classList); +} +})); + _$jscoverage['plugins/table.action.js'][552]++; + me.addListener("mousedown", mouseDownEvent); + _$jscoverage['plugins/table.action.js'][553]++; + me.addListener("mouseup", mouseUpEvent); + _$jscoverage['plugins/table.action.js'][555]++; + domUtils.on(me.body, "dragstart", (function (evt) { + _$jscoverage['plugins/table.action.js'][556]++; + mouseUpEvent.call(me, "dragstart", evt); +})); + _$jscoverage['plugins/table.action.js'][559]++; + var currentRowIndex = 0; + _$jscoverage['plugins/table.action.js'][560]++; + me.addListener("mousedown", (function () { + _$jscoverage['plugins/table.action.js'][561]++; + currentRowIndex = 0; +})); + _$jscoverage['plugins/table.action.js'][563]++; + me.addListener("tabkeydown", (function () { + _$jscoverage['plugins/table.action.js'][564]++; + var range = this.selection.getRange(), common = range.getCommonAncestor(true, true), table = domUtils.findParentByTagName(common, "table"); + _$jscoverage['plugins/table.action.js'][567]++; + if (table) { + _$jscoverage['plugins/table.action.js'][568]++; + if (domUtils.findParentByTagName(common, "caption", true)) { + _$jscoverage['plugins/table.action.js'][569]++; + var cell = domUtils.getElementsByTagName(table, "th td"); + _$jscoverage['plugins/table.action.js'][570]++; + if ((cell && cell.length)) { + _$jscoverage['plugins/table.action.js'][571]++; + range.setStart(cell[0], 0).setCursor(false, true); + } + } + else { + _$jscoverage['plugins/table.action.js'][574]++; + var cell = domUtils.findParentByTagName(common, ["td", "th"], true), ua = getUETable(cell); + _$jscoverage['plugins/table.action.js'][576]++; + currentRowIndex = ((cell.rowSpan > 1)? currentRowIndex: ua.getCellInfo(cell).rowIndex); + _$jscoverage['plugins/table.action.js'][577]++; + var nextCell = ua.getTabNextCell(cell, currentRowIndex); + _$jscoverage['plugins/table.action.js'][578]++; + if (nextCell) { + _$jscoverage['plugins/table.action.js'][579]++; + if (isEmptyBlock(nextCell)) { + _$jscoverage['plugins/table.action.js'][580]++; + range.setStart(nextCell, 0).setCursor(false, true); + } + else { + _$jscoverage['plugins/table.action.js'][582]++; + range.selectNodeContents(nextCell).select(); + } + } + else { + _$jscoverage['plugins/table.action.js'][585]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/table.action.js'][586]++; + me.__hasEnterExecCommand = true; + _$jscoverage['plugins/table.action.js'][587]++; + this.execCommand("insertrownext"); + _$jscoverage['plugins/table.action.js'][588]++; + me.__hasEnterExecCommand = false; + _$jscoverage['plugins/table.action.js'][589]++; + range = this.selection.getRange(); + _$jscoverage['plugins/table.action.js'][590]++; + range.setStart(table.rows[(table.rows.length - 1)].cells[0], 0).setCursor(); + _$jscoverage['plugins/table.action.js'][591]++; + me.fireEvent("saveScene"); + } + } + _$jscoverage['plugins/table.action.js'][594]++; + return true; + } +})); + _$jscoverage['plugins/table.action.js'][598]++; + (browser.ie && me.addListener("selectionchange", (function () { + _$jscoverage['plugins/table.action.js'][599]++; + toggleDraggableState(this, false, "", null); +}))); + _$jscoverage['plugins/table.action.js'][601]++; + me.addListener("keydown", (function (type, evt) { + _$jscoverage['plugins/table.action.js'][602]++; + var me = this; + _$jscoverage['plugins/table.action.js'][604]++; + var keyCode = (evt.keyCode || evt.which); + _$jscoverage['plugins/table.action.js'][605]++; + if (((keyCode == 8) || (keyCode == 46))) { + _$jscoverage['plugins/table.action.js'][606]++; + return; + } + _$jscoverage['plugins/table.action.js'][608]++; + var notCtrlKey = ((! evt.ctrlKey) && (! evt.metaKey) && (! evt.shiftKey) && (! evt.altKey)); + _$jscoverage['plugins/table.action.js'][609]++; + (notCtrlKey && removeSelectedClass(domUtils.getElementsByTagName(me.body, "td"))); + _$jscoverage['plugins/table.action.js'][610]++; + var ut = getUETableBySelected(me); + _$jscoverage['plugins/table.action.js'][611]++; + if ((! ut)) { + _$jscoverage['plugins/table.action.js'][611]++; + return; + } + _$jscoverage['plugins/table.action.js'][612]++; + (notCtrlKey && ut.clearSelected()); +})); + _$jscoverage['plugins/table.action.js'][615]++; + me.addListener("beforegetcontent", (function () { + _$jscoverage['plugins/table.action.js'][616]++; + switchBorderColor(this, false); + _$jscoverage['plugins/table.action.js'][617]++; + (browser.ie && utils.each(this.document.getElementsByTagName("caption"), (function (ci) { + _$jscoverage['plugins/table.action.js'][618]++; + if (domUtils.isEmptyNode(ci)) { + _$jscoverage['plugins/table.action.js'][619]++; + ci.innerHTML = " "; + } +}))); +})); + _$jscoverage['plugins/table.action.js'][623]++; + me.addListener("aftergetcontent", (function () { + _$jscoverage['plugins/table.action.js'][624]++; + switchBorderColor(this, true); +})); + _$jscoverage['plugins/table.action.js'][626]++; + me.addListener("getAllHtml", (function () { + _$jscoverage['plugins/table.action.js'][627]++; + removeSelectedClass(me.document.getElementsByTagName("td")); +})); + _$jscoverage['plugins/table.action.js'][630]++; + me.addListener("fullscreenchanged", (function (type, fullscreen) { + _$jscoverage['plugins/table.action.js'][631]++; + if ((! fullscreen)) { + _$jscoverage['plugins/table.action.js'][632]++; + var ratio = (this.body.offsetWidth / document.body.offsetWidth), tables = domUtils.getElementsByTagName(this.body, "table"); + _$jscoverage['plugins/table.action.js'][634]++; + utils.each(tables, (function (table) { + _$jscoverage['plugins/table.action.js'][635]++; + if ((table.offsetWidth < me.body.offsetWidth)) { + _$jscoverage['plugins/table.action.js'][635]++; + return false; + } + _$jscoverage['plugins/table.action.js'][636]++; + var tds = domUtils.getElementsByTagName(table, "td"), backWidths = []; + _$jscoverage['plugins/table.action.js'][638]++; + utils.each(tds, (function (td) { + _$jscoverage['plugins/table.action.js'][639]++; + backWidths.push(td.offsetWidth); +})); + _$jscoverage['plugins/table.action.js'][641]++; + for (var i = 0, td; (td = tds[i]); (i++)) { + _$jscoverage['plugins/table.action.js'][642]++; + td.setAttribute("width", Math.floor((backWidths[i] * ratio))); +} + _$jscoverage['plugins/table.action.js'][644]++; + table.setAttribute("width", Math.floor(getTableWidth(me, needIEHack, getDefaultValue(me)))); +})); + } +})); + _$jscoverage['plugins/table.action.js'][650]++; + var oldExecCommand = me.execCommand; + _$jscoverage['plugins/table.action.js'][651]++; + me.execCommand = (function (cmd, datatat) { + _$jscoverage['plugins/table.action.js'][653]++; + var me = this, args = arguments; + _$jscoverage['plugins/table.action.js'][656]++; + cmd = cmd.toLowerCase(); + _$jscoverage['plugins/table.action.js'][657]++; + var ut = getUETableBySelected(me), tds, range = new (dom.Range)(me.document), cmdFun = (me.commands[cmd] || UE.commands[cmd]), result; + _$jscoverage['plugins/table.action.js'][661]++; + if ((! cmdFun)) { + _$jscoverage['plugins/table.action.js'][661]++; + return; + } + _$jscoverage['plugins/table.action.js'][662]++; + if ((ut && (! commands[cmd]) && (! cmdFun.notNeedUndo) && (! me.__hasEnterExecCommand))) { + _$jscoverage['plugins/table.action.js'][663]++; + me.__hasEnterExecCommand = true; + _$jscoverage['plugins/table.action.js'][664]++; + me.fireEvent("beforeexeccommand", cmd); + _$jscoverage['plugins/table.action.js'][665]++; + tds = ut.selectedTds; + _$jscoverage['plugins/table.action.js'][666]++; + var lastState = -2, lastValue = -2, value, state; + _$jscoverage['plugins/table.action.js'][667]++; + for (var i = 0, td; (td = tds[i]); (i++)) { + _$jscoverage['plugins/table.action.js'][668]++; + if (isEmptyBlock(td)) { + _$jscoverage['plugins/table.action.js'][669]++; + range.setStart(td, 0).setCursor(false, true); + } + else { + _$jscoverage['plugins/table.action.js'][671]++; + range.selectNode(td).select(true); + } + _$jscoverage['plugins/table.action.js'][673]++; + state = me.queryCommandState(cmd); + _$jscoverage['plugins/table.action.js'][674]++; + value = me.queryCommandValue(cmd); + _$jscoverage['plugins/table.action.js'][675]++; + if ((state != -1)) { + _$jscoverage['plugins/table.action.js'][676]++; + if (((lastState !== state) || (lastValue !== value))) { + _$jscoverage['plugins/table.action.js'][677]++; + me._ignoreContentChange = true; + _$jscoverage['plugins/table.action.js'][678]++; + result = oldExecCommand.apply(me, arguments); + _$jscoverage['plugins/table.action.js'][679]++; + me._ignoreContentChange = false; + } + _$jscoverage['plugins/table.action.js'][682]++; + lastState = me.queryCommandState(cmd); + _$jscoverage['plugins/table.action.js'][683]++; + lastValue = me.queryCommandValue(cmd); + _$jscoverage['plugins/table.action.js'][684]++; + if (domUtils.isEmptyBlock(td)) { + _$jscoverage['plugins/table.action.js'][685]++; + domUtils.fillNode(me.document, td); + } + } +} + _$jscoverage['plugins/table.action.js'][689]++; + range.setStart(tds[0], 0).shrinkBoundary(true).setCursor(false, true); + _$jscoverage['plugins/table.action.js'][690]++; + me.fireEvent("contentchange"); + _$jscoverage['plugins/table.action.js'][691]++; + me.fireEvent("afterexeccommand", cmd); + _$jscoverage['plugins/table.action.js'][692]++; + me.__hasEnterExecCommand = false; + _$jscoverage['plugins/table.action.js'][693]++; + me._selectionChange(); + } + else { + _$jscoverage['plugins/table.action.js'][695]++; + result = oldExecCommand.apply(me, arguments); + } + _$jscoverage['plugins/table.action.js'][697]++; + return result; +}); +})); + _$jscoverage['plugins/table.action.js'][707]++; + function removeStyleSize(obj, replaceToProperty) { + _$jscoverage['plugins/table.action.js'][708]++; + removeStyle(obj, "width", true); + _$jscoverage['plugins/table.action.js'][709]++; + removeStyle(obj, "height", true); +} + _$jscoverage['plugins/table.action.js'][712]++; + function removeStyle(obj, styleName, replaceToProperty) { + _$jscoverage['plugins/table.action.js'][713]++; + if (obj.style[styleName]) { + _$jscoverage['plugins/table.action.js'][714]++; + (replaceToProperty && obj.setAttribute(styleName, parseInt(obj.style[styleName], 10))); + _$jscoverage['plugins/table.action.js'][715]++; + obj.style[styleName] = ""; + } +} + _$jscoverage['plugins/table.action.js'][719]++; + function getParentTdOrTh(ele) { + _$jscoverage['plugins/table.action.js'][720]++; + if (((ele.tagName == "TD") || (ele.tagName == "TH"))) { + _$jscoverage['plugins/table.action.js'][720]++; + return ele; + } + _$jscoverage['plugins/table.action.js'][721]++; + var td; + _$jscoverage['plugins/table.action.js'][722]++; + if ((td = (domUtils.findParentByTagName(ele, "td", true) || domUtils.findParentByTagName(ele, "th", true)))) { + _$jscoverage['plugins/table.action.js'][722]++; + return td; + } + _$jscoverage['plugins/table.action.js'][723]++; + return null; +} + _$jscoverage['plugins/table.action.js'][726]++; + function isEmptyBlock(node) { + _$jscoverage['plugins/table.action.js'][727]++; + var reg = new RegExp(domUtils.fillChar, "g"); + _$jscoverage['plugins/table.action.js'][728]++; + if ((node[(browser.ie? "innerText": "textContent")].replace(/^\s*$/, "").replace(reg, "").length > 0)) { + _$jscoverage['plugins/table.action.js'][729]++; + return 0; + } + _$jscoverage['plugins/table.action.js'][731]++; + for (var n in dtd.$isNotEmpty) { + _$jscoverage['plugins/table.action.js'][732]++; + if (node.getElementsByTagName(n).length) { + _$jscoverage['plugins/table.action.js'][733]++; + return 0; + } +} + _$jscoverage['plugins/table.action.js'][736]++; + return 1; +} + _$jscoverage['plugins/table.action.js'][740]++; + function mouseCoords(evt) { + _$jscoverage['plugins/table.action.js'][741]++; + if ((evt.pageX || evt.pageY)) { + _$jscoverage['plugins/table.action.js'][742]++; + return ({x: evt.pageX, y: evt.pageY}); + } + _$jscoverage['plugins/table.action.js'][744]++; + return ({x: ((evt.clientX + me.document.body.scrollLeft) - me.document.body.clientLeft), y: ((evt.clientY + me.document.body.scrollTop) - me.document.body.clientTop)}); +} + _$jscoverage['plugins/table.action.js'][750]++; + function mouseMoveEvent(evt) { + _$jscoverage['plugins/table.action.js'][752]++; + if (isEditorDisabled()) { + _$jscoverage['plugins/table.action.js'][753]++; + return; + } + _$jscoverage['plugins/table.action.js'][756]++; + try { + _$jscoverage['plugins/table.action.js'][759]++; + var target = getParentTdOrTh((evt.target || evt.srcElement)), pos; + _$jscoverage['plugins/table.action.js'][763]++; + if (isInResizeBuffer) { + _$jscoverage['plugins/table.action.js'][765]++; + me.body.style.webkitUserSelect = "none"; + _$jscoverage['plugins/table.action.js'][767]++; + if (((Math.abs((userActionStatus.x - evt.clientX)) > offsetOfTableCell) || (Math.abs((userActionStatus.y - evt.clientY)) > offsetOfTableCell))) { + _$jscoverage['plugins/table.action.js'][768]++; + clearTableDragTimer(); + _$jscoverage['plugins/table.action.js'][769]++; + isInResizeBuffer = false; + _$jscoverage['plugins/table.action.js'][770]++; + singleClickState = 0; + _$jscoverage['plugins/table.action.js'][772]++; + tableBorderDrag(evt); + } + } + _$jscoverage['plugins/table.action.js'][777]++; + if ((onDrag && dragTd)) { + _$jscoverage['plugins/table.action.js'][778]++; + singleClickState = 0; + _$jscoverage['plugins/table.action.js'][779]++; + me.body.style.webkitUserSelect = "none"; + _$jscoverage['plugins/table.action.js'][780]++; + (me.selection.getNative()[(browser.ie? "empty": "removeAllRanges")])(); + _$jscoverage['plugins/table.action.js'][781]++; + pos = mouseCoords(evt); + _$jscoverage['plugins/table.action.js'][782]++; + toggleDraggableState(me, true, onDrag, pos, target); + _$jscoverage['plugins/table.action.js'][783]++; + if ((onDrag == "h")) { + _$jscoverage['plugins/table.action.js'][784]++; + dragLine.style.left = (getPermissionX(dragTd, evt) + "px"); + } + else { + _$jscoverage['plugins/table.action.js'][785]++; + if ((onDrag == "v")) { + _$jscoverage['plugins/table.action.js'][786]++; + dragLine.style.top = (getPermissionY(dragTd, evt) + "px"); + } + } + _$jscoverage['plugins/table.action.js'][788]++; + return; + } + _$jscoverage['plugins/table.action.js'][791]++; + if (target) { + _$jscoverage['plugins/table.action.js'][793]++; + if ((me.fireEvent("excludetable", target) === true)) { + _$jscoverage['plugins/table.action.js'][794]++; + return; + } + _$jscoverage['plugins/table.action.js'][795]++; + pos = mouseCoords(evt); + _$jscoverage['plugins/table.action.js'][796]++; + var state = getRelation(target, pos), table = domUtils.findParentByTagName(target, "table", true); + _$jscoverage['plugins/table.action.js'][799]++; + if (inTableSide(table, target, evt, true)) { + _$jscoverage['plugins/table.action.js'][800]++; + if ((me.fireEvent("excludetable", table) === true)) { + _$jscoverage['plugins/table.action.js'][800]++; + return; + } + _$jscoverage['plugins/table.action.js'][801]++; + me.body.style.cursor = ("url(" + me.options.cursorpath + "h.png),pointer"); + } + else { + _$jscoverage['plugins/table.action.js'][802]++; + if (inTableSide(table, target, evt)) { + _$jscoverage['plugins/table.action.js'][803]++; + if ((me.fireEvent("excludetable", table) === true)) { + _$jscoverage['plugins/table.action.js'][803]++; + return; + } + _$jscoverage['plugins/table.action.js'][804]++; + me.body.style.cursor = ("url(" + me.options.cursorpath + "v.png),pointer"); + } + else { + _$jscoverage['plugins/table.action.js'][806]++; + me.body.style.cursor = "text"; + _$jscoverage['plugins/table.action.js'][807]++; + var curCell = target; + _$jscoverage['plugins/table.action.js'][808]++; + if (/\d/.test(state)) { + _$jscoverage['plugins/table.action.js'][809]++; + state = state.replace(/\d/, ""); + _$jscoverage['plugins/table.action.js'][810]++; + target = getUETable(target).getPreviewCell(target, (state == "v")); + } + _$jscoverage['plugins/table.action.js'][813]++; + toggleDraggableState(me, (target? (! (! state)): false), (target? state: ""), pos, target); + } + } + } + else { + _$jscoverage['plugins/table.action.js'][817]++; + toggleDragButton(false, table, me); + } + } + catch (e) { + _$jscoverage['plugins/table.action.js'][821]++; + showError(e); + } +} + _$jscoverage['plugins/table.action.js'][825]++; + var dragButtonTimer; + _$jscoverage['plugins/table.action.js'][827]++; + function toggleDragButton(show, table, editor) { + _$jscoverage['plugins/table.action.js'][828]++; + if ((! show)) { + _$jscoverage['plugins/table.action.js'][829]++; + if (dragOver) { + _$jscoverage['plugins/table.action.js'][829]++; + return; + } + _$jscoverage['plugins/table.action.js'][830]++; + dragButtonTimer = setTimeout((function () { + _$jscoverage['plugins/table.action.js'][831]++; + ((! dragOver) && dragButton && dragButton.parentNode && dragButton.parentNode.removeChild(dragButton)); +}), 2000); + } + else { + _$jscoverage['plugins/table.action.js'][834]++; + createDragButton(table, editor); + } +} + _$jscoverage['plugins/table.action.js'][838]++; + function createDragButton(table, editor) { + _$jscoverage['plugins/table.action.js'][839]++; + var pos = domUtils.getXY(table), doc = table.ownerDocument; + _$jscoverage['plugins/table.action.js'][841]++; + if ((dragButton && dragButton.parentNode)) { + _$jscoverage['plugins/table.action.js'][841]++; + return dragButton; + } + _$jscoverage['plugins/table.action.js'][842]++; + dragButton = doc.createElement("div"); + _$jscoverage['plugins/table.action.js'][843]++; + dragButton.contentEditable = false; + _$jscoverage['plugins/table.action.js'][844]++; + dragButton.innerHTML = ""; + _$jscoverage['plugins/table.action.js'][845]++; + dragButton.style.cssText = ("width:15px;height:15px;background-image:url(" + editor.options.UEDITOR_HOME_URL + "dialogs/table/dragicon.png);position: absolute;cursor:move;top:" + (pos.y - 15) + "px;left:" + pos.x + "px;"); + _$jscoverage['plugins/table.action.js'][846]++; + domUtils.unSelectable(dragButton); + _$jscoverage['plugins/table.action.js'][847]++; + dragButton.onmouseover = (function (evt) { + _$jscoverage['plugins/table.action.js'][848]++; + dragOver = true; +}); + _$jscoverage['plugins/table.action.js'][850]++; + dragButton.onmouseout = (function (evt) { + _$jscoverage['plugins/table.action.js'][851]++; + dragOver = false; +}); + _$jscoverage['plugins/table.action.js'][853]++; + domUtils.on(dragButton, "click", (function (type, evt) { + _$jscoverage['plugins/table.action.js'][854]++; + doClick(evt, this); +})); + _$jscoverage['plugins/table.action.js'][856]++; + domUtils.on(dragButton, "dblclick", (function (type, evt) { + _$jscoverage['plugins/table.action.js'][857]++; + doDblClick(evt); +})); + _$jscoverage['plugins/table.action.js'][859]++; + domUtils.on(dragButton, "dragstart", (function (type, evt) { + _$jscoverage['plugins/table.action.js'][860]++; + domUtils.preventDefault(evt); +})); + _$jscoverage['plugins/table.action.js'][862]++; + var timer; + _$jscoverage['plugins/table.action.js'][864]++; + function doClick(evt, button) { + _$jscoverage['plugins/table.action.js'][866]++; + clearTimeout(timer); + _$jscoverage['plugins/table.action.js'][867]++; + timer = setTimeout((function () { + _$jscoverage['plugins/table.action.js'][868]++; + editor.fireEvent("tableClicked", table, button); +}), 300); +} + _$jscoverage['plugins/table.action.js'][872]++; + function doDblClick(evt) { + _$jscoverage['plugins/table.action.js'][873]++; + clearTimeout(timer); + _$jscoverage['plugins/table.action.js'][874]++; + var ut = getUETable(table), start = table.rows[0].cells[0], end = ut.getLastCell(), range = ut.getCellsRange(start, end); + _$jscoverage['plugins/table.action.js'][878]++; + editor.selection.getRange().setStart(start, 0).setCursor(false, true); + _$jscoverage['plugins/table.action.js'][879]++; + ut.setSelected(range); +} + _$jscoverage['plugins/table.action.js'][882]++; + doc.body.appendChild(dragButton); +} + _$jscoverage['plugins/table.action.js'][897]++; + function inTableSide(table, cell, evt, top) { + _$jscoverage['plugins/table.action.js'][898]++; + var pos = mouseCoords(evt), state = getRelation(cell, pos); + _$jscoverage['plugins/table.action.js'][901]++; + if (top) { + _$jscoverage['plugins/table.action.js'][902]++; + var caption = table.getElementsByTagName("caption")[0], capHeight = (caption? caption.offsetHeight: 0); + _$jscoverage['plugins/table.action.js'][904]++; + return ((state == "v1") && ((pos.y - domUtils.getXY(table).y - capHeight) < 8)); + } + else { + _$jscoverage['plugins/table.action.js'][906]++; + return ((state == "h1") && ((pos.x - domUtils.getXY(table).x) < 8)); + } +} + _$jscoverage['plugins/table.action.js'][915]++; + function getPermissionX(dragTd, evt) { + _$jscoverage['plugins/table.action.js'][916]++; + var ut = getUETable(dragTd); + _$jscoverage['plugins/table.action.js'][917]++; + if (ut) { + _$jscoverage['plugins/table.action.js'][918]++; + var preTd = ut.getSameEndPosCells(dragTd, "x")[0], nextTd = ut.getSameStartPosXCells(dragTd)[0], mouseX = mouseCoords(evt).x, left = ((preTd? domUtils.getXY(preTd).x: domUtils.getXY(ut.table).x) + 20), right = (nextTd? ((domUtils.getXY(nextTd).x + nextTd.offsetWidth) - 20): ((me.body.offsetWidth + 5) || parseInt(domUtils.getComputedStyle(me.body, "width"), 10))); + _$jscoverage['plugins/table.action.js'][924]++; + left += cellMinWidth; + _$jscoverage['plugins/table.action.js'][925]++; + right -= cellMinWidth; + _$jscoverage['plugins/table.action.js'][927]++; + return ((mouseX < left)? left: ((mouseX > right)? right: mouseX)); + } +} + _$jscoverage['plugins/table.action.js'][934]++; + function getPermissionY(dragTd, evt) { + _$jscoverage['plugins/table.action.js'][935]++; + try { + _$jscoverage['plugins/table.action.js'][936]++; + var top = domUtils.getXY(dragTd).y, mousePosY = mouseCoords(evt).y; + _$jscoverage['plugins/table.action.js'][938]++; + return ((mousePosY < top)? top: mousePosY); + } + catch (e) { + _$jscoverage['plugins/table.action.js'][940]++; + showError(e); + } +} + _$jscoverage['plugins/table.action.js'][947]++; + function toggleDraggableState(editor, draggable, dir, mousePos, cell) { + _$jscoverage['plugins/table.action.js'][948]++; + try { + _$jscoverage['plugins/table.action.js'][949]++; + editor.body.style.cursor = ((dir == "h")? "col-resize": ((dir == "v")? "row-resize": "text")); + _$jscoverage['plugins/table.action.js'][950]++; + if (browser.ie) { + _$jscoverage['plugins/table.action.js'][951]++; + if ((dir && (! mousedown) && (! getUETableBySelected(editor)))) { + _$jscoverage['plugins/table.action.js'][952]++; + getDragLine(editor, editor.document); + _$jscoverage['plugins/table.action.js'][953]++; + showDragLineAt(dir, cell); + } + else { + _$jscoverage['plugins/table.action.js'][955]++; + hideDragLine(editor); + } + } + _$jscoverage['plugins/table.action.js'][958]++; + onBorder = draggable; + } + catch (e) { + _$jscoverage['plugins/table.action.js'][960]++; + showError(e); + } +} + _$jscoverage['plugins/table.action.js'][968]++; + function getResizeLineByUETable() { + _$jscoverage['plugins/table.action.js'][970]++; + var lineId = "_UETableResizeLine", line = this.document.getElementById(lineId); + _$jscoverage['plugins/table.action.js'][973]++; + if ((! line)) { + _$jscoverage['plugins/table.action.js'][974]++; + line = this.document.createElement("div"); + _$jscoverage['plugins/table.action.js'][975]++; + line.id = lineId; + _$jscoverage['plugins/table.action.js'][976]++; + line.contnetEditable = false; + _$jscoverage['plugins/table.action.js'][977]++; + line.setAttribute("unselectable", "on"); + _$jscoverage['plugins/table.action.js'][979]++; + var styles = {width: ((2 * cellBorderWidth) + 1 + "px"), position: "absolute", "z-index": 100000, cursor: "col-resize", background: "red", display: "none"}; + _$jscoverage['plugins/table.action.js'][989]++; + line.onmouseout = (function () { + _$jscoverage['plugins/table.action.js'][990]++; + this.style.display = "none"; +}); + _$jscoverage['plugins/table.action.js'][993]++; + utils.extend(line.style, styles); + _$jscoverage['plugins/table.action.js'][995]++; + this.document.body.appendChild(line); + } + _$jscoverage['plugins/table.action.js'][999]++; + return line; +} + _$jscoverage['plugins/table.action.js'][1006]++; + function updateResizeLine(cell, uetable) { + _$jscoverage['plugins/table.action.js'][1008]++; + var line = getResizeLineByUETable.call(this), table = uetable.table, styles = {top: (domUtils.getXY(table).y + "px"), left: (((domUtils.getXY(cell).x + cell.offsetWidth) - cellBorderWidth) + "px"), display: "block", height: (table.offsetHeight + "px")}; + _$jscoverage['plugins/table.action.js'][1017]++; + utils.extend(line.style, styles); +} + _$jscoverage['plugins/table.action.js'][1024]++; + function showResizeLine(cell) { + _$jscoverage['plugins/table.action.js'][1026]++; + var uetable = getUETable(cell); + _$jscoverage['plugins/table.action.js'][1028]++; + updateResizeLine.call(this, cell, uetable); +} + _$jscoverage['plugins/table.action.js'][1037]++; + function getRelation(ele, mousePos) { + _$jscoverage['plugins/table.action.js'][1038]++; + var elePos = domUtils.getXY(ele); + _$jscoverage['plugins/table.action.js'][1040]++; + if ((! elePos)) { + _$jscoverage['plugins/table.action.js'][1041]++; + return ""; + } + _$jscoverage['plugins/table.action.js'][1044]++; + if ((((elePos.x + ele.offsetWidth) - mousePos.x) < cellBorderWidth)) { + _$jscoverage['plugins/table.action.js'][1045]++; + return "h"; + } + _$jscoverage['plugins/table.action.js'][1047]++; + if (((mousePos.x - elePos.x) < cellBorderWidth)) { + _$jscoverage['plugins/table.action.js'][1048]++; + return "h1"; + } + _$jscoverage['plugins/table.action.js'][1050]++; + if ((((elePos.y + ele.offsetHeight) - mousePos.y) < cellBorderWidth)) { + _$jscoverage['plugins/table.action.js'][1051]++; + return "v"; + } + _$jscoverage['plugins/table.action.js'][1053]++; + if (((mousePos.y - elePos.y) < cellBorderWidth)) { + _$jscoverage['plugins/table.action.js'][1054]++; + return "v1"; + } + _$jscoverage['plugins/table.action.js'][1056]++; + return ""; +} + _$jscoverage['plugins/table.action.js'][1059]++; + function mouseDownEvent(type, evt) { + _$jscoverage['plugins/table.action.js'][1061]++; + if (isEditorDisabled()) { + _$jscoverage['plugins/table.action.js'][1062]++; + return; + } + _$jscoverage['plugins/table.action.js'][1065]++; + userActionStatus = {x: evt.clientX, y: evt.clientY}; + _$jscoverage['plugins/table.action.js'][1071]++; + if ((evt.button == 2)) { + _$jscoverage['plugins/table.action.js'][1072]++; + var ut = getUETableBySelected(me), flag = false; + _$jscoverage['plugins/table.action.js'][1075]++; + if (ut) { + _$jscoverage['plugins/table.action.js'][1076]++; + var td = getTargetTd(me, evt); + _$jscoverage['plugins/table.action.js'][1077]++; + utils.each(ut.selectedTds, (function (ti) { + _$jscoverage['plugins/table.action.js'][1078]++; + if ((ti === td)) { + _$jscoverage['plugins/table.action.js'][1079]++; + flag = true; + } +})); + _$jscoverage['plugins/table.action.js'][1082]++; + if ((! flag)) { + _$jscoverage['plugins/table.action.js'][1083]++; + removeSelectedClass(domUtils.getElementsByTagName(me.body, "th td")); + _$jscoverage['plugins/table.action.js'][1084]++; + ut.clearSelected(); + } + else { + _$jscoverage['plugins/table.action.js'][1086]++; + td = ut.selectedTds[0]; + _$jscoverage['plugins/table.action.js'][1087]++; + setTimeout((function () { + _$jscoverage['plugins/table.action.js'][1088]++; + me.selection.getRange().setStart(td, 0).setCursor(false, true); +}), 0); + } + } + } + else { + _$jscoverage['plugins/table.action.js'][1094]++; + tableClickHander(evt); + } +} + _$jscoverage['plugins/table.action.js'][1100]++; + function clearTableTimer() { + _$jscoverage['plugins/table.action.js'][1101]++; + (tabTimer && clearTimeout(tabTimer)); + _$jscoverage['plugins/table.action.js'][1102]++; + tabTimer = null; +} + _$jscoverage['plugins/table.action.js'][1106]++; + function tableDbclickHandler(evt) { + _$jscoverage['plugins/table.action.js'][1107]++; + singleClickState = 0; + _$jscoverage['plugins/table.action.js'][1108]++; + evt = (evt || me.window.event); + _$jscoverage['plugins/table.action.js'][1109]++; + var target = getParentTdOrTh((evt.target || evt.srcElement)); + _$jscoverage['plugins/table.action.js'][1110]++; + if (target) { + _$jscoverage['plugins/table.action.js'][1111]++; + var h; + _$jscoverage['plugins/table.action.js'][1112]++; + if ((h = getRelation(target, mouseCoords(evt)))) { + _$jscoverage['plugins/table.action.js'][1114]++; + hideDragLine(me); + _$jscoverage['plugins/table.action.js'][1116]++; + if ((h == "h1")) { + _$jscoverage['plugins/table.action.js'][1117]++; + h = "h"; + _$jscoverage['plugins/table.action.js'][1118]++; + if (inTableSide(domUtils.findParentByTagName(target, "table"), target, evt)) { + _$jscoverage['plugins/table.action.js'][1119]++; + me.execCommand("adaptbywindow"); + } + else { + _$jscoverage['plugins/table.action.js'][1121]++; + target = getUETable(target).getPreviewCell(target); + _$jscoverage['plugins/table.action.js'][1122]++; + if (target) { + _$jscoverage['plugins/table.action.js'][1123]++; + var rng = me.selection.getRange(); + _$jscoverage['plugins/table.action.js'][1124]++; + rng.selectNodeContents(target).setCursor(true, true); + } + } + } + _$jscoverage['plugins/table.action.js'][1128]++; + if ((h == "h")) { + _$jscoverage['plugins/table.action.js'][1129]++; + var ut = getUETable(target), table = ut.table, cells = getCellsByMoveBorder(target, table, true); + _$jscoverage['plugins/table.action.js'][1133]++; + cells = extractArray(cells, "left"); + _$jscoverage['plugins/table.action.js'][1135]++; + ut.width = ut.offsetWidth; + _$jscoverage['plugins/table.action.js'][1137]++; + var oldWidth = [], newWidth = []; + _$jscoverage['plugins/table.action.js'][1140]++; + utils.each(cells, (function (cell) { + _$jscoverage['plugins/table.action.js'][1142]++; + oldWidth.push(cell.offsetWidth); +})); + _$jscoverage['plugins/table.action.js'][1146]++; + utils.each(cells, (function (cell) { + _$jscoverage['plugins/table.action.js'][1148]++; + cell.removeAttribute("width"); +})); + _$jscoverage['plugins/table.action.js'][1152]++; + window.setTimeout((function () { + _$jscoverage['plugins/table.action.js'][1155]++; + var changeable = true; + _$jscoverage['plugins/table.action.js'][1157]++; + utils.each(cells, (function (cell, index) { + _$jscoverage['plugins/table.action.js'][1159]++; + var width = cell.offsetWidth; + _$jscoverage['plugins/table.action.js'][1161]++; + if ((width > oldWidth[index])) { + _$jscoverage['plugins/table.action.js'][1162]++; + changeable = false; + _$jscoverage['plugins/table.action.js'][1163]++; + return false; + } + _$jscoverage['plugins/table.action.js'][1166]++; + newWidth.push(width); +})); + _$jscoverage['plugins/table.action.js'][1170]++; + var change = (changeable? newWidth: oldWidth); + _$jscoverage['plugins/table.action.js'][1172]++; + utils.each(cells, (function (cell, index) { + _$jscoverage['plugins/table.action.js'][1174]++; + cell.width = (change[index] - getTabcellSpace()); +})); +}), 0); + } + } + } +} + _$jscoverage['plugins/table.action.js'][1194]++; + function tableClickHander(evt) { + _$jscoverage['plugins/table.action.js'][1196]++; + removeSelectedClass(domUtils.getElementsByTagName(me.body, "td th")); + _$jscoverage['plugins/table.action.js'][1199]++; + utils.each(me.document.getElementsByTagName("table"), (function (t) { + _$jscoverage['plugins/table.action.js'][1200]++; + t.ueTable = null; +})); + _$jscoverage['plugins/table.action.js'][1202]++; + startTd = getTargetTd(me, evt); + _$jscoverage['plugins/table.action.js'][1203]++; + if ((! startTd)) { + _$jscoverage['plugins/table.action.js'][1203]++; + return; + } + _$jscoverage['plugins/table.action.js'][1204]++; + var table = domUtils.findParentByTagName(startTd, "table", true); + _$jscoverage['plugins/table.action.js'][1205]++; + ut = getUETable(table); + _$jscoverage['plugins/table.action.js'][1206]++; + (ut && ut.clearSelected()); + _$jscoverage['plugins/table.action.js'][1209]++; + if ((! onBorder)) { + _$jscoverage['plugins/table.action.js'][1210]++; + me.document.body.style.webkitUserSelect = ""; + _$jscoverage['plugins/table.action.js'][1211]++; + mousedown = true; + _$jscoverage['plugins/table.action.js'][1212]++; + me.addListener("mouseover", mouseOverEvent); + } + else { + _$jscoverage['plugins/table.action.js'][1215]++; + borderActionHandler(evt); + } +} + _$jscoverage['plugins/table.action.js'][1222]++; + function borderActionHandler(evt) { + _$jscoverage['plugins/table.action.js'][1224]++; + if (browser.ie) { + _$jscoverage['plugins/table.action.js'][1225]++; + evt = reconstruct(evt); + } + _$jscoverage['plugins/table.action.js'][1228]++; + clearTableDragTimer(); + _$jscoverage['plugins/table.action.js'][1231]++; + isInResizeBuffer = true; + _$jscoverage['plugins/table.action.js'][1233]++; + tableDragTimer = setTimeout((function () { + _$jscoverage['plugins/table.action.js'][1234]++; + tableBorderDrag(evt); +}), dblclickTime); +} + _$jscoverage['plugins/table.action.js'][1239]++; + function extractArray(originArr, key) { + _$jscoverage['plugins/table.action.js'][1241]++; + var result = [], tmp = null; + _$jscoverage['plugins/table.action.js'][1244]++; + for (var i = 0, len = originArr.length; (i < len); (i++)) { + _$jscoverage['plugins/table.action.js'][1246]++; + tmp = originArr[i][key]; + _$jscoverage['plugins/table.action.js'][1248]++; + if (tmp) { + _$jscoverage['plugins/table.action.js'][1249]++; + result.push(tmp); + } +} + _$jscoverage['plugins/table.action.js'][1254]++; + return result; +} + _$jscoverage['plugins/table.action.js'][1258]++; + function clearTableDragTimer() { + _$jscoverage['plugins/table.action.js'][1259]++; + (tableDragTimer && clearTimeout(tableDragTimer)); + _$jscoverage['plugins/table.action.js'][1260]++; + tableDragTimer = null; +} + _$jscoverage['plugins/table.action.js'][1263]++; + function reconstruct(obj) { + _$jscoverage['plugins/table.action.js'][1265]++; + var attrs = ["pageX", "pageY", "clientX", "clientY", "srcElement", "target"], newObj = {}; + _$jscoverage['plugins/table.action.js'][1268]++; + if (obj) { + _$jscoverage['plugins/table.action.js'][1270]++; + for (var i = 0, key, val; (key = attrs[i]); (i++)) { + _$jscoverage['plugins/table.action.js'][1271]++; + val = obj[key]; + _$jscoverage['plugins/table.action.js'][1272]++; + (val && (newObj[key] = val)); +} + } + _$jscoverage['plugins/table.action.js'][1277]++; + return newObj; +} + _$jscoverage['plugins/table.action.js'][1282]++; + function tableBorderDrag(evt) { + _$jscoverage['plugins/table.action.js'][1284]++; + isInResizeBuffer = false; + _$jscoverage['plugins/table.action.js'][1286]++; + if ((! startTd)) { + _$jscoverage['plugins/table.action.js'][1286]++; + return; + } + _$jscoverage['plugins/table.action.js'][1287]++; + var state = ((Math.abs((userActionStatus.x - evt.clientX)) >= Math.abs((userActionStatus.y - evt.clientY)))? "h": "v"); + _$jscoverage['plugins/table.action.js'][1289]++; + if (/\d/.test(state)) { + _$jscoverage['plugins/table.action.js'][1290]++; + state = state.replace(/\d/, ""); + _$jscoverage['plugins/table.action.js'][1291]++; + startTd = getUETable(startTd).getPreviewCell(startTd, (state == "v")); + } + _$jscoverage['plugins/table.action.js'][1293]++; + hideDragLine(me); + _$jscoverage['plugins/table.action.js'][1294]++; + getDragLine(me, me.document); + _$jscoverage['plugins/table.action.js'][1295]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/table.action.js'][1296]++; + showDragLineAt(state, startTd); + _$jscoverage['plugins/table.action.js'][1297]++; + mousedown = true; + _$jscoverage['plugins/table.action.js'][1299]++; + onDrag = state; + _$jscoverage['plugins/table.action.js'][1300]++; + dragTd = startTd; +} + _$jscoverage['plugins/table.action.js'][1303]++; + function mouseUpEvent(type, evt) { + _$jscoverage['plugins/table.action.js'][1305]++; + if (isEditorDisabled()) { + _$jscoverage['plugins/table.action.js'][1306]++; + return; + } + _$jscoverage['plugins/table.action.js'][1309]++; + clearTableDragTimer(); + _$jscoverage['plugins/table.action.js'][1311]++; + isInResizeBuffer = false; + _$jscoverage['plugins/table.action.js'][1313]++; + if (onBorder) { + _$jscoverage['plugins/table.action.js'][1314]++; + singleClickState = ((++singleClickState) % 3); + _$jscoverage['plugins/table.action.js'][1316]++; + userActionStatus = {x: evt.clientX, y: evt.clientY}; + _$jscoverage['plugins/table.action.js'][1321]++; + tableResizeTimer = setTimeout((function () { + _$jscoverage['plugins/table.action.js'][1322]++; + ((singleClickState > 0) && (singleClickState--)); +}), dblclickTime); + _$jscoverage['plugins/table.action.js'][1325]++; + if ((singleClickState === 2)) { + _$jscoverage['plugins/table.action.js'][1327]++; + singleClickState = 0; + _$jscoverage['plugins/table.action.js'][1328]++; + tableDbclickHandler(evt); + _$jscoverage['plugins/table.action.js'][1329]++; + return; + } + } + _$jscoverage['plugins/table.action.js'][1335]++; + if ((evt.button == 2)) { + _$jscoverage['plugins/table.action.js'][1335]++; + return; + } + _$jscoverage['plugins/table.action.js'][1336]++; + var me = this; + _$jscoverage['plugins/table.action.js'][1338]++; + var range = me.selection.getRange(), start = domUtils.findParentByTagName(range.startContainer, "table", true), end = domUtils.findParentByTagName(range.endContainer, "table", true); + _$jscoverage['plugins/table.action.js'][1342]++; + if ((start || end)) { + _$jscoverage['plugins/table.action.js'][1343]++; + if ((start === end)) { + _$jscoverage['plugins/table.action.js'][1344]++; + start = domUtils.findParentByTagName(range.startContainer, ["td", "th", "caption"], true); + _$jscoverage['plugins/table.action.js'][1345]++; + end = domUtils.findParentByTagName(range.endContainer, ["td", "th", "caption"], true); + _$jscoverage['plugins/table.action.js'][1346]++; + if ((start !== end)) { + _$jscoverage['plugins/table.action.js'][1347]++; + me.selection.clearRange(); + } + } + else { + _$jscoverage['plugins/table.action.js'][1350]++; + me.selection.clearRange(); + } + } + _$jscoverage['plugins/table.action.js'][1353]++; + mousedown = false; + _$jscoverage['plugins/table.action.js'][1354]++; + me.document.body.style.webkitUserSelect = ""; + _$jscoverage['plugins/table.action.js'][1356]++; + if ((onDrag && dragTd)) { + _$jscoverage['plugins/table.action.js'][1358]++; + (me.selection.getNative()[(browser.ie? "empty": "removeAllRanges")])(); + _$jscoverage['plugins/table.action.js'][1360]++; + singleClickState = 0; + _$jscoverage['plugins/table.action.js'][1361]++; + dragLine = me.document.getElementById("ue_tableDragLine"); + _$jscoverage['plugins/table.action.js'][1363]++; + var dragTdPos = domUtils.getXY(dragTd), dragLinePos = domUtils.getXY(dragLine); + _$jscoverage['plugins/table.action.js'][1366]++; + switch (onDrag) { + case "h": + _$jscoverage['plugins/table.action.js'][1368]++; + changeColWidth(dragTd, (dragLinePos.x - dragTdPos.x)); + _$jscoverage['plugins/table.action.js'][1369]++; + break; + case "v": + _$jscoverage['plugins/table.action.js'][1371]++; + changeRowHeight(dragTd, (dragLinePos.y - dragTdPos.y - dragTd.offsetHeight)); + _$jscoverage['plugins/table.action.js'][1372]++; + break; + default: + } + _$jscoverage['plugins/table.action.js'][1375]++; + onDrag = ""; + _$jscoverage['plugins/table.action.js'][1376]++; + dragTd = null; + _$jscoverage['plugins/table.action.js'][1378]++; + hideDragLine(me); + _$jscoverage['plugins/table.action.js'][1379]++; + me.fireEvent("saveScene"); + _$jscoverage['plugins/table.action.js'][1380]++; + return; + } + _$jscoverage['plugins/table.action.js'][1383]++; + if ((! startTd)) { + _$jscoverage['plugins/table.action.js'][1384]++; + var target = domUtils.findParentByTagName((evt.target || evt.srcElement), "td", true); + _$jscoverage['plugins/table.action.js'][1385]++; + if ((! target)) { + _$jscoverage['plugins/table.action.js'][1385]++; + target = domUtils.findParentByTagName((evt.target || evt.srcElement), "th", true); + } + _$jscoverage['plugins/table.action.js'][1386]++; + if ((target && ((target.tagName == "TD") || (target.tagName == "TH")))) { + _$jscoverage['plugins/table.action.js'][1387]++; + if ((me.fireEvent("excludetable", target) === true)) { + _$jscoverage['plugins/table.action.js'][1387]++; + return; + } + _$jscoverage['plugins/table.action.js'][1388]++; + range = new (dom.Range)(me.document); + _$jscoverage['plugins/table.action.js'][1389]++; + range.setStart(target, 0).setCursor(false, true); + } + } + else { + _$jscoverage['plugins/table.action.js'][1392]++; + var ut = getUETable(startTd), cell = (ut? ut.selectedTds[0]: null); + _$jscoverage['plugins/table.action.js'][1394]++; + if (cell) { + _$jscoverage['plugins/table.action.js'][1395]++; + range = new (dom.Range)(me.document); + _$jscoverage['plugins/table.action.js'][1396]++; + if (domUtils.isEmptyBlock(cell)) { + _$jscoverage['plugins/table.action.js'][1397]++; + range.setStart(cell, 0).setCursor(false, true); + } + else { + _$jscoverage['plugins/table.action.js'][1399]++; + range.selectNodeContents(cell).shrinkBoundary().setCursor(false, true); + } + } + else { + _$jscoverage['plugins/table.action.js'][1402]++; + range = me.selection.getRange().shrinkBoundary(); + _$jscoverage['plugins/table.action.js'][1403]++; + if ((! range.collapsed)) { + _$jscoverage['plugins/table.action.js'][1404]++; + var start = domUtils.findParentByTagName(range.startContainer, ["td", "th"], true), end = domUtils.findParentByTagName(range.endContainer, ["td", "th"], true); + _$jscoverage['plugins/table.action.js'][1407]++; + if (((start && (! end)) || ((! start) && end) || (start && end && (start !== end)))) { + _$jscoverage['plugins/table.action.js'][1408]++; + range.setCursor(false, true); + } + } + } + _$jscoverage['plugins/table.action.js'][1412]++; + startTd = null; + _$jscoverage['plugins/table.action.js'][1413]++; + me.removeListener("mouseover", mouseOverEvent); + } + _$jscoverage['plugins/table.action.js'][1415]++; + me._selectionChange(250, evt); +} + _$jscoverage['plugins/table.action.js'][1418]++; + function mouseOverEvent(type, evt) { + _$jscoverage['plugins/table.action.js'][1420]++; + if (isEditorDisabled()) { + _$jscoverage['plugins/table.action.js'][1421]++; + return; + } + _$jscoverage['plugins/table.action.js'][1424]++; + var me = this, tar = (evt.target || evt.srcElement); + _$jscoverage['plugins/table.action.js'][1426]++; + currentTd = (domUtils.findParentByTagName(tar, "td", true) || domUtils.findParentByTagName(tar, "th", true)); + _$jscoverage['plugins/table.action.js'][1428]++; + if ((startTd && currentTd && (((startTd.tagName == "TD") && (currentTd.tagName == "TD")) || ((startTd.tagName == "TH") && (currentTd.tagName == "TH"))) && (domUtils.findParentByTagName(startTd, "table") == domUtils.findParentByTagName(currentTd, "table")))) { + _$jscoverage['plugins/table.action.js'][1431]++; + var ut = getUETable(currentTd); + _$jscoverage['plugins/table.action.js'][1432]++; + if ((startTd != currentTd)) { + _$jscoverage['plugins/table.action.js'][1433]++; + me.document.body.style.webkitUserSelect = "none"; + _$jscoverage['plugins/table.action.js'][1434]++; + (me.selection.getNative()[(browser.ie? "empty": "removeAllRanges")])(); + _$jscoverage['plugins/table.action.js'][1435]++; + var range = ut.getCellsRange(startTd, currentTd); + _$jscoverage['plugins/table.action.js'][1436]++; + ut.setSelected(range); + } + else { + _$jscoverage['plugins/table.action.js'][1438]++; + me.document.body.style.webkitUserSelect = ""; + _$jscoverage['plugins/table.action.js'][1439]++; + ut.clearSelected(); + } + } + _$jscoverage['plugins/table.action.js'][1443]++; + (evt.preventDefault? evt.preventDefault(): (evt.returnValue = false)); +} + _$jscoverage['plugins/table.action.js'][1446]++; + function setCellHeight(cell, height, backHeight) { + _$jscoverage['plugins/table.action.js'][1447]++; + var lineHight = parseInt(domUtils.getComputedStyle(cell, "line-height"), 10), tmpHeight = (backHeight + height); + _$jscoverage['plugins/table.action.js'][1449]++; + height = ((tmpHeight < lineHight)? lineHight: tmpHeight); + _$jscoverage['plugins/table.action.js'][1450]++; + if (cell.style.height) { + _$jscoverage['plugins/table.action.js'][1450]++; + cell.style.height = ""; + } + _$jscoverage['plugins/table.action.js'][1451]++; + ((cell.rowSpan == 1)? cell.setAttribute("height", height): (cell.removeAttribute && cell.removeAttribute("height"))); +} + _$jscoverage['plugins/table.action.js'][1454]++; + function getWidth(cell) { + _$jscoverage['plugins/table.action.js'][1455]++; + if ((! cell)) { + _$jscoverage['plugins/table.action.js'][1455]++; + return 0; + } + _$jscoverage['plugins/table.action.js'][1456]++; + return parseInt(domUtils.getComputedStyle(cell, "width"), 10); +} + _$jscoverage['plugins/table.action.js'][1459]++; + function changeColWidth(cell, changeValue) { + _$jscoverage['plugins/table.action.js'][1461]++; + var ut = getUETable(cell); + _$jscoverage['plugins/table.action.js'][1462]++; + if (ut) { + _$jscoverage['plugins/table.action.js'][1465]++; + var table = ut.table, cells = getCellsByMoveBorder(cell, table); + _$jscoverage['plugins/table.action.js'][1468]++; + table.style.width = ""; + _$jscoverage['plugins/table.action.js'][1469]++; + table.removeAttribute("width"); + _$jscoverage['plugins/table.action.js'][1472]++; + changeValue = correctChangeValue(changeValue, cell, cells); + _$jscoverage['plugins/table.action.js'][1474]++; + if (cell.nextSibling) { + _$jscoverage['plugins/table.action.js'][1476]++; + var i = 0; + _$jscoverage['plugins/table.action.js'][1478]++; + utils.each(cells, (function (cellGroup) { + _$jscoverage['plugins/table.action.js'][1480]++; + cellGroup.left.width = ((+ cellGroup.left.width) + changeValue); + _$jscoverage['plugins/table.action.js'][1481]++; + (cellGroup.right && (cellGroup.right.width = ((+ cellGroup.right.width) - changeValue))); +})); + } + else { + _$jscoverage['plugins/table.action.js'][1487]++; + utils.each(cells, (function (cellGroup) { + _$jscoverage['plugins/table.action.js'][1488]++; + cellGroup.left.width -= (- changeValue); +})); + } + } +} + _$jscoverage['plugins/table.action.js'][1496]++; + function isEditorDisabled() { + _$jscoverage['plugins/table.action.js'][1497]++; + return (me.body.contentEditable === "false"); +} + _$jscoverage['plugins/table.action.js'][1500]++; + function changeRowHeight(td, changeValue) { + _$jscoverage['plugins/table.action.js'][1501]++; + if ((Math.abs(changeValue) < 10)) { + _$jscoverage['plugins/table.action.js'][1501]++; + return; + } + _$jscoverage['plugins/table.action.js'][1502]++; + var ut = getUETable(td); + _$jscoverage['plugins/table.action.js'][1503]++; + if (ut) { + _$jscoverage['plugins/table.action.js'][1504]++; + var cells = ut.getSameEndPosCells(td, "y"), backHeight = (cells[0]? cells[0].offsetHeight: 0); + _$jscoverage['plugins/table.action.js'][1507]++; + for (var i = 0, cell; (cell = cells[(i++)]);) { + _$jscoverage['plugins/table.action.js'][1508]++; + setCellHeight(cell, changeValue, backHeight); +} + } +} + _$jscoverage['plugins/table.action.js'][1518]++; + function getCellsByMoveBorder(cell, table, isContainMergeCell) { + _$jscoverage['plugins/table.action.js'][1520]++; + if ((! table)) { + _$jscoverage['plugins/table.action.js'][1521]++; + table = domUtils.findParentByTagName(cell, "table"); + } + _$jscoverage['plugins/table.action.js'][1524]++; + if ((! table)) { + _$jscoverage['plugins/table.action.js'][1525]++; + return null; + } + _$jscoverage['plugins/table.action.js'][1529]++; + var index = domUtils.getNodeIndex(cell), temp = cell, rows = table.rows, colIndex = 0; + _$jscoverage['plugins/table.action.js'][1534]++; + while (temp) { + _$jscoverage['plugins/table.action.js'][1536]++; + if ((temp.nodeType === 1)) { + _$jscoverage['plugins/table.action.js'][1537]++; + colIndex += (temp.colSpan || 1); + } + _$jscoverage['plugins/table.action.js'][1539]++; + temp = temp.previousSibling; +} + _$jscoverage['plugins/table.action.js'][1542]++; + temp = null; + _$jscoverage['plugins/table.action.js'][1545]++; + var borderCells = []; + _$jscoverage['plugins/table.action.js'][1547]++; + utils.each(rows, (function (tabRow) { + _$jscoverage['plugins/table.action.js'][1549]++; + var cells = tabRow.cells, currIndex = 0; + _$jscoverage['plugins/table.action.js'][1552]++; + utils.each(cells, (function (tabCell) { + _$jscoverage['plugins/table.action.js'][1554]++; + currIndex += (tabCell.colSpan || 1); + _$jscoverage['plugins/table.action.js'][1556]++; + if ((currIndex === colIndex)) { + _$jscoverage['plugins/table.action.js'][1558]++; + borderCells.push({left: tabCell, right: (tabCell.nextSibling || null)}); + _$jscoverage['plugins/table.action.js'][1563]++; + return false; + } + else { + _$jscoverage['plugins/table.action.js'][1565]++; + if ((currIndex > colIndex)) { + _$jscoverage['plugins/table.action.js'][1567]++; + if (isContainMergeCell) { + _$jscoverage['plugins/table.action.js'][1568]++; + borderCells.push({left: tabCell}); + } + _$jscoverage['plugins/table.action.js'][1573]++; + return false; + } + } +})); +})); + _$jscoverage['plugins/table.action.js'][1581]++; + return borderCells; +} + _$jscoverage['plugins/table.action.js'][1589]++; + function getMinWidthByTableCells(cells) { + _$jscoverage['plugins/table.action.js'][1591]++; + var minWidth = Number.MAX_VALUE; + _$jscoverage['plugins/table.action.js'][1593]++; + for (var i = 0, curCell; (curCell = cells[i]); (i++)) { + _$jscoverage['plugins/table.action.js'][1595]++; + minWidth = Math.min(minWidth, (curCell.width || getTableCellWidth(curCell))); +} + _$jscoverage['plugins/table.action.js'][1599]++; + return minWidth; +} + _$jscoverage['plugins/table.action.js'][1603]++; + function correctChangeValue(changeValue, relatedCell, cells) { + _$jscoverage['plugins/table.action.js'][1606]++; + changeValue -= getTabcellSpace(); + _$jscoverage['plugins/table.action.js'][1608]++; + if ((changeValue < 0)) { + _$jscoverage['plugins/table.action.js'][1609]++; + return 0; + } + _$jscoverage['plugins/table.action.js'][1612]++; + changeValue -= getTableCellWidth(relatedCell); + _$jscoverage['plugins/table.action.js'][1615]++; + var direction = ((changeValue < 0)? "left": "right"); + _$jscoverage['plugins/table.action.js'][1617]++; + changeValue = Math.abs(changeValue); + _$jscoverage['plugins/table.action.js'][1620]++; + utils.each(cells, (function (cellGroup) { + _$jscoverage['plugins/table.action.js'][1622]++; + var curCell = cellGroup[direction]; + _$jscoverage['plugins/table.action.js'][1625]++; + if (curCell) { + _$jscoverage['plugins/table.action.js'][1626]++; + changeValue = Math.min(changeValue, (getTableCellWidth(curCell) - cellMinWidth)); + } +})); + _$jscoverage['plugins/table.action.js'][1634]++; + changeValue = ((changeValue < 0)? 0: changeValue); + _$jscoverage['plugins/table.action.js'][1636]++; + return ((direction === "left")? (- changeValue): changeValue); +} + _$jscoverage['plugins/table.action.js'][1640]++; + function getTableCellWidth(cell) { + _$jscoverage['plugins/table.action.js'][1642]++; + var width = 0, offset = 0, width = (cell.offsetWidth - getTabcellSpace()); + _$jscoverage['plugins/table.action.js'][1648]++; + if ((! cell.nextSibling)) { + _$jscoverage['plugins/table.action.js'][1650]++; + width -= getTableCellOffset(cell); + } + _$jscoverage['plugins/table.action.js'][1654]++; + width = ((width < 0)? 0: width); + _$jscoverage['plugins/table.action.js'][1656]++; + try { + _$jscoverage['plugins/table.action.js'][1657]++; + cell.width = width; + } + catch (e) { + } + _$jscoverage['plugins/table.action.js'][1661]++; + return width; +} + _$jscoverage['plugins/table.action.js'][1668]++; + function getTableCellOffset(cell) { + _$jscoverage['plugins/table.action.js'][1670]++; + tab = domUtils.findParentByTagName(cell, "table", false); + _$jscoverage['plugins/table.action.js'][1672]++; + if ((tab.offsetVal === undefined)) { + _$jscoverage['plugins/table.action.js'][1674]++; + var prev = cell.previousSibling; + _$jscoverage['plugins/table.action.js'][1676]++; + if (prev) { + _$jscoverage['plugins/table.action.js'][1679]++; + tab.offsetVal = (((cell.offsetWidth - prev.offsetWidth) === UT.borderWidth)? UT.borderWidth: 0); + } + else { + _$jscoverage['plugins/table.action.js'][1682]++; + tab.offsetVal = 0; + } + } + _$jscoverage['plugins/table.action.js'][1687]++; + return tab.offsetVal; +} + _$jscoverage['plugins/table.action.js'][1691]++; + function getTabcellSpace() { + _$jscoverage['plugins/table.action.js'][1693]++; + if ((UT.tabcellSpace === undefined)) { + _$jscoverage['plugins/table.action.js'][1695]++; + var cell = null, tab = me.document.createElement("table"), tbody = me.document.createElement("tbody"), trow = me.document.createElement("tr"), tabcell = me.document.createElement("td"), mirror = null; + _$jscoverage['plugins/table.action.js'][1702]++; + tabcell.style.cssText = "border: 0;"; + _$jscoverage['plugins/table.action.js'][1703]++; + tabcell.width = 1; + _$jscoverage['plugins/table.action.js'][1705]++; + trow.appendChild(tabcell); + _$jscoverage['plugins/table.action.js'][1706]++; + trow.appendChild((mirror = tabcell.cloneNode(false))); + _$jscoverage['plugins/table.action.js'][1708]++; + tbody.appendChild(trow); + _$jscoverage['plugins/table.action.js'][1710]++; + tab.appendChild(tbody); + _$jscoverage['plugins/table.action.js'][1712]++; + tab.style.cssText = "visibility: hidden;"; + _$jscoverage['plugins/table.action.js'][1714]++; + me.body.appendChild(tab); + _$jscoverage['plugins/table.action.js'][1716]++; + UT.paddingSpace = (tabcell.offsetWidth - 1); + _$jscoverage['plugins/table.action.js'][1718]++; + var tmpTabWidth = tab.offsetWidth; + _$jscoverage['plugins/table.action.js'][1720]++; + tabcell.style.cssText = ""; + _$jscoverage['plugins/table.action.js'][1721]++; + mirror.style.cssText = ""; + _$jscoverage['plugins/table.action.js'][1723]++; + UT.borderWidth = ((tab.offsetWidth - tmpTabWidth) / 3); + _$jscoverage['plugins/table.action.js'][1725]++; + UT.tabcellSpace = (UT.paddingSpace + UT.borderWidth); + _$jscoverage['plugins/table.action.js'][1727]++; + me.body.removeChild(tab); + } + _$jscoverage['plugins/table.action.js'][1731]++; + getTabcellSpace = (function () { + _$jscoverage['plugins/table.action.js'][1731]++; + return UT.tabcellSpace; +}); + _$jscoverage['plugins/table.action.js'][1733]++; + return UT.tabcellSpace; +} + _$jscoverage['plugins/table.action.js'][1737]++; + function getDragLine(editor, doc) { + _$jscoverage['plugins/table.action.js'][1738]++; + if (mousedown) { + _$jscoverage['plugins/table.action.js'][1738]++; + return; + } + _$jscoverage['plugins/table.action.js'][1739]++; + dragLine = editor.document.createElement("div"); + _$jscoverage['plugins/table.action.js'][1740]++; + domUtils.setAttributes(dragLine, {id: "ue_tableDragLine", unselectable: "on", contenteditable: false, "onresizestart": "return false", "ondragstart": "return false", "onselectstart": "return false", style: "background-color:blue;position:absolute;padding:0;margin:0;background-image:none;border:0px none;opacity:0;filter:alpha(opacity=0)"}); + _$jscoverage['plugins/table.action.js'][1749]++; + editor.body.appendChild(dragLine); +} + _$jscoverage['plugins/table.action.js'][1752]++; + function hideDragLine(editor) { + _$jscoverage['plugins/table.action.js'][1753]++; + if (mousedown) { + _$jscoverage['plugins/table.action.js'][1753]++; + return; + } + _$jscoverage['plugins/table.action.js'][1754]++; + var line; + _$jscoverage['plugins/table.action.js'][1755]++; + while ((line = editor.document.getElementById("ue_tableDragLine"))) { + _$jscoverage['plugins/table.action.js'][1756]++; + domUtils.remove(line); +} +} + _$jscoverage['plugins/table.action.js'][1765]++; + function showDragLineAt(state, cell) { + _$jscoverage['plugins/table.action.js'][1766]++; + if ((! cell)) { + _$jscoverage['plugins/table.action.js'][1766]++; + return; + } + _$jscoverage['plugins/table.action.js'][1767]++; + var table = domUtils.findParentByTagName(cell, "table"), caption = table.getElementsByTagName("caption"), width = table.offsetWidth, height = (table.offsetHeight - ((caption.length > 0)? caption[0].offsetHeight: 0)), tablePos = domUtils.getXY(table), cellPos = domUtils.getXY(cell), css; + _$jscoverage['plugins/table.action.js'][1773]++; + switch (state) { + case "h": + _$jscoverage['plugins/table.action.js'][1775]++; + css = ("height:" + height + "px;top:" + (tablePos.y + ((caption.length > 0)? caption[0].offsetHeight: 0)) + "px;left:" + (cellPos.x + cell.offsetWidth)); + _$jscoverage['plugins/table.action.js'][1776]++; + dragLine.style.cssText = (css + "px;position: absolute;display:block;background-color:blue;width:1px;border:0; color:blue;opacity:.3;filter:alpha(opacity=30)"); + _$jscoverage['plugins/table.action.js'][1777]++; + break; + case "v": + _$jscoverage['plugins/table.action.js'][1779]++; + css = ("width:" + width + "px;left:" + tablePos.x + "px;top:" + (cellPos.y + cell.offsetHeight)); + _$jscoverage['plugins/table.action.js'][1781]++; + dragLine.style.cssText = (css + "px;overflow:hidden;position: absolute;display:block;background-color:blue;height:1px;border:0;color:blue;opacity:.2;filter:alpha(opacity=20)"); + _$jscoverage['plugins/table.action.js'][1782]++; + break; + default: + } +} + _$jscoverage['plugins/table.action.js'][1792]++; + function switchBorderColor(editor, flag) { + _$jscoverage['plugins/table.action.js'][1793]++; + var tableArr = domUtils.getElementsByTagName(editor.body, "table"), color; + _$jscoverage['plugins/table.action.js'][1794]++; + for (var i = 0, node; (node = tableArr[(i++)]);) { + _$jscoverage['plugins/table.action.js'][1795]++; + var td = domUtils.getElementsByTagName(node, "td"); + _$jscoverage['plugins/table.action.js'][1796]++; + if (td[0]) { + _$jscoverage['plugins/table.action.js'][1797]++; + if (flag) { + _$jscoverage['plugins/table.action.js'][1798]++; + color = td[0].style.borderColor.replace(/\s/g, ""); + _$jscoverage['plugins/table.action.js'][1799]++; + if (/(#ffffff)|(rgb\(255,f55,255\))/gi.test(color)) { + _$jscoverage['plugins/table.action.js'][1800]++; + domUtils.addClass(node, "noBorderTable"); + } + } + else { + _$jscoverage['plugins/table.action.js'][1802]++; + domUtils.removeClasses(node, "noBorderTable"); + } + } +} +} + _$jscoverage['plugins/table.action.js'][1809]++; + function getTableWidth(editor, needIEHack, defaultValue) { + _$jscoverage['plugins/table.action.js'][1810]++; + var body = editor.body; + _$jscoverage['plugins/table.action.js'][1811]++; + return (body.offsetWidth - (needIEHack? (parseInt(domUtils.getComputedStyle(body, "margin-left"), 10) * 2): 0) - (defaultValue.tableBorder * 2) - (editor.options.offsetWidth || 0)); +} + _$jscoverage['plugins/table.action.js'][1817]++; + function getTargetTd(editor, evt) { + _$jscoverage['plugins/table.action.js'][1819]++; + var target = domUtils.findParentByTagName((evt.target || evt.srcElement), ["td", "th"], true), dir = null; + _$jscoverage['plugins/table.action.js'][1822]++; + if ((! target)) { + _$jscoverage['plugins/table.action.js'][1823]++; + return null; + } + _$jscoverage['plugins/table.action.js'][1826]++; + dir = getRelation(target, mouseCoords(evt)); + _$jscoverage['plugins/table.action.js'][1830]++; + if ((! target)) { + _$jscoverage['plugins/table.action.js'][1831]++; + return null; + } + _$jscoverage['plugins/table.action.js'][1834]++; + if (((dir === "h1") && target.previousSibling)) { + _$jscoverage['plugins/table.action.js'][1836]++; + var position = domUtils.getXY(target), cellWidth = target.offsetWidth; + _$jscoverage['plugins/table.action.js'][1839]++; + if ((Math.abs(((position.x + cellWidth) - evt.clientX)) > (cellWidth / 3))) { + _$jscoverage['plugins/table.action.js'][1840]++; + target = target.previousSibling; + } + } + else { + _$jscoverage['plugins/table.action.js'][1843]++; + if (((dir === "v1") && target.parentNode.previousSibling)) { + _$jscoverage['plugins/table.action.js'][1845]++; + var position = domUtils.getXY(target), cellHeight = target.offsetHeight; + _$jscoverage['plugins/table.action.js'][1848]++; + if ((Math.abs(((position.y + cellHeight) - evt.clientY)) > (cellHeight / 3))) { + _$jscoverage['plugins/table.action.js'][1849]++; + target = target.parentNode.previousSibling.firstChild; + } + } + } + _$jscoverage['plugins/table.action.js'][1856]++; + return ((target && (! (editor.fireEvent("excludetable", target) === true)))? target: null); +} +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/table.cmds.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/table.cmds.js new file mode 100644 index 000000000..f90fa6651 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/table.cmds.js @@ -0,0 +1,1622 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/table.cmds.js']) { + _$jscoverage['plugins/table.cmds.js'] = []; + _$jscoverage['plugins/table.cmds.js'][8] = 0; + _$jscoverage['plugins/table.cmds.js'][9] = 0; + _$jscoverage['plugins/table.cmds.js'][10] = 0; + _$jscoverage['plugins/table.cmds.js'][12] = 0; + _$jscoverage['plugins/table.cmds.js'][15] = 0; + _$jscoverage['plugins/table.cmds.js'][18] = 0; + _$jscoverage['plugins/table.cmds.js'][21] = 0; + _$jscoverage['plugins/table.cmds.js'][25] = 0; + _$jscoverage['plugins/table.cmds.js'][27] = 0; + _$jscoverage['plugins/table.cmds.js'][30] = 0; + _$jscoverage['plugins/table.cmds.js'][31] = 0; + _$jscoverage['plugins/table.cmds.js'][34] = 0; + _$jscoverage['plugins/table.cmds.js'][35] = 0; + _$jscoverage['plugins/table.cmds.js'][36] = 0; + _$jscoverage['plugins/table.cmds.js'][37] = 0; + _$jscoverage['plugins/table.cmds.js'][39] = 0; + _$jscoverage['plugins/table.cmds.js'][42] = 0; + _$jscoverage['plugins/table.cmds.js'][45] = 0; + _$jscoverage['plugins/table.cmds.js'][46] = 0; + _$jscoverage['plugins/table.cmds.js'][52] = 0; + _$jscoverage['plugins/table.cmds.js'][53] = 0; + _$jscoverage['plugins/table.cmds.js'][56] = 0; + _$jscoverage['plugins/table.cmds.js'][59] = 0; + _$jscoverage['plugins/table.cmds.js'][64] = 0; + _$jscoverage['plugins/table.cmds.js'][65] = 0; + _$jscoverage['plugins/table.cmds.js'][69] = 0; + _$jscoverage['plugins/table.cmds.js'][71] = 0; + _$jscoverage['plugins/table.cmds.js'][74] = 0; + _$jscoverage['plugins/table.cmds.js'][75] = 0; + _$jscoverage['plugins/table.cmds.js'][76] = 0; + _$jscoverage['plugins/table.cmds.js'][77] = 0; + _$jscoverage['plugins/table.cmds.js'][78] = 0; + _$jscoverage['plugins/table.cmds.js'][79] = 0; + _$jscoverage['plugins/table.cmds.js'][84] = 0; + _$jscoverage['plugins/table.cmds.js'][86] = 0; + _$jscoverage['plugins/table.cmds.js'][87] = 0; + _$jscoverage['plugins/table.cmds.js'][90] = 0; + _$jscoverage['plugins/table.cmds.js'][91] = 0; + _$jscoverage['plugins/table.cmds.js'][92] = 0; + _$jscoverage['plugins/table.cmds.js'][93] = 0; + _$jscoverage['plugins/table.cmds.js'][94] = 0; + _$jscoverage['plugins/table.cmds.js'][95] = 0; + _$jscoverage['plugins/table.cmds.js'][98] = 0; + _$jscoverage['plugins/table.cmds.js'][100] = 0; + _$jscoverage['plugins/table.cmds.js'][101] = 0; + _$jscoverage['plugins/table.cmds.js'][102] = 0; + _$jscoverage['plugins/table.cmds.js'][103] = 0; + _$jscoverage['plugins/table.cmds.js'][105] = 0; + _$jscoverage['plugins/table.cmds.js'][107] = 0; + _$jscoverage['plugins/table.cmds.js'][108] = 0; + _$jscoverage['plugins/table.cmds.js'][114] = 0; + _$jscoverage['plugins/table.cmds.js'][116] = 0; + _$jscoverage['plugins/table.cmds.js'][119] = 0; + _$jscoverage['plugins/table.cmds.js'][120] = 0; + _$jscoverage['plugins/table.cmds.js'][121] = 0; + _$jscoverage['plugins/table.cmds.js'][122] = 0; + _$jscoverage['plugins/table.cmds.js'][127] = 0; + _$jscoverage['plugins/table.cmds.js'][129] = 0; + _$jscoverage['plugins/table.cmds.js'][132] = 0; + _$jscoverage['plugins/table.cmds.js'][133] = 0; + _$jscoverage['plugins/table.cmds.js'][134] = 0; + _$jscoverage['plugins/table.cmds.js'][135] = 0; + _$jscoverage['plugins/table.cmds.js'][140] = 0; + _$jscoverage['plugins/table.cmds.js'][142] = 0; + _$jscoverage['plugins/table.cmds.js'][143] = 0; + _$jscoverage['plugins/table.cmds.js'][144] = 0; + _$jscoverage['plugins/table.cmds.js'][146] = 0; + _$jscoverage['plugins/table.cmds.js'][149] = 0; + _$jscoverage['plugins/table.cmds.js'][150] = 0; + _$jscoverage['plugins/table.cmds.js'][151] = 0; + _$jscoverage['plugins/table.cmds.js'][152] = 0; + _$jscoverage['plugins/table.cmds.js'][153] = 0; + _$jscoverage['plugins/table.cmds.js'][154] = 0; + _$jscoverage['plugins/table.cmds.js'][155] = 0; + _$jscoverage['plugins/table.cmds.js'][160] = 0; + _$jscoverage['plugins/table.cmds.js'][162] = 0; + _$jscoverage['plugins/table.cmds.js'][164] = 0; + _$jscoverage['plugins/table.cmds.js'][165] = 0; + _$jscoverage['plugins/table.cmds.js'][167] = 0; + _$jscoverage['plugins/table.cmds.js'][170] = 0; + _$jscoverage['plugins/table.cmds.js'][172] = 0; + _$jscoverage['plugins/table.cmds.js'][173] = 0; + _$jscoverage['plugins/table.cmds.js'][174] = 0; + _$jscoverage['plugins/table.cmds.js'][175] = 0; + _$jscoverage['plugins/table.cmds.js'][180] = 0; + _$jscoverage['plugins/table.cmds.js'][182] = 0; + _$jscoverage['plugins/table.cmds.js'][183] = 0; + _$jscoverage['plugins/table.cmds.js'][184] = 0; + _$jscoverage['plugins/table.cmds.js'][185] = 0; + _$jscoverage['plugins/table.cmds.js'][187] = 0; + _$jscoverage['plugins/table.cmds.js'][190] = 0; + _$jscoverage['plugins/table.cmds.js'][191] = 0; + _$jscoverage['plugins/table.cmds.js'][192] = 0; + _$jscoverage['plugins/table.cmds.js'][194] = 0; + _$jscoverage['plugins/table.cmds.js'][195] = 0; + _$jscoverage['plugins/table.cmds.js'][198] = 0; + _$jscoverage['plugins/table.cmds.js'][200] = 0; + _$jscoverage['plugins/table.cmds.js'][201] = 0; + _$jscoverage['plugins/table.cmds.js'][202] = 0; + _$jscoverage['plugins/table.cmds.js'][203] = 0; + _$jscoverage['plugins/table.cmds.js'][205] = 0; + _$jscoverage['plugins/table.cmds.js'][208] = 0; + _$jscoverage['plugins/table.cmds.js'][209] = 0; + _$jscoverage['plugins/table.cmds.js'][210] = 0; + _$jscoverage['plugins/table.cmds.js'][212] = 0; + _$jscoverage['plugins/table.cmds.js'][213] = 0; + _$jscoverage['plugins/table.cmds.js'][217] = 0; + _$jscoverage['plugins/table.cmds.js'][219] = 0; + _$jscoverage['plugins/table.cmds.js'][220] = 0; + _$jscoverage['plugins/table.cmds.js'][221] = 0; + _$jscoverage['plugins/table.cmds.js'][222] = 0; + _$jscoverage['plugins/table.cmds.js'][223] = 0; + _$jscoverage['plugins/table.cmds.js'][225] = 0; + _$jscoverage['plugins/table.cmds.js'][226] = 0; + _$jscoverage['plugins/table.cmds.js'][227] = 0; + _$jscoverage['plugins/table.cmds.js'][231] = 0; + _$jscoverage['plugins/table.cmds.js'][233] = 0; + _$jscoverage['plugins/table.cmds.js'][235] = 0; + _$jscoverage['plugins/table.cmds.js'][236] = 0; + _$jscoverage['plugins/table.cmds.js'][239] = 0; + _$jscoverage['plugins/table.cmds.js'][241] = 0; + _$jscoverage['plugins/table.cmds.js'][243] = 0; + _$jscoverage['plugins/table.cmds.js'][244] = 0; + _$jscoverage['plugins/table.cmds.js'][245] = 0; + _$jscoverage['plugins/table.cmds.js'][246] = 0; + _$jscoverage['plugins/table.cmds.js'][249] = 0; + _$jscoverage['plugins/table.cmds.js'][250] = 0; + _$jscoverage['plugins/table.cmds.js'][252] = 0; + _$jscoverage['plugins/table.cmds.js'][256] = 0; + _$jscoverage['plugins/table.cmds.js'][258] = 0; + _$jscoverage['plugins/table.cmds.js'][260] = 0; + _$jscoverage['plugins/table.cmds.js'][261] = 0; + _$jscoverage['plugins/table.cmds.js'][264] = 0; + _$jscoverage['plugins/table.cmds.js'][266] = 0; + _$jscoverage['plugins/table.cmds.js'][269] = 0; + _$jscoverage['plugins/table.cmds.js'][270] = 0; + _$jscoverage['plugins/table.cmds.js'][271] = 0; + _$jscoverage['plugins/table.cmds.js'][272] = 0; + _$jscoverage['plugins/table.cmds.js'][273] = 0; + _$jscoverage['plugins/table.cmds.js'][274] = 0; + _$jscoverage['plugins/table.cmds.js'][275] = 0; + _$jscoverage['plugins/table.cmds.js'][277] = 0; + _$jscoverage['plugins/table.cmds.js'][279] = 0; + _$jscoverage['plugins/table.cmds.js'][285] = 0; + _$jscoverage['plugins/table.cmds.js'][287] = 0; + _$jscoverage['plugins/table.cmds.js'][289] = 0; + _$jscoverage['plugins/table.cmds.js'][292] = 0; + _$jscoverage['plugins/table.cmds.js'][294] = 0; + _$jscoverage['plugins/table.cmds.js'][300] = 0; + _$jscoverage['plugins/table.cmds.js'][301] = 0; + _$jscoverage['plugins/table.cmds.js'][303] = 0; + _$jscoverage['plugins/table.cmds.js'][304] = 0; + _$jscoverage['plugins/table.cmds.js'][305] = 0; + _$jscoverage['plugins/table.cmds.js'][308] = 0; + _$jscoverage['plugins/table.cmds.js'][309] = 0; + _$jscoverage['plugins/table.cmds.js'][313] = 0; + _$jscoverage['plugins/table.cmds.js'][315] = 0; + _$jscoverage['plugins/table.cmds.js'][317] = 0; + _$jscoverage['plugins/table.cmds.js'][320] = 0; + _$jscoverage['plugins/table.cmds.js'][322] = 0; + _$jscoverage['plugins/table.cmds.js'][328] = 0; + _$jscoverage['plugins/table.cmds.js'][329] = 0; + _$jscoverage['plugins/table.cmds.js'][331] = 0; + _$jscoverage['plugins/table.cmds.js'][332] = 0; + _$jscoverage['plugins/table.cmds.js'][333] = 0; + _$jscoverage['plugins/table.cmds.js'][336] = 0; + _$jscoverage['plugins/table.cmds.js'][337] = 0; + _$jscoverage['plugins/table.cmds.js'][340] = 0; + _$jscoverage['plugins/table.cmds.js'][342] = 0; + _$jscoverage['plugins/table.cmds.js'][343] = 0; + _$jscoverage['plugins/table.cmds.js'][344] = 0; + _$jscoverage['plugins/table.cmds.js'][348] = 0; + _$jscoverage['plugins/table.cmds.js'][355] = 0; + _$jscoverage['plugins/table.cmds.js'][356] = 0; + _$jscoverage['plugins/table.cmds.js'][358] = 0; + _$jscoverage['plugins/table.cmds.js'][359] = 0; + _$jscoverage['plugins/table.cmds.js'][362] = 0; + _$jscoverage['plugins/table.cmds.js'][363] = 0; + _$jscoverage['plugins/table.cmds.js'][364] = 0; + _$jscoverage['plugins/table.cmds.js'][365] = 0; + _$jscoverage['plugins/table.cmds.js'][366] = 0; + _$jscoverage['plugins/table.cmds.js'][367] = 0; + _$jscoverage['plugins/table.cmds.js'][370] = 0; + _$jscoverage['plugins/table.cmds.js'][371] = 0; + _$jscoverage['plugins/table.cmds.js'][373] = 0; + _$jscoverage['plugins/table.cmds.js'][374] = 0; + _$jscoverage['plugins/table.cmds.js'][377] = 0; + _$jscoverage['plugins/table.cmds.js'][380] = 0; + _$jscoverage['plugins/table.cmds.js'][382] = 0; + _$jscoverage['plugins/table.cmds.js'][384] = 0; + _$jscoverage['plugins/table.cmds.js'][387] = 0; + _$jscoverage['plugins/table.cmds.js'][389] = 0; + _$jscoverage['plugins/table.cmds.js'][390] = 0; + _$jscoverage['plugins/table.cmds.js'][395] = 0; + _$jscoverage['plugins/table.cmds.js'][396] = 0; + _$jscoverage['plugins/table.cmds.js'][398] = 0; + _$jscoverage['plugins/table.cmds.js'][399] = 0; + _$jscoverage['plugins/table.cmds.js'][400] = 0; + _$jscoverage['plugins/table.cmds.js'][403] = 0; + _$jscoverage['plugins/table.cmds.js'][406] = 0; + _$jscoverage['plugins/table.cmds.js'][408] = 0; + _$jscoverage['plugins/table.cmds.js'][410] = 0; + _$jscoverage['plugins/table.cmds.js'][413] = 0; + _$jscoverage['plugins/table.cmds.js'][415] = 0; + _$jscoverage['plugins/table.cmds.js'][419] = 0; + _$jscoverage['plugins/table.cmds.js'][420] = 0; + _$jscoverage['plugins/table.cmds.js'][422] = 0; + _$jscoverage['plugins/table.cmds.js'][423] = 0; + _$jscoverage['plugins/table.cmds.js'][424] = 0; + _$jscoverage['plugins/table.cmds.js'][427] = 0; + _$jscoverage['plugins/table.cmds.js'][431] = 0; + _$jscoverage['plugins/table.cmds.js'][433] = 0; + _$jscoverage['plugins/table.cmds.js'][434] = 0; + _$jscoverage['plugins/table.cmds.js'][437] = 0; + _$jscoverage['plugins/table.cmds.js'][443] = 0; + _$jscoverage['plugins/table.cmds.js'][444] = 0; + _$jscoverage['plugins/table.cmds.js'][446] = 0; + _$jscoverage['plugins/table.cmds.js'][447] = 0; + _$jscoverage['plugins/table.cmds.js'][450] = 0; + _$jscoverage['plugins/table.cmds.js'][453] = 0; + _$jscoverage['plugins/table.cmds.js'][454] = 0; + _$jscoverage['plugins/table.cmds.js'][455] = 0; + _$jscoverage['plugins/table.cmds.js'][456] = 0; + _$jscoverage['plugins/table.cmds.js'][457] = 0; + _$jscoverage['plugins/table.cmds.js'][460] = 0; + _$jscoverage['plugins/table.cmds.js'][461] = 0; + _$jscoverage['plugins/table.cmds.js'][463] = 0; + _$jscoverage['plugins/table.cmds.js'][464] = 0; + _$jscoverage['plugins/table.cmds.js'][466] = 0; + _$jscoverage['plugins/table.cmds.js'][467] = 0; + _$jscoverage['plugins/table.cmds.js'][474] = 0; + _$jscoverage['plugins/table.cmds.js'][476] = 0; + _$jscoverage['plugins/table.cmds.js'][478] = 0; + _$jscoverage['plugins/table.cmds.js'][479] = 0; + _$jscoverage['plugins/table.cmds.js'][480] = 0; + _$jscoverage['plugins/table.cmds.js'][481] = 0; + _$jscoverage['plugins/table.cmds.js'][484] = 0; + _$jscoverage['plugins/table.cmds.js'][486] = 0; + _$jscoverage['plugins/table.cmds.js'][488] = 0; + _$jscoverage['plugins/table.cmds.js'][489] = 0; + _$jscoverage['plugins/table.cmds.js'][492] = 0; + _$jscoverage['plugins/table.cmds.js'][494] = 0; + _$jscoverage['plugins/table.cmds.js'][496] = 0; + _$jscoverage['plugins/table.cmds.js'][497] = 0; + _$jscoverage['plugins/table.cmds.js'][498] = 0; + _$jscoverage['plugins/table.cmds.js'][499] = 0; + _$jscoverage['plugins/table.cmds.js'][502] = 0; + _$jscoverage['plugins/table.cmds.js'][504] = 0; + _$jscoverage['plugins/table.cmds.js'][506] = 0; + _$jscoverage['plugins/table.cmds.js'][507] = 0; + _$jscoverage['plugins/table.cmds.js'][510] = 0; + _$jscoverage['plugins/table.cmds.js'][512] = 0; + _$jscoverage['plugins/table.cmds.js'][514] = 0; + _$jscoverage['plugins/table.cmds.js'][515] = 0; + _$jscoverage['plugins/table.cmds.js'][516] = 0; + _$jscoverage['plugins/table.cmds.js'][517] = 0; + _$jscoverage['plugins/table.cmds.js'][520] = 0; + _$jscoverage['plugins/table.cmds.js'][522] = 0; + _$jscoverage['plugins/table.cmds.js'][524] = 0; + _$jscoverage['plugins/table.cmds.js'][525] = 0; + _$jscoverage['plugins/table.cmds.js'][530] = 0; + _$jscoverage['plugins/table.cmds.js'][533] = 0; + _$jscoverage['plugins/table.cmds.js'][536] = 0; + _$jscoverage['plugins/table.cmds.js'][538] = 0; + _$jscoverage['plugins/table.cmds.js'][539] = 0; + _$jscoverage['plugins/table.cmds.js'][540] = 0; + _$jscoverage['plugins/table.cmds.js'][542] = 0; + _$jscoverage['plugins/table.cmds.js'][543] = 0; + _$jscoverage['plugins/table.cmds.js'][544] = 0; + _$jscoverage['plugins/table.cmds.js'][546] = 0; + _$jscoverage['plugins/table.cmds.js'][553] = 0; + _$jscoverage['plugins/table.cmds.js'][555] = 0; + _$jscoverage['plugins/table.cmds.js'][556] = 0; + _$jscoverage['plugins/table.cmds.js'][557] = 0; + _$jscoverage['plugins/table.cmds.js'][560] = 0; + _$jscoverage['plugins/table.cmds.js'][563] = 0; + _$jscoverage['plugins/table.cmds.js'][564] = 0; + _$jscoverage['plugins/table.cmds.js'][568] = 0; + _$jscoverage['plugins/table.cmds.js'][569] = 0; + _$jscoverage['plugins/table.cmds.js'][570] = 0; + _$jscoverage['plugins/table.cmds.js'][572] = 0; + _$jscoverage['plugins/table.cmds.js'][575] = 0; + _$jscoverage['plugins/table.cmds.js'][576] = 0; + _$jscoverage['plugins/table.cmds.js'][577] = 0; + _$jscoverage['plugins/table.cmds.js'][578] = 0; + _$jscoverage['plugins/table.cmds.js'][579] = 0; + _$jscoverage['plugins/table.cmds.js'][582] = 0; + _$jscoverage['plugins/table.cmds.js'][583] = 0; + _$jscoverage['plugins/table.cmds.js'][586] = 0; + _$jscoverage['plugins/table.cmds.js'][587] = 0; + _$jscoverage['plugins/table.cmds.js'][588] = 0; + _$jscoverage['plugins/table.cmds.js'][590] = 0; + _$jscoverage['plugins/table.cmds.js'][592] = 0; + _$jscoverage['plugins/table.cmds.js'][593] = 0; + _$jscoverage['plugins/table.cmds.js'][594] = 0; + _$jscoverage['plugins/table.cmds.js'][599] = 0; + _$jscoverage['plugins/table.cmds.js'][600] = 0; + _$jscoverage['plugins/table.cmds.js'][605] = 0; + _$jscoverage['plugins/table.cmds.js'][607] = 0; + _$jscoverage['plugins/table.cmds.js'][608] = 0; + _$jscoverage['plugins/table.cmds.js'][609] = 0; + _$jscoverage['plugins/table.cmds.js'][610] = 0; + _$jscoverage['plugins/table.cmds.js'][613] = 0; + _$jscoverage['plugins/table.cmds.js'][616] = 0; + _$jscoverage['plugins/table.cmds.js'][617] = 0; + _$jscoverage['plugins/table.cmds.js'][622] = 0; + _$jscoverage['plugins/table.cmds.js'][623] = 0; + _$jscoverage['plugins/table.cmds.js'][627] = 0; + _$jscoverage['plugins/table.cmds.js'][628] = 0; + _$jscoverage['plugins/table.cmds.js'][630] = 0; + _$jscoverage['plugins/table.cmds.js'][631] = 0; + _$jscoverage['plugins/table.cmds.js'][634] = 0; + _$jscoverage['plugins/table.cmds.js'][635] = 0; + _$jscoverage['plugins/table.cmds.js'][637] = 0; + _$jscoverage['plugins/table.cmds.js'][641] = 0; + _$jscoverage['plugins/table.cmds.js'][642] = 0; + _$jscoverage['plugins/table.cmds.js'][643] = 0; + _$jscoverage['plugins/table.cmds.js'][645] = 0; + _$jscoverage['plugins/table.cmds.js'][648] = 0; + _$jscoverage['plugins/table.cmds.js'][649] = 0; + _$jscoverage['plugins/table.cmds.js'][651] = 0; + _$jscoverage['plugins/table.cmds.js'][653] = 0; + _$jscoverage['plugins/table.cmds.js'][656] = 0; + _$jscoverage['plugins/table.cmds.js'][657] = 0; + _$jscoverage['plugins/table.cmds.js'][658] = 0; + _$jscoverage['plugins/table.cmds.js'][659] = 0; + _$jscoverage['plugins/table.cmds.js'][660] = 0; + _$jscoverage['plugins/table.cmds.js'][665] = 0; + _$jscoverage['plugins/table.cmds.js'][666] = 0; + _$jscoverage['plugins/table.cmds.js'][672] = 0; + _$jscoverage['plugins/table.cmds.js'][674] = 0; + _$jscoverage['plugins/table.cmds.js'][677] = 0; + _$jscoverage['plugins/table.cmds.js'][680] = 0; + _$jscoverage['plugins/table.cmds.js'][681] = 0; + _$jscoverage['plugins/table.cmds.js'][683] = 0; + _$jscoverage['plugins/table.cmds.js'][684] = 0; + _$jscoverage['plugins/table.cmds.js'][686] = 0; + _$jscoverage['plugins/table.cmds.js'][687] = 0; + _$jscoverage['plugins/table.cmds.js'][689] = 0; + _$jscoverage['plugins/table.cmds.js'][691] = 0; + _$jscoverage['plugins/table.cmds.js'][692] = 0; + _$jscoverage['plugins/table.cmds.js'][702] = 0; + _$jscoverage['plugins/table.cmds.js'][704] = 0; + _$jscoverage['plugins/table.cmds.js'][705] = 0; + _$jscoverage['plugins/table.cmds.js'][708] = 0; + _$jscoverage['plugins/table.cmds.js'][710] = 0; + _$jscoverage['plugins/table.cmds.js'][715] = 0; + _$jscoverage['plugins/table.cmds.js'][717] = 0; + _$jscoverage['plugins/table.cmds.js'][719] = 0; + _$jscoverage['plugins/table.cmds.js'][726] = 0; + _$jscoverage['plugins/table.cmds.js'][728] = 0; + _$jscoverage['plugins/table.cmds.js'][729] = 0; + _$jscoverage['plugins/table.cmds.js'][731] = 0; + _$jscoverage['plugins/table.cmds.js'][734] = 0; + _$jscoverage['plugins/table.cmds.js'][738] = 0; + _$jscoverage['plugins/table.cmds.js'][739] = 0; + _$jscoverage['plugins/table.cmds.js'][745] = 0; + _$jscoverage['plugins/table.cmds.js'][747] = 0; + _$jscoverage['plugins/table.cmds.js'][750] = 0; + _$jscoverage['plugins/table.cmds.js'][752] = 0; + _$jscoverage['plugins/table.cmds.js'][753] = 0; + _$jscoverage['plugins/table.cmds.js'][757] = 0; + _$jscoverage['plugins/table.cmds.js'][758] = 0; + _$jscoverage['plugins/table.cmds.js'][764] = 0; + _$jscoverage['plugins/table.cmds.js'][766] = 0; + _$jscoverage['plugins/table.cmds.js'][769] = 0; + _$jscoverage['plugins/table.cmds.js'][772] = 0; + _$jscoverage['plugins/table.cmds.js'][773] = 0; + _$jscoverage['plugins/table.cmds.js'][775] = 0; + _$jscoverage['plugins/table.cmds.js'][776] = 0; + _$jscoverage['plugins/table.cmds.js'][779] = 0; + _$jscoverage['plugins/table.cmds.js'][780] = 0; + _$jscoverage['plugins/table.cmds.js'][785] = 0; + _$jscoverage['plugins/table.cmds.js'][787] = 0; + _$jscoverage['plugins/table.cmds.js'][789] = 0; + _$jscoverage['plugins/table.cmds.js'][790] = 0; + _$jscoverage['plugins/table.cmds.js'][792] = 0; + _$jscoverage['plugins/table.cmds.js'][793] = 0; + _$jscoverage['plugins/table.cmds.js'][795] = 0; + _$jscoverage['plugins/table.cmds.js'][798] = 0; + _$jscoverage['plugins/table.cmds.js'][805] = 0; + _$jscoverage['plugins/table.cmds.js'][806] = 0; + _$jscoverage['plugins/table.cmds.js'][810] = 0; + _$jscoverage['plugins/table.cmds.js'][812] = 0; + _$jscoverage['plugins/table.cmds.js'][815] = 0; + _$jscoverage['plugins/table.cmds.js'][816] = 0; + _$jscoverage['plugins/table.cmds.js'][819] = 0; + _$jscoverage['plugins/table.cmds.js'][821] = 0; + _$jscoverage['plugins/table.cmds.js'][824] = 0; + _$jscoverage['plugins/table.cmds.js'][825] = 0; + _$jscoverage['plugins/table.cmds.js'][826] = 0; + _$jscoverage['plugins/table.cmds.js'][827] = 0; + _$jscoverage['plugins/table.cmds.js'][831] = 0; + _$jscoverage['plugins/table.cmds.js'][833] = 0; + _$jscoverage['plugins/table.cmds.js'][834] = 0; + _$jscoverage['plugins/table.cmds.js'][835] = 0; + _$jscoverage['plugins/table.cmds.js'][836] = 0; + _$jscoverage['plugins/table.cmds.js'][838] = 0; + _$jscoverage['plugins/table.cmds.js'][841] = 0; + _$jscoverage['plugins/table.cmds.js'][843] = 0; + _$jscoverage['plugins/table.cmds.js'][847] = 0; + _$jscoverage['plugins/table.cmds.js'][849] = 0; + _$jscoverage['plugins/table.cmds.js'][850] = 0; + _$jscoverage['plugins/table.cmds.js'][851] = 0; + _$jscoverage['plugins/table.cmds.js'][852] = 0; + _$jscoverage['plugins/table.cmds.js'][855] = 0; + _$jscoverage['plugins/table.cmds.js'][857] = 0; + _$jscoverage['plugins/table.cmds.js'][861] = 0; + _$jscoverage['plugins/table.cmds.js'][862] = 0; + _$jscoverage['plugins/table.cmds.js'][863] = 0; + _$jscoverage['plugins/table.cmds.js'][864] = 0; + _$jscoverage['plugins/table.cmds.js'][866] = 0; + _$jscoverage['plugins/table.cmds.js'][867] = 0; + _$jscoverage['plugins/table.cmds.js'][872] = 0; + _$jscoverage['plugins/table.cmds.js'][873] = 0; + _$jscoverage['plugins/table.cmds.js'][874] = 0; + _$jscoverage['plugins/table.cmds.js'][875] = 0; + _$jscoverage['plugins/table.cmds.js'][877] = 0; + _$jscoverage['plugins/table.cmds.js'][878] = 0; + _$jscoverage['plugins/table.cmds.js'][879] = 0; + _$jscoverage['plugins/table.cmds.js'][880] = 0; + _$jscoverage['plugins/table.cmds.js'][885] = 0; + _$jscoverage['plugins/table.cmds.js'][886] = 0; + _$jscoverage['plugins/table.cmds.js'][887] = 0; + _$jscoverage['plugins/table.cmds.js'][890] = 0; + _$jscoverage['plugins/table.cmds.js'][891] = 0; + _$jscoverage['plugins/table.cmds.js'][892] = 0; + _$jscoverage['plugins/table.cmds.js'][893] = 0; + _$jscoverage['plugins/table.cmds.js'][894] = 0; + _$jscoverage['plugins/table.cmds.js'][896] = 0; +} +_$jscoverage['plugins/table.cmds.js'].source = ["/*"," * Created with JetBrains PhpStorm."," * User: taoqili"," * Date: 13-2-20"," * Time: 下午6:25"," * To change this template use File | Settings | File Templates."," */",";","(function () {"," var UT = UE.UETable,"," getTableItemsByRange = function (editor) {"," return UT.getTableItemsByRange(editor);"," },"," getUETableBySelected = function (editor) {"," return UT.getUETableBySelected(editor)"," },"," getDefaultValue = function (editor, table) {"," return UT.getDefaultValue(editor, table);"," },"," getUETable = function (tdOrTable) {"," return UT.getUETable(tdOrTable);"," };","",""," UE.commands['inserttable'] = {"," queryCommandState: function () {"," return getTableItemsByRange(this).table ? -1 : 0;"," },"," execCommand: function (cmd, opt) {"," function createTable(opt, tdWidth) {"," var html = [],"," rowsNum = opt.numRows,"," colsNum = opt.numCols;"," for (var r = 0; r < rowsNum; r++) {"," html.push('<tr>');"," for (var c = 0; c < colsNum; c++) {"," html.push('<td width=\"' + tdWidth + '\" vAlign=\"' + opt.tdvalign + '\" >' + (browser.ie ? domUtils.fillChar : '<br/>') + '</td>')"," }"," html.push('</tr>')"," }"," //禁止指定table-width"," return '<table><tbody>' + html.join('') + '</tbody></table>'"," }",""," if (!opt) {"," opt = utils.extend({}, {"," numCols: this.options.defaultCols,"," numRows: this.options.defaultRows,"," tdvalign: this.options.tdvalign"," })"," }"," var me = this;"," var range = this.selection.getRange(),"," start = range.startContainer,"," firstParentBlock = domUtils.findParent(start, function (node) {"," return domUtils.isBlockElm(node);"," }, true) || me.body;",""," var defaultValue = getDefaultValue(me),"," tableWidth = firstParentBlock.offsetWidth,"," tdWidth = Math.floor(tableWidth / opt.numCols - defaultValue.tdPadding * 2 - defaultValue.tdBorder);",""," //todo其他属性"," !opt.tdvalign && (opt.tdvalign = me.options.tdvalign);"," me.execCommand(\"inserthtml\", createTable(opt, tdWidth));"," }"," };",""," UE.commands['insertparagraphbeforetable'] = {"," queryCommandState: function () {"," return getTableItemsByRange(this).cell ? 0 : -1;"," },"," execCommand: function () {"," var table = getTableItemsByRange(this).table;"," if (table) {"," var p = this.document.createElement(\"p\");"," p.innerHTML = browser.ie ? '&nbsp;' : '<br />';"," table.parentNode.insertBefore(p, table);"," this.selection.getRange().setStart(p, 0).setCursor();"," }"," }"," };",""," UE.commands['deletetable'] = {"," queryCommandState: function () {"," var rng = this.selection.getRange();"," return domUtils.findParentByTagName(rng.startContainer, 'table', true) ? 0 : -1;"," },"," execCommand: function (cmd, table) {"," var rng = this.selection.getRange();"," table = table || domUtils.findParentByTagName(rng.startContainer, 'table', true);"," if (table) {"," var next = table.nextSibling;"," if (!next) {"," next = domUtils.createElement(this.document, 'p', {"," 'innerHTML': browser.ie ? domUtils.fillChar : '<br/>'"," });"," table.parentNode.insertBefore(next, table);"," }"," domUtils.remove(table);"," rng = this.selection.getRange();"," if (next.nodeType == 3) {"," rng.setStartBefore(next)"," } else {"," rng.setStart(next, 0)"," }"," rng.setCursor(false, true)"," this.fireEvent(\"tablehasdeleted\")",""," }",""," }"," };"," UE.commands['cellalign'] = {"," queryCommandState: function () {"," return getSelectedArr(this).length ? 0 : -1"," },"," execCommand: function (cmd, align) {"," var selectedTds = getSelectedArr(this);"," if (selectedTds.length) {"," for (var i = 0, ci; ci = selectedTds[i++];) {"," ci.setAttribute('align', align);"," }"," }"," }"," };"," UE.commands['cellvalign'] = {"," queryCommandState: function () {"," return getSelectedArr(this).length ? 0 : -1;"," },"," execCommand: function (cmd, valign) {"," var selectedTds = getSelectedArr(this);"," if (selectedTds.length) {"," for (var i = 0, ci; ci = selectedTds[i++];) {"," ci.setAttribute('vAlign', valign);"," }"," }"," }"," };"," UE.commands['insertcaption'] = {"," queryCommandState: function () {"," var table = getTableItemsByRange(this).table;"," if (table) {"," return table.getElementsByTagName('caption').length == 0 ? 1 : -1;"," }"," return -1;"," },"," execCommand: function () {"," var table = getTableItemsByRange(this).table;"," if (table) {"," var caption = this.document.createElement('caption');"," caption.innerHTML = browser.ie ? domUtils.fillChar : '<br/>';"," table.insertBefore(caption, table.firstChild);"," var range = this.selection.getRange();"," range.setStart(caption, 0).setCursor();"," }",""," }"," };"," UE.commands['deletecaption'] = {"," queryCommandState: function () {"," var rng = this.selection.getRange(),"," table = domUtils.findParentByTagName(rng.startContainer, 'table');"," if (table) {"," return table.getElementsByTagName('caption').length == 0 ? -1 : 1;"," }"," return -1;"," },"," execCommand: function () {"," var rng = this.selection.getRange(),"," table = domUtils.findParentByTagName(rng.startContainer, 'table');"," if (table) {"," domUtils.remove(table.getElementsByTagName('caption')[0]);"," var range = this.selection.getRange();"," range.setStart(table.rows[0].cells[0], 0).setCursor();"," }",""," }"," };"," UE.commands['inserttitle'] = {"," queryCommandState: function () {"," var table = getTableItemsByRange(this).table;"," if (table) {"," var firstRow = table.rows[0];"," return firstRow.getElementsByTagName('th').length == 0 ? 0 : -1"," }"," return -1;"," },"," execCommand: function () {"," var table = getTableItemsByRange(this).table;"," if (table) {"," getUETable(table).insertRow(0, 'th');"," }"," var th = table.getElementsByTagName('th')[0];"," this.selection.getRange().setStart(th, 0).setCursor(false, true);"," }"," };"," UE.commands['deletetitle'] = {"," queryCommandState: function () {"," var table = getTableItemsByRange(this).table;"," if (table) {"," var firstRow = table.rows[0];"," return firstRow.getElementsByTagName('th').length ? 0 : -1"," }"," return -1;"," },"," execCommand: function () {"," var table = getTableItemsByRange(this).table;"," if (table) {"," domUtils.remove(table.rows[0])"," }"," var td = table.getElementsByTagName('td')[0];"," this.selection.getRange().setStart(td, 0).setCursor(false, true);"," }"," };",""," UE.commands[\"mergeright\"] = {"," queryCommandState: function (cmd) {"," var tableItems = getTableItemsByRange(this);"," if (!tableItems.cell) return -1;"," var ut = getUETable(tableItems.table);"," if (ut.selectedTds.length) return -1;"," var cellInfo = ut.getCellInfo(tableItems.cell),"," rightColIndex = cellInfo.colIndex + cellInfo.colSpan;"," if (rightColIndex >= ut.colsNum) return -1;"," var rightCellInfo = ut.indexTable[cellInfo.rowIndex][rightColIndex];"," return (rightCellInfo.rowIndex == cellInfo.rowIndex"," && rightCellInfo.rowSpan == cellInfo.rowSpan) ? 0 : -1;"," },"," execCommand: function (cmd) {"," var rng = this.selection.getRange(),"," bk = rng.createBookmark(true);"," var cell = getTableItemsByRange(this).cell,"," ut = getUETable(cell);"," ut.mergeRight(cell);"," rng.moveToBookmark(bk).select();"," }"," };"," UE.commands[\"mergedown\"] = {"," queryCommandState: function (cmd) {"," var tableItems = getTableItemsByRange(this),"," cell = tableItems.cell;"," if (!cell || cell.tagName == \"TH\") return -1;"," var ut = getUETable(tableItems.table);"," if (ut.selectedTds.length)return -1;"," var cellInfo = ut.getCellInfo(tableItems.cell),"," downRowIndex = cellInfo.rowIndex + cellInfo.rowSpan;"," // 如果处于最下边则不能f向右合并"," if (downRowIndex >= ut.rowsNum) return -1;"," var downCellInfo = ut.indexTable[downRowIndex][cellInfo.colIndex];"," // 当且仅当两个Cell的开始列号和结束列号一致时能进行合并"," return (downCellInfo.colIndex == cellInfo.colIndex"," && downCellInfo.colSpan == cellInfo.colSpan) && tableItems.cell.tagName !== 'TH' ? 0 : -1;"," },"," execCommand: function () {"," var rng = this.selection.getRange(),"," bk = rng.createBookmark(true);"," var cell = getTableItemsByRange(this).cell,"," ut = getUETable(cell);"," ut.mergeDown(cell);"," rng.moveToBookmark(bk).select();"," }"," };"," UE.commands[\"mergecells\"] = {"," queryCommandState: function () {"," return getUETableBySelected(this) ? 0 : -1;"," },"," execCommand: function () {"," var ut = getUETableBySelected(this);"," if (ut && ut.selectedTds.length) {"," var cell = ut.selectedTds[0];"," ut.mergeRange();"," var rng = this.selection.getRange();"," if (domUtils.isEmptyBlock(cell)) {"," rng.setStart(cell, 0).collapse(true)"," } else {"," rng.selectNodeContents(cell)"," }"," rng.select();"," }","",""," }"," };"," UE.commands[\"insertrow\"] = {"," queryCommandState: function () {"," var tableItems = getTableItemsByRange(this),"," cell = tableItems.cell;"," return cell && cell.tagName == \"TD\" && getUETable(tableItems.table).rowsNum < this.options.maxRowNum ? 0 : -1;"," },"," execCommand: function () {"," var rng = this.selection.getRange(),"," bk = rng.createBookmark(true);"," var tableItems = getTableItemsByRange(this),"," cell = tableItems.cell,"," table = tableItems.table,"," ut = getUETable(table),"," cellInfo = ut.getCellInfo(cell);"," //ut.insertRow(!ut.selectedTds.length ? cellInfo.rowIndex:ut.cellsRange.beginRowIndex,'');"," if (!ut.selectedTds.length) {"," ut.insertRow(cellInfo.rowIndex, cell);"," } else {"," var range = ut.cellsRange;"," for (var i = 0, len = range.endRowIndex - range.beginRowIndex + 1; i < len; i++) {"," ut.insertRow(range.beginRowIndex, cell);"," }"," }"," rng.moveToBookmark(bk).select();"," if (table.getAttribute(\"interlaced\") === \"enabled\")this.fireEvent(\"interlacetable\", table);"," }"," };"," //后插入行"," UE.commands[\"insertrownext\"] = {"," queryCommandState: function () {"," var tableItems = getTableItemsByRange(this),"," cell = tableItems.cell;"," return cell && (cell.tagName == \"TD\") && getUETable(tableItems.table).rowsNum < this.options.maxRowNum ? 0 : -1;"," },"," execCommand: function () {"," var rng = this.selection.getRange(),"," bk = rng.createBookmark(true);"," var tableItems = getTableItemsByRange(this),"," cell = tableItems.cell,"," table = tableItems.table,"," ut = getUETable(table),"," cellInfo = ut.getCellInfo(cell);"," //ut.insertRow(!ut.selectedTds.length? cellInfo.rowIndex + cellInfo.rowSpan : ut.cellsRange.endRowIndex + 1,'');"," if (!ut.selectedTds.length) {"," ut.insertRow(cellInfo.rowIndex + cellInfo.rowSpan, cell);"," } else {"," var range = ut.cellsRange;"," for (var i = 0, len = range.endRowIndex - range.beginRowIndex + 1; i < len; i++) {"," ut.insertRow(range.endRowIndex + 1, cell);"," }"," }"," rng.moveToBookmark(bk).select();"," if (table.getAttribute(\"interlaced\") === \"enabled\")this.fireEvent(\"interlacetable\", table);"," }"," };"," UE.commands[\"deleterow\"] = {"," queryCommandState: function () {"," var tableItems = getTableItemsByRange(this);"," if (!tableItems.cell) {"," return -1;"," }"," },"," execCommand: function () {"," var cell = getTableItemsByRange(this).cell,"," ut = getUETable(cell),"," cellsRange = ut.cellsRange,"," cellInfo = ut.getCellInfo(cell),"," preCell = ut.getVSideCell(cell),"," nextCell = ut.getVSideCell(cell, true),"," rng = this.selection.getRange();"," if (utils.isEmptyObject(cellsRange)) {"," ut.deleteRow(cellInfo.rowIndex);"," } else {"," for (var i = cellsRange.beginRowIndex; i < cellsRange.endRowIndex + 1; i++) {"," ut.deleteRow(cellsRange.beginRowIndex);"," }"," }"," var table = ut.table;"," if (!table.getElementsByTagName('td').length) {"," var nextSibling = table.nextSibling;"," domUtils.remove(table);"," if (nextSibling) {"," rng.setStart(nextSibling, 0).setCursor(false, true);"," }"," } else {"," if (cellInfo.rowSpan == 1 || cellInfo.rowSpan == cellsRange.endRowIndex - cellsRange.beginRowIndex + 1) {"," if (nextCell || preCell) rng.selectNodeContents(nextCell || preCell).setCursor(false, true);"," } else {"," var newCell = ut.getCell(cellInfo.rowIndex, ut.indexTable[cellInfo.rowIndex][cellInfo.colIndex].cellIndex);"," if (newCell) rng.selectNodeContents(newCell).setCursor(false, true);"," }"," }"," if (table.getAttribute(\"interlaced\") === \"enabled\")this.fireEvent(\"interlacetable\", table);"," }"," };"," UE.commands[\"insertcol\"] = {"," queryCommandState: function (cmd) {"," var tableItems = getTableItemsByRange(this),"," cell = tableItems.cell;"," return cell && (cell.tagName == \"TD\" || cell.tagName == 'TH') && getUETable(tableItems.table).colsNum < this.options.maxColNum ? 0 : -1;"," },"," execCommand: function (cmd) {"," var rng = this.selection.getRange(),"," bk = rng.createBookmark(true);"," if (this.queryCommandState(cmd) == -1)return;"," var cell = getTableItemsByRange(this).cell,"," ut = getUETable(cell),"," cellInfo = ut.getCellInfo(cell);",""," //ut.insertCol(!ut.selectedTds.length ? cellInfo.colIndex:ut.cellsRange.beginColIndex);"," if (!ut.selectedTds.length) {"," ut.insertCol(cellInfo.colIndex, cell);"," } else {"," var range = ut.cellsRange;"," for (var i = 0, len = range.endColIndex - range.beginColIndex + 1; i < len; i++) {"," ut.insertCol(range.beginColIndex, cell);"," }"," }"," rng.moveToBookmark(bk).select(true);"," }"," };"," UE.commands[\"insertcolnext\"] = {"," queryCommandState: function () {"," var tableItems = getTableItemsByRange(this),"," cell = tableItems.cell;"," return cell && getUETable(tableItems.table).colsNum < this.options.maxColNum ? 0 : -1;"," },"," execCommand: function () {"," var rng = this.selection.getRange(),"," bk = rng.createBookmark(true);"," var cell = getTableItemsByRange(this).cell,"," ut = getUETable(cell),"," cellInfo = ut.getCellInfo(cell);"," //ut.insertCol(!ut.selectedTds.length ? cellInfo.colIndex + cellInfo.colSpan:ut.cellsRange.endColIndex +1);"," if (!ut.selectedTds.length) {"," ut.insertCol(cellInfo.colIndex + cellInfo.colSpan, cell);"," } else {"," var range = ut.cellsRange;"," for (var i = 0, len = range.endColIndex - range.beginColIndex + 1; i < len; i++) {"," ut.insertCol(range.endColIndex + 1, cell);"," }"," }"," rng.moveToBookmark(bk).select();"," }"," };",""," UE.commands[\"deletecol\"] = {"," queryCommandState: function () {"," var tableItems = getTableItemsByRange(this);"," if (!tableItems.cell) return -1;"," },"," execCommand: function () {"," var cell = getTableItemsByRange(this).cell,"," ut = getUETable(cell),"," range = ut.cellsRange,"," cellInfo = ut.getCellInfo(cell),"," preCell = ut.getHSideCell(cell),"," nextCell = ut.getHSideCell(cell, true);"," if (utils.isEmptyObject(range)) {"," ut.deleteCol(cellInfo.colIndex);"," } else {"," for (var i = range.beginColIndex; i < range.endColIndex + 1; i++) {"," ut.deleteCol(range.beginColIndex);"," }"," }"," var table = ut.table,"," rng = this.selection.getRange();",""," if (!table.getElementsByTagName('td').length) {"," var nextSibling = table.nextSibling;"," domUtils.remove(table);"," if (nextSibling) {"," rng.setStart(nextSibling, 0).setCursor(false, true);"," }"," } else {"," if (domUtils.inDoc(cell, this.document)) {"," rng.setStart(cell, 0).setCursor(false, true);"," } else {"," if (nextCell && domUtils.inDoc(nextCell, this.document)) {"," rng.selectNodeContents(nextCell).setCursor(false, true);"," } else {"," if (preCell && domUtils.inDoc(preCell, this.document)) {"," rng.selectNodeContents(preCell).setCursor(true, true);"," }"," }"," }"," }"," }"," };"," UE.commands[\"splittocells\"] = {"," queryCommandState: function () {"," var tableItems = getTableItemsByRange(this),"," cell = tableItems.cell;"," if (!cell) return -1;"," var ut = getUETable(tableItems.table);"," if (ut.selectedTds.length > 0) return -1;"," return cell && (cell.colSpan > 1 || cell.rowSpan > 1) ? 0 : -1;"," },"," execCommand: function () {"," var rng = this.selection.getRange(),"," bk = rng.createBookmark(true);"," var cell = getTableItemsByRange(this).cell,"," ut = getUETable(cell);"," ut.splitToCells(cell);"," rng.moveToBookmark(bk).select();"," }"," };"," UE.commands[\"splittorows\"] = {"," queryCommandState: function () {"," var tableItems = getTableItemsByRange(this),"," cell = tableItems.cell;"," if (!cell) return -1;"," var ut = getUETable(tableItems.table);"," if (ut.selectedTds.length > 0) return -1;"," return cell && cell.rowSpan > 1 ? 0 : -1;"," },"," execCommand: function () {"," var rng = this.selection.getRange(),"," bk = rng.createBookmark(true);"," var cell = getTableItemsByRange(this).cell,"," ut = getUETable(cell);"," ut.splitToRows(cell);"," rng.moveToBookmark(bk).select();"," }"," };"," UE.commands[\"splittocols\"] = {"," queryCommandState: function () {"," var tableItems = getTableItemsByRange(this),"," cell = tableItems.cell;"," if (!cell) return -1;"," var ut = getUETable(tableItems.table);"," if (ut.selectedTds.length > 0) return -1;"," return cell && cell.colSpan > 1 ? 0 : -1;"," },"," execCommand: function () {"," var rng = this.selection.getRange(),"," bk = rng.createBookmark(true);"," var cell = getTableItemsByRange(this).cell,"," ut = getUETable(cell);"," ut.splitToCols(cell);"," rng.moveToBookmark(bk).select();",""," }"," };",""," UE.commands[\"adaptbytext\"] ="," UE.commands[\"adaptbywindow\"] = {"," queryCommandState: function () {"," return getTableItemsByRange(this).table ? 0 : -1"," },"," execCommand: function (cmd) {"," var tableItems = getTableItemsByRange(this),"," table = tableItems.table;"," if (table) {"," if (cmd == 'adaptbywindow') {"," resetTdWidth(table, this);"," } else {"," var cells = domUtils.getElementsByTagName(table, \"td th\");"," utils.each(cells, function (cell) {"," cell.removeAttribute(\"width\");"," });"," table.removeAttribute(\"width\");"," }"," }"," }"," };",""," //平均分配各列"," UE.commands['averagedistributecol'] = {"," queryCommandState: function () {"," var ut = getUETableBySelected(this);"," if (!ut) return -1;"," return ut.isFullRow() || ut.isFullCol() ? 0 : -1;"," },"," execCommand: function (cmd) {"," var me = this,"," ut = getUETableBySelected(me);",""," function getAverageWidth() {"," var tb = ut.table,"," averageWidth, sumWidth = 0, colsNum = 0,"," tbAttr = getDefaultValue(me, tb);",""," if (ut.isFullRow()) {"," sumWidth = tb.offsetWidth;"," colsNum = ut.colsNum;"," } else {"," var begin = ut.cellsRange.beginColIndex,"," end = ut.cellsRange.endColIndex,"," node;"," for (var i = begin; i <= end;) {"," node = ut.selectedTds[i];"," sumWidth += node.offsetWidth;"," i += node.colSpan;"," colsNum += 1;"," }"," }"," averageWidth = Math.ceil(sumWidth / colsNum) - tbAttr.tdBorder * 2 - tbAttr.tdPadding * 2;"," return averageWidth;"," }",""," function setAverageWidth(averageWidth) {"," utils.each(domUtils.getElementsByTagName(ut.table, \"th\"), function (node) {"," node.setAttribute(\"width\", \"\");"," });"," var cells = ut.isFullRow() ? domUtils.getElementsByTagName(ut.table, \"td\") : ut.selectedTds;",""," utils.each(cells, function (node) {"," if (node.colSpan == 1) {"," node.setAttribute(\"width\", averageWidth);"," }"," });"," }",""," if (ut && ut.selectedTds.length) {"," setAverageWidth(getAverageWidth());"," }"," }"," };"," //平均分配各行"," UE.commands['averagedistributerow'] = {"," queryCommandState: function () {"," var ut = getUETableBySelected(this);"," if (!ut) return -1;"," if (ut.selectedTds && /th/ig.test(ut.selectedTds[0].tagName)) return -1;"," return ut.isFullRow() || ut.isFullCol() ? 0 : -1;"," },"," execCommand: function (cmd) {"," var me = this,"," ut = getUETableBySelected(me);",""," function getAverageHeight() {"," var averageHeight, rowNum, sumHeight = 0,"," tb = ut.table,"," tbAttr = getDefaultValue(me, tb),"," tdpadding = parseInt(domUtils.getComputedStyle(tb.getElementsByTagName('td')[0], \"padding-top\"));",""," if (ut.isFullCol()) {"," var captionArr = domUtils.getElementsByTagName(tb, \"caption\"),"," thArr = domUtils.getElementsByTagName(tb, \"th\"),"," captionHeight, thHeight;",""," if (captionArr.length > 0) {"," captionHeight = captionArr[0].offsetHeight;"," }"," if (thArr.length > 0) {"," thHeight = thArr[0].offsetHeight;"," }",""," sumHeight = tb.offsetHeight - (captionHeight || 0) - (thHeight || 0);"," rowNum = thArr.length == 0 ? ut.rowsNum : (ut.rowsNum - 1);"," } else {"," var begin = ut.cellsRange.beginRowIndex,"," end = ut.cellsRange.endRowIndex,"," count = 0,"," trs = domUtils.getElementsByTagName(tb, \"tr\");"," for (var i = begin; i <= end; i++) {"," sumHeight += trs[i].offsetHeight;"," count += 1;"," }"," rowNum = count;"," }"," //ie8下是混杂模式"," if (browser.ie && browser.version < 9) {"," averageHeight = Math.ceil(sumHeight / rowNum);"," } else {"," averageHeight = Math.ceil(sumHeight / rowNum) - tbAttr.tdBorder * 2 - tdpadding * 2;"," }"," return averageHeight;"," }",""," function setAverageHeight(averageHeight) {"," var cells = ut.isFullCol() ? domUtils.getElementsByTagName(ut.table, \"td\") : ut.selectedTds;"," utils.each(cells, function (node) {"," if (node.rowSpan == 1) {"," node.setAttribute(\"height\", averageHeight);"," }"," });"," }",""," if (ut && ut.selectedTds.length) {"," setAverageHeight(getAverageHeight());"," }"," }"," };",""," //单元格对齐方式"," UE.commands['cellalignment'] = {"," queryCommandState: function () {"," return getTableItemsByRange(this).table ? 0 : -1"," },"," execCommand: function (cmd, data) {"," var me = this,"," ut = getUETableBySelected(me);",""," if (!ut) {"," var start = me.selection.getStart(),"," cell = start && domUtils.findParentByTagName(start, [\"td\", \"th\", \"caption\"], true);"," if (!/caption/ig.test(cell.tagName)) {"," domUtils.setAttributes(cell, data);"," } else {"," cell.style.textAlign = data.align;"," cell.style.verticalAlign = data.vAlign;"," }"," me.selection.getRange().setCursor(true);"," } else {"," utils.each(ut.selectedTds, function (cell) {"," domUtils.setAttributes(cell, data);"," });"," }"," },"," /*"," * 查询当前点击的单元格的对齐状态, 如果当前已经选择了多个单元格, 则会返回所有单元格经过统一协调过后的状态"," * @see UE.UETable.getTableCellAlignState"," */"," queryCommandValue: function (cmd) {",""," var activeMenuCell = getTableItemsByRange( this).cell;",""," if( !activeMenuCell ) {"," activeMenuCell = getSelectedArr(this)[0];"," }",""," if (!activeMenuCell) {",""," return null;",""," } else {",""," //获取同时选中的其他单元格"," var cells = UE.UETable.getUETable(activeMenuCell).selectedTds;",""," !cells.length && ( cells = activeMenuCell );",""," return UE.UETable.getTableCellAlignState(cells);",""," }",""," }"," };"," //表格对齐方式"," UE.commands['tablealignment'] = {"," queryCommandState: function () {"," if (browser.ie && browser.version < 8) {"," return -1;"," }"," return getTableItemsByRange(this).table ? 0 : -1"," },"," execCommand: function (cmd, value) {"," var me = this,"," start = me.selection.getStart(),"," table = start && domUtils.findParentByTagName(start, [\"table\"], true);",""," if (table) {"," table.setAttribute(\"align\",value);"," }"," }"," };",""," //表格属性"," UE.commands['edittable'] = {"," queryCommandState: function () {"," return getTableItemsByRange(this).table ? 0 : -1"," },"," execCommand: function (cmd, color) {"," var rng = this.selection.getRange(),"," table = domUtils.findParentByTagName(rng.startContainer, 'table');"," if (table) {"," var arr = domUtils.getElementsByTagName(table, \"td\").concat("," domUtils.getElementsByTagName(table, \"th\"),"," domUtils.getElementsByTagName(table, \"caption\")"," );"," utils.each(arr, function (node) {"," node.style.borderColor = color;"," });"," }"," }"," };"," //单元格属性"," UE.commands['edittd'] = {"," queryCommandState: function () {"," return getTableItemsByRange(this).table ? 0 : -1"," },"," execCommand: function (cmd, bkColor) {"," var me = this,"," ut = getUETableBySelected(me);",""," if (!ut) {"," var start = me.selection.getStart(),"," cell = start && domUtils.findParentByTagName(start, [\"td\", \"th\", \"caption\"], true);"," if (cell) {"," cell.style.backgroundColor = bkColor;"," }"," } else {"," utils.each(ut.selectedTds, function (cell) {"," cell.style.backgroundColor = bkColor;"," });"," }"," }"," };"," UE.commands['sorttable'] = {"," queryCommandState: function () {"," var me = this,"," tableItems = getTableItemsByRange(me);"," if (!tableItems.cell) return -1;"," var table = tableItems.table,"," cells = table.getElementsByTagName(\"td\");"," for (var i = 0, cell; cell = cells[i++];) {"," if (cell.rowSpan != 1 || cell.colSpan != 1) return -1;"," }"," return 0;"," },"," execCommand: function (cmd, fn) {"," var me = this,"," range = me.selection.getRange(),"," bk = range.createBookmark(true),"," tableItems = getTableItemsByRange(me),"," cell = tableItems.cell,"," ut = getUETable(tableItems.table),"," cellInfo = ut.getCellInfo(cell);"," ut.sortTable(cellInfo.cellIndex, fn);"," range.moveToBookmark(bk).select();"," }"," };",""," UE.commands[\"enablesort\"] = UE.commands[\"disablesort\"] = {"," queryCommandState: function () {"," return getTableItemsByRange(this).table ? 0 : -1;"," },"," execCommand: function (cmd) {"," var table = getTableItemsByRange(this).table;"," table.setAttribute(\"data-sort\", cmd == \"enablesort\" ? \"sortEnabled\" : \"sortDisabled\");"," }"," };"," UE.commands[\"settablebackground\"] = {"," queryCommandState: function () {"," return getSelectedArr(this).length > 1 ? 0 : -1;"," },"," execCommand: function (cmd, value) {"," var table, cells, ut;"," cells = getSelectedArr(this);"," ut = getUETable(cells[0]);"," ut.setBackground(cells, value);"," }"," };",""," UE.commands[\"cleartablebackground\"] = {"," queryCommandState: function () {"," var cells = getSelectedArr(this);"," if (!cells.length)return -1;"," for (var i = 0, cell; cell = cells[i++];) {"," if (cell.style.backgroundColor !== \"\") return 0;"," }"," return -1;"," },"," execCommand: function () {"," var cells = getSelectedArr(this),"," ut = getUETable(cells[0]);"," ut.removeBackground(cells);"," }"," };",""," UE.commands[\"interlacetable\"] = UE.commands[\"uninterlacetable\"] = {"," queryCommandState: function (cmd) {"," var table = getTableItemsByRange(this).table;"," if (!table) return -1;"," var interlaced = table.getAttribute(\"interlaced\");"," if (cmd == \"interlacetable\") {"," //TODO 待定"," //是否需要待定,如果设置,则命令只能单次执行成功,但反射具备toggle效果;否则可以覆盖前次命令,但反射将不存在toggle效果"," return (interlaced === \"enabled\") ? -1 : 0;"," } else {"," return (!interlaced || interlaced === \"disabled\") ? -1 : 0;"," }"," },"," execCommand: function (cmd, classList) {"," var table = getTableItemsByRange(this).table;"," if (cmd == \"interlacetable\") {"," table.setAttribute(\"interlaced\", \"enabled\");"," this.fireEvent(\"interlacetable\", table, classList);"," } else {"," table.setAttribute(\"interlaced\", \"disabled\");"," this.fireEvent(\"uninterlacetable\", table);"," }"," }"," };",""," function resetTdWidth(table, editor) {"," var tds = table.getElementsByTagName(\"td\");"," utils.each(tds, function (td) {"," td.removeAttribute(\"width\");"," });"," table.setAttribute('width', getTableWidth(editor, true, getDefaultValue(editor, table)));"," setTimeout(function () {"," utils.each(tds, function (td) {"," (td.colSpan == 1) && td.setAttribute(\"width\", td.offsetWidth + \"\");"," })"," }, 0);"," }",""," function getTableWidth(editor, needIEHack, defaultValue) {"," var body = editor.body;"," return body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(body, 'margin-left'), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (editor.options.offsetWidth || 0);"," }",""," function getSelectedArr(editor) {"," var cell = getTableItemsByRange(editor).cell;"," if (cell) {"," var ut = getUETable(cell);"," return ut.selectedTds.length ? ut.selectedTds : [cell];"," } else {"," return [];"," }"," }","})();"]; +_$jscoverage['plugins/table.cmds.js'][8]++; +; +_$jscoverage['plugins/table.cmds.js'][9]++; +(function () { + _$jscoverage['plugins/table.cmds.js'][10]++; + var UT = UE.UETable, getTableItemsByRange = (function (editor) { + _$jscoverage['plugins/table.cmds.js'][12]++; + return UT.getTableItemsByRange(editor); +}), getUETableBySelected = (function (editor) { + _$jscoverage['plugins/table.cmds.js'][15]++; + return UT.getUETableBySelected(editor); +}), getDefaultValue = (function (editor, table) { + _$jscoverage['plugins/table.cmds.js'][18]++; + return UT.getDefaultValue(editor, table); +}), getUETable = (function (tdOrTable) { + _$jscoverage['plugins/table.cmds.js'][21]++; + return UT.getUETable(tdOrTable); +}); + _$jscoverage['plugins/table.cmds.js'][25]++; + UE.commands.inserttable = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][27]++; + return (getTableItemsByRange(this).table? -1: 0); +}), execCommand: (function (cmd, opt) { + _$jscoverage['plugins/table.cmds.js'][30]++; + function createTable(opt, tdWidth) { + _$jscoverage['plugins/table.cmds.js'][31]++; + var html = [], rowsNum = opt.numRows, colsNum = opt.numCols; + _$jscoverage['plugins/table.cmds.js'][34]++; + for (var r = 0; (r < rowsNum); (r++)) { + _$jscoverage['plugins/table.cmds.js'][35]++; + html.push(""); + _$jscoverage['plugins/table.cmds.js'][36]++; + for (var c = 0; (c < colsNum); (c++)) { + _$jscoverage['plugins/table.cmds.js'][37]++; + html.push(("" + (browser.ie? domUtils.fillChar: "
    ") + "")); +} + _$jscoverage['plugins/table.cmds.js'][39]++; + html.push(""); +} + _$jscoverage['plugins/table.cmds.js'][42]++; + return ("" + html.join("") + "
    "); +} + _$jscoverage['plugins/table.cmds.js'][45]++; + if ((! opt)) { + _$jscoverage['plugins/table.cmds.js'][46]++; + opt = utils.extend({}, {numCols: this.options.defaultCols, numRows: this.options.defaultRows, tdvalign: this.options.tdvalign}); + } + _$jscoverage['plugins/table.cmds.js'][52]++; + var me = this; + _$jscoverage['plugins/table.cmds.js'][53]++; + var range = this.selection.getRange(), start = range.startContainer, firstParentBlock = (domUtils.findParent(start, (function (node) { + _$jscoverage['plugins/table.cmds.js'][56]++; + return domUtils.isBlockElm(node); +}), true) || me.body); + _$jscoverage['plugins/table.cmds.js'][59]++; + var defaultValue = getDefaultValue(me), tableWidth = firstParentBlock.offsetWidth, tdWidth = Math.floor(((tableWidth / opt.numCols) - (defaultValue.tdPadding * 2) - defaultValue.tdBorder)); + _$jscoverage['plugins/table.cmds.js'][64]++; + ((! opt.tdvalign) && (opt.tdvalign = me.options.tdvalign)); + _$jscoverage['plugins/table.cmds.js'][65]++; + me.execCommand("inserthtml", createTable(opt, tdWidth)); +})}; + _$jscoverage['plugins/table.cmds.js'][69]++; + UE.commands.insertparagraphbeforetable = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][71]++; + return (getTableItemsByRange(this).cell? 0: -1); +}), execCommand: (function () { + _$jscoverage['plugins/table.cmds.js'][74]++; + var table = getTableItemsByRange(this).table; + _$jscoverage['plugins/table.cmds.js'][75]++; + if (table) { + _$jscoverage['plugins/table.cmds.js'][76]++; + var p = this.document.createElement("p"); + _$jscoverage['plugins/table.cmds.js'][77]++; + p.innerHTML = (browser.ie? " ": "
    "); + _$jscoverage['plugins/table.cmds.js'][78]++; + table.parentNode.insertBefore(p, table); + _$jscoverage['plugins/table.cmds.js'][79]++; + this.selection.getRange().setStart(p, 0).setCursor(); + } +})}; + _$jscoverage['plugins/table.cmds.js'][84]++; + UE.commands.deletetable = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][86]++; + var rng = this.selection.getRange(); + _$jscoverage['plugins/table.cmds.js'][87]++; + return (domUtils.findParentByTagName(rng.startContainer, "table", true)? 0: -1); +}), execCommand: (function (cmd, table) { + _$jscoverage['plugins/table.cmds.js'][90]++; + var rng = this.selection.getRange(); + _$jscoverage['plugins/table.cmds.js'][91]++; + table = (table || domUtils.findParentByTagName(rng.startContainer, "table", true)); + _$jscoverage['plugins/table.cmds.js'][92]++; + if (table) { + _$jscoverage['plugins/table.cmds.js'][93]++; + var next = table.nextSibling; + _$jscoverage['plugins/table.cmds.js'][94]++; + if ((! next)) { + _$jscoverage['plugins/table.cmds.js'][95]++; + next = domUtils.createElement(this.document, "p", {"innerHTML": (browser.ie? domUtils.fillChar: "
    ")}); + _$jscoverage['plugins/table.cmds.js'][98]++; + table.parentNode.insertBefore(next, table); + } + _$jscoverage['plugins/table.cmds.js'][100]++; + domUtils.remove(table); + _$jscoverage['plugins/table.cmds.js'][101]++; + rng = this.selection.getRange(); + _$jscoverage['plugins/table.cmds.js'][102]++; + if ((next.nodeType == 3)) { + _$jscoverage['plugins/table.cmds.js'][103]++; + rng.setStartBefore(next); + } + else { + _$jscoverage['plugins/table.cmds.js'][105]++; + rng.setStart(next, 0); + } + _$jscoverage['plugins/table.cmds.js'][107]++; + rng.setCursor(false, true); + _$jscoverage['plugins/table.cmds.js'][108]++; + this.fireEvent("tablehasdeleted"); + } +})}; + _$jscoverage['plugins/table.cmds.js'][114]++; + UE.commands.cellalign = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][116]++; + return (getSelectedArr(this).length? 0: -1); +}), execCommand: (function (cmd, align) { + _$jscoverage['plugins/table.cmds.js'][119]++; + var selectedTds = getSelectedArr(this); + _$jscoverage['plugins/table.cmds.js'][120]++; + if (selectedTds.length) { + _$jscoverage['plugins/table.cmds.js'][121]++; + for (var i = 0, ci; (ci = selectedTds[(i++)]);) { + _$jscoverage['plugins/table.cmds.js'][122]++; + ci.setAttribute("align", align); +} + } +})}; + _$jscoverage['plugins/table.cmds.js'][127]++; + UE.commands.cellvalign = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][129]++; + return (getSelectedArr(this).length? 0: -1); +}), execCommand: (function (cmd, valign) { + _$jscoverage['plugins/table.cmds.js'][132]++; + var selectedTds = getSelectedArr(this); + _$jscoverage['plugins/table.cmds.js'][133]++; + if (selectedTds.length) { + _$jscoverage['plugins/table.cmds.js'][134]++; + for (var i = 0, ci; (ci = selectedTds[(i++)]);) { + _$jscoverage['plugins/table.cmds.js'][135]++; + ci.setAttribute("vAlign", valign); +} + } +})}; + _$jscoverage['plugins/table.cmds.js'][140]++; + UE.commands.insertcaption = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][142]++; + var table = getTableItemsByRange(this).table; + _$jscoverage['plugins/table.cmds.js'][143]++; + if (table) { + _$jscoverage['plugins/table.cmds.js'][144]++; + return ((table.getElementsByTagName("caption").length == 0)? 1: -1); + } + _$jscoverage['plugins/table.cmds.js'][146]++; + return -1; +}), execCommand: (function () { + _$jscoverage['plugins/table.cmds.js'][149]++; + var table = getTableItemsByRange(this).table; + _$jscoverage['plugins/table.cmds.js'][150]++; + if (table) { + _$jscoverage['plugins/table.cmds.js'][151]++; + var caption = this.document.createElement("caption"); + _$jscoverage['plugins/table.cmds.js'][152]++; + caption.innerHTML = (browser.ie? domUtils.fillChar: "
    "); + _$jscoverage['plugins/table.cmds.js'][153]++; + table.insertBefore(caption, table.firstChild); + _$jscoverage['plugins/table.cmds.js'][154]++; + var range = this.selection.getRange(); + _$jscoverage['plugins/table.cmds.js'][155]++; + range.setStart(caption, 0).setCursor(); + } +})}; + _$jscoverage['plugins/table.cmds.js'][160]++; + UE.commands.deletecaption = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][162]++; + var rng = this.selection.getRange(), table = domUtils.findParentByTagName(rng.startContainer, "table"); + _$jscoverage['plugins/table.cmds.js'][164]++; + if (table) { + _$jscoverage['plugins/table.cmds.js'][165]++; + return ((table.getElementsByTagName("caption").length == 0)? -1: 1); + } + _$jscoverage['plugins/table.cmds.js'][167]++; + return -1; +}), execCommand: (function () { + _$jscoverage['plugins/table.cmds.js'][170]++; + var rng = this.selection.getRange(), table = domUtils.findParentByTagName(rng.startContainer, "table"); + _$jscoverage['plugins/table.cmds.js'][172]++; + if (table) { + _$jscoverage['plugins/table.cmds.js'][173]++; + domUtils.remove(table.getElementsByTagName("caption")[0]); + _$jscoverage['plugins/table.cmds.js'][174]++; + var range = this.selection.getRange(); + _$jscoverage['plugins/table.cmds.js'][175]++; + range.setStart(table.rows[0].cells[0], 0).setCursor(); + } +})}; + _$jscoverage['plugins/table.cmds.js'][180]++; + UE.commands.inserttitle = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][182]++; + var table = getTableItemsByRange(this).table; + _$jscoverage['plugins/table.cmds.js'][183]++; + if (table) { + _$jscoverage['plugins/table.cmds.js'][184]++; + var firstRow = table.rows[0]; + _$jscoverage['plugins/table.cmds.js'][185]++; + return ((firstRow.getElementsByTagName("th").length == 0)? 0: -1); + } + _$jscoverage['plugins/table.cmds.js'][187]++; + return -1; +}), execCommand: (function () { + _$jscoverage['plugins/table.cmds.js'][190]++; + var table = getTableItemsByRange(this).table; + _$jscoverage['plugins/table.cmds.js'][191]++; + if (table) { + _$jscoverage['plugins/table.cmds.js'][192]++; + getUETable(table).insertRow(0, "th"); + } + _$jscoverage['plugins/table.cmds.js'][194]++; + var th = table.getElementsByTagName("th")[0]; + _$jscoverage['plugins/table.cmds.js'][195]++; + this.selection.getRange().setStart(th, 0).setCursor(false, true); +})}; + _$jscoverage['plugins/table.cmds.js'][198]++; + UE.commands.deletetitle = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][200]++; + var table = getTableItemsByRange(this).table; + _$jscoverage['plugins/table.cmds.js'][201]++; + if (table) { + _$jscoverage['plugins/table.cmds.js'][202]++; + var firstRow = table.rows[0]; + _$jscoverage['plugins/table.cmds.js'][203]++; + return (firstRow.getElementsByTagName("th").length? 0: -1); + } + _$jscoverage['plugins/table.cmds.js'][205]++; + return -1; +}), execCommand: (function () { + _$jscoverage['plugins/table.cmds.js'][208]++; + var table = getTableItemsByRange(this).table; + _$jscoverage['plugins/table.cmds.js'][209]++; + if (table) { + _$jscoverage['plugins/table.cmds.js'][210]++; + domUtils.remove(table.rows[0]); + } + _$jscoverage['plugins/table.cmds.js'][212]++; + var td = table.getElementsByTagName("td")[0]; + _$jscoverage['plugins/table.cmds.js'][213]++; + this.selection.getRange().setStart(td, 0).setCursor(false, true); +})}; + _$jscoverage['plugins/table.cmds.js'][217]++; + UE.commands.mergeright = {queryCommandState: (function (cmd) { + _$jscoverage['plugins/table.cmds.js'][219]++; + var tableItems = getTableItemsByRange(this); + _$jscoverage['plugins/table.cmds.js'][220]++; + if ((! tableItems.cell)) { + _$jscoverage['plugins/table.cmds.js'][220]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][221]++; + var ut = getUETable(tableItems.table); + _$jscoverage['plugins/table.cmds.js'][222]++; + if (ut.selectedTds.length) { + _$jscoverage['plugins/table.cmds.js'][222]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][223]++; + var cellInfo = ut.getCellInfo(tableItems.cell), rightColIndex = (cellInfo.colIndex + cellInfo.colSpan); + _$jscoverage['plugins/table.cmds.js'][225]++; + if ((rightColIndex >= ut.colsNum)) { + _$jscoverage['plugins/table.cmds.js'][225]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][226]++; + var rightCellInfo = ut.indexTable[cellInfo.rowIndex][rightColIndex]; + _$jscoverage['plugins/table.cmds.js'][227]++; + return (((rightCellInfo.rowIndex == cellInfo.rowIndex) && (rightCellInfo.rowSpan == cellInfo.rowSpan))? 0: -1); +}), execCommand: (function (cmd) { + _$jscoverage['plugins/table.cmds.js'][231]++; + var rng = this.selection.getRange(), bk = rng.createBookmark(true); + _$jscoverage['plugins/table.cmds.js'][233]++; + var cell = getTableItemsByRange(this).cell, ut = getUETable(cell); + _$jscoverage['plugins/table.cmds.js'][235]++; + ut.mergeRight(cell); + _$jscoverage['plugins/table.cmds.js'][236]++; + rng.moveToBookmark(bk).select(); +})}; + _$jscoverage['plugins/table.cmds.js'][239]++; + UE.commands.mergedown = {queryCommandState: (function (cmd) { + _$jscoverage['plugins/table.cmds.js'][241]++; + var tableItems = getTableItemsByRange(this), cell = tableItems.cell; + _$jscoverage['plugins/table.cmds.js'][243]++; + if (((! cell) || (cell.tagName == "TH"))) { + _$jscoverage['plugins/table.cmds.js'][243]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][244]++; + var ut = getUETable(tableItems.table); + _$jscoverage['plugins/table.cmds.js'][245]++; + if (ut.selectedTds.length) { + _$jscoverage['plugins/table.cmds.js'][245]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][246]++; + var cellInfo = ut.getCellInfo(tableItems.cell), downRowIndex = (cellInfo.rowIndex + cellInfo.rowSpan); + _$jscoverage['plugins/table.cmds.js'][249]++; + if ((downRowIndex >= ut.rowsNum)) { + _$jscoverage['plugins/table.cmds.js'][249]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][250]++; + var downCellInfo = ut.indexTable[downRowIndex][cellInfo.colIndex]; + _$jscoverage['plugins/table.cmds.js'][252]++; + return (((downCellInfo.colIndex == cellInfo.colIndex) && (downCellInfo.colSpan == cellInfo.colSpan) && (tableItems.cell.tagName !== "TH"))? 0: -1); +}), execCommand: (function () { + _$jscoverage['plugins/table.cmds.js'][256]++; + var rng = this.selection.getRange(), bk = rng.createBookmark(true); + _$jscoverage['plugins/table.cmds.js'][258]++; + var cell = getTableItemsByRange(this).cell, ut = getUETable(cell); + _$jscoverage['plugins/table.cmds.js'][260]++; + ut.mergeDown(cell); + _$jscoverage['plugins/table.cmds.js'][261]++; + rng.moveToBookmark(bk).select(); +})}; + _$jscoverage['plugins/table.cmds.js'][264]++; + UE.commands.mergecells = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][266]++; + return (getUETableBySelected(this)? 0: -1); +}), execCommand: (function () { + _$jscoverage['plugins/table.cmds.js'][269]++; + var ut = getUETableBySelected(this); + _$jscoverage['plugins/table.cmds.js'][270]++; + if ((ut && ut.selectedTds.length)) { + _$jscoverage['plugins/table.cmds.js'][271]++; + var cell = ut.selectedTds[0]; + _$jscoverage['plugins/table.cmds.js'][272]++; + ut.mergeRange(); + _$jscoverage['plugins/table.cmds.js'][273]++; + var rng = this.selection.getRange(); + _$jscoverage['plugins/table.cmds.js'][274]++; + if (domUtils.isEmptyBlock(cell)) { + _$jscoverage['plugins/table.cmds.js'][275]++; + rng.setStart(cell, 0).collapse(true); + } + else { + _$jscoverage['plugins/table.cmds.js'][277]++; + rng.selectNodeContents(cell); + } + _$jscoverage['plugins/table.cmds.js'][279]++; + rng.select(); + } +})}; + _$jscoverage['plugins/table.cmds.js'][285]++; + UE.commands.insertrow = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][287]++; + var tableItems = getTableItemsByRange(this), cell = tableItems.cell; + _$jscoverage['plugins/table.cmds.js'][289]++; + return ((cell && (cell.tagName == "TD") && (getUETable(tableItems.table).rowsNum < this.options.maxRowNum))? 0: -1); +}), execCommand: (function () { + _$jscoverage['plugins/table.cmds.js'][292]++; + var rng = this.selection.getRange(), bk = rng.createBookmark(true); + _$jscoverage['plugins/table.cmds.js'][294]++; + var tableItems = getTableItemsByRange(this), cell = tableItems.cell, table = tableItems.table, ut = getUETable(table), cellInfo = ut.getCellInfo(cell); + _$jscoverage['plugins/table.cmds.js'][300]++; + if ((! ut.selectedTds.length)) { + _$jscoverage['plugins/table.cmds.js'][301]++; + ut.insertRow(cellInfo.rowIndex, cell); + } + else { + _$jscoverage['plugins/table.cmds.js'][303]++; + var range = ut.cellsRange; + _$jscoverage['plugins/table.cmds.js'][304]++; + for (var i = 0, len = ((range.endRowIndex - range.beginRowIndex) + 1); (i < len); (i++)) { + _$jscoverage['plugins/table.cmds.js'][305]++; + ut.insertRow(range.beginRowIndex, cell); +} + } + _$jscoverage['plugins/table.cmds.js'][308]++; + rng.moveToBookmark(bk).select(); + _$jscoverage['plugins/table.cmds.js'][309]++; + if ((table.getAttribute("interlaced") === "enabled")) { + _$jscoverage['plugins/table.cmds.js'][309]++; + this.fireEvent("interlacetable", table); + } +})}; + _$jscoverage['plugins/table.cmds.js'][313]++; + UE.commands.insertrownext = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][315]++; + var tableItems = getTableItemsByRange(this), cell = tableItems.cell; + _$jscoverage['plugins/table.cmds.js'][317]++; + return ((cell && (cell.tagName == "TD") && (getUETable(tableItems.table).rowsNum < this.options.maxRowNum))? 0: -1); +}), execCommand: (function () { + _$jscoverage['plugins/table.cmds.js'][320]++; + var rng = this.selection.getRange(), bk = rng.createBookmark(true); + _$jscoverage['plugins/table.cmds.js'][322]++; + var tableItems = getTableItemsByRange(this), cell = tableItems.cell, table = tableItems.table, ut = getUETable(table), cellInfo = ut.getCellInfo(cell); + _$jscoverage['plugins/table.cmds.js'][328]++; + if ((! ut.selectedTds.length)) { + _$jscoverage['plugins/table.cmds.js'][329]++; + ut.insertRow((cellInfo.rowIndex + cellInfo.rowSpan), cell); + } + else { + _$jscoverage['plugins/table.cmds.js'][331]++; + var range = ut.cellsRange; + _$jscoverage['plugins/table.cmds.js'][332]++; + for (var i = 0, len = ((range.endRowIndex - range.beginRowIndex) + 1); (i < len); (i++)) { + _$jscoverage['plugins/table.cmds.js'][333]++; + ut.insertRow((range.endRowIndex + 1), cell); +} + } + _$jscoverage['plugins/table.cmds.js'][336]++; + rng.moveToBookmark(bk).select(); + _$jscoverage['plugins/table.cmds.js'][337]++; + if ((table.getAttribute("interlaced") === "enabled")) { + _$jscoverage['plugins/table.cmds.js'][337]++; + this.fireEvent("interlacetable", table); + } +})}; + _$jscoverage['plugins/table.cmds.js'][340]++; + UE.commands.deleterow = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][342]++; + var tableItems = getTableItemsByRange(this); + _$jscoverage['plugins/table.cmds.js'][343]++; + if ((! tableItems.cell)) { + _$jscoverage['plugins/table.cmds.js'][344]++; + return -1; + } +}), execCommand: (function () { + _$jscoverage['plugins/table.cmds.js'][348]++; + var cell = getTableItemsByRange(this).cell, ut = getUETable(cell), cellsRange = ut.cellsRange, cellInfo = ut.getCellInfo(cell), preCell = ut.getVSideCell(cell), nextCell = ut.getVSideCell(cell, true), rng = this.selection.getRange(); + _$jscoverage['plugins/table.cmds.js'][355]++; + if (utils.isEmptyObject(cellsRange)) { + _$jscoverage['plugins/table.cmds.js'][356]++; + ut.deleteRow(cellInfo.rowIndex); + } + else { + _$jscoverage['plugins/table.cmds.js'][358]++; + for (var i = cellsRange.beginRowIndex; (i < (cellsRange.endRowIndex + 1)); (i++)) { + _$jscoverage['plugins/table.cmds.js'][359]++; + ut.deleteRow(cellsRange.beginRowIndex); +} + } + _$jscoverage['plugins/table.cmds.js'][362]++; + var table = ut.table; + _$jscoverage['plugins/table.cmds.js'][363]++; + if ((! table.getElementsByTagName("td").length)) { + _$jscoverage['plugins/table.cmds.js'][364]++; + var nextSibling = table.nextSibling; + _$jscoverage['plugins/table.cmds.js'][365]++; + domUtils.remove(table); + _$jscoverage['plugins/table.cmds.js'][366]++; + if (nextSibling) { + _$jscoverage['plugins/table.cmds.js'][367]++; + rng.setStart(nextSibling, 0).setCursor(false, true); + } + } + else { + _$jscoverage['plugins/table.cmds.js'][370]++; + if (((cellInfo.rowSpan == 1) || (cellInfo.rowSpan == ((cellsRange.endRowIndex - cellsRange.beginRowIndex) + 1)))) { + _$jscoverage['plugins/table.cmds.js'][371]++; + if ((nextCell || preCell)) { + _$jscoverage['plugins/table.cmds.js'][371]++; + rng.selectNodeContents((nextCell || preCell)).setCursor(false, true); + } + } + else { + _$jscoverage['plugins/table.cmds.js'][373]++; + var newCell = ut.getCell(cellInfo.rowIndex, ut.indexTable[cellInfo.rowIndex][cellInfo.colIndex].cellIndex); + _$jscoverage['plugins/table.cmds.js'][374]++; + if (newCell) { + _$jscoverage['plugins/table.cmds.js'][374]++; + rng.selectNodeContents(newCell).setCursor(false, true); + } + } + } + _$jscoverage['plugins/table.cmds.js'][377]++; + if ((table.getAttribute("interlaced") === "enabled")) { + _$jscoverage['plugins/table.cmds.js'][377]++; + this.fireEvent("interlacetable", table); + } +})}; + _$jscoverage['plugins/table.cmds.js'][380]++; + UE.commands.insertcol = {queryCommandState: (function (cmd) { + _$jscoverage['plugins/table.cmds.js'][382]++; + var tableItems = getTableItemsByRange(this), cell = tableItems.cell; + _$jscoverage['plugins/table.cmds.js'][384]++; + return ((cell && ((cell.tagName == "TD") || (cell.tagName == "TH")) && (getUETable(tableItems.table).colsNum < this.options.maxColNum))? 0: -1); +}), execCommand: (function (cmd) { + _$jscoverage['plugins/table.cmds.js'][387]++; + var rng = this.selection.getRange(), bk = rng.createBookmark(true); + _$jscoverage['plugins/table.cmds.js'][389]++; + if ((this.queryCommandState(cmd) == -1)) { + _$jscoverage['plugins/table.cmds.js'][389]++; + return; + } + _$jscoverage['plugins/table.cmds.js'][390]++; + var cell = getTableItemsByRange(this).cell, ut = getUETable(cell), cellInfo = ut.getCellInfo(cell); + _$jscoverage['plugins/table.cmds.js'][395]++; + if ((! ut.selectedTds.length)) { + _$jscoverage['plugins/table.cmds.js'][396]++; + ut.insertCol(cellInfo.colIndex, cell); + } + else { + _$jscoverage['plugins/table.cmds.js'][398]++; + var range = ut.cellsRange; + _$jscoverage['plugins/table.cmds.js'][399]++; + for (var i = 0, len = ((range.endColIndex - range.beginColIndex) + 1); (i < len); (i++)) { + _$jscoverage['plugins/table.cmds.js'][400]++; + ut.insertCol(range.beginColIndex, cell); +} + } + _$jscoverage['plugins/table.cmds.js'][403]++; + rng.moveToBookmark(bk).select(true); +})}; + _$jscoverage['plugins/table.cmds.js'][406]++; + UE.commands.insertcolnext = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][408]++; + var tableItems = getTableItemsByRange(this), cell = tableItems.cell; + _$jscoverage['plugins/table.cmds.js'][410]++; + return ((cell && (getUETable(tableItems.table).colsNum < this.options.maxColNum))? 0: -1); +}), execCommand: (function () { + _$jscoverage['plugins/table.cmds.js'][413]++; + var rng = this.selection.getRange(), bk = rng.createBookmark(true); + _$jscoverage['plugins/table.cmds.js'][415]++; + var cell = getTableItemsByRange(this).cell, ut = getUETable(cell), cellInfo = ut.getCellInfo(cell); + _$jscoverage['plugins/table.cmds.js'][419]++; + if ((! ut.selectedTds.length)) { + _$jscoverage['plugins/table.cmds.js'][420]++; + ut.insertCol((cellInfo.colIndex + cellInfo.colSpan), cell); + } + else { + _$jscoverage['plugins/table.cmds.js'][422]++; + var range = ut.cellsRange; + _$jscoverage['plugins/table.cmds.js'][423]++; + for (var i = 0, len = ((range.endColIndex - range.beginColIndex) + 1); (i < len); (i++)) { + _$jscoverage['plugins/table.cmds.js'][424]++; + ut.insertCol((range.endColIndex + 1), cell); +} + } + _$jscoverage['plugins/table.cmds.js'][427]++; + rng.moveToBookmark(bk).select(); +})}; + _$jscoverage['plugins/table.cmds.js'][431]++; + UE.commands.deletecol = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][433]++; + var tableItems = getTableItemsByRange(this); + _$jscoverage['plugins/table.cmds.js'][434]++; + if ((! tableItems.cell)) { + _$jscoverage['plugins/table.cmds.js'][434]++; + return -1; + } +}), execCommand: (function () { + _$jscoverage['plugins/table.cmds.js'][437]++; + var cell = getTableItemsByRange(this).cell, ut = getUETable(cell), range = ut.cellsRange, cellInfo = ut.getCellInfo(cell), preCell = ut.getHSideCell(cell), nextCell = ut.getHSideCell(cell, true); + _$jscoverage['plugins/table.cmds.js'][443]++; + if (utils.isEmptyObject(range)) { + _$jscoverage['plugins/table.cmds.js'][444]++; + ut.deleteCol(cellInfo.colIndex); + } + else { + _$jscoverage['plugins/table.cmds.js'][446]++; + for (var i = range.beginColIndex; (i < (range.endColIndex + 1)); (i++)) { + _$jscoverage['plugins/table.cmds.js'][447]++; + ut.deleteCol(range.beginColIndex); +} + } + _$jscoverage['plugins/table.cmds.js'][450]++; + var table = ut.table, rng = this.selection.getRange(); + _$jscoverage['plugins/table.cmds.js'][453]++; + if ((! table.getElementsByTagName("td").length)) { + _$jscoverage['plugins/table.cmds.js'][454]++; + var nextSibling = table.nextSibling; + _$jscoverage['plugins/table.cmds.js'][455]++; + domUtils.remove(table); + _$jscoverage['plugins/table.cmds.js'][456]++; + if (nextSibling) { + _$jscoverage['plugins/table.cmds.js'][457]++; + rng.setStart(nextSibling, 0).setCursor(false, true); + } + } + else { + _$jscoverage['plugins/table.cmds.js'][460]++; + if (domUtils.inDoc(cell, this.document)) { + _$jscoverage['plugins/table.cmds.js'][461]++; + rng.setStart(cell, 0).setCursor(false, true); + } + else { + _$jscoverage['plugins/table.cmds.js'][463]++; + if ((nextCell && domUtils.inDoc(nextCell, this.document))) { + _$jscoverage['plugins/table.cmds.js'][464]++; + rng.selectNodeContents(nextCell).setCursor(false, true); + } + else { + _$jscoverage['plugins/table.cmds.js'][466]++; + if ((preCell && domUtils.inDoc(preCell, this.document))) { + _$jscoverage['plugins/table.cmds.js'][467]++; + rng.selectNodeContents(preCell).setCursor(true, true); + } + } + } + } +})}; + _$jscoverage['plugins/table.cmds.js'][474]++; + UE.commands.splittocells = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][476]++; + var tableItems = getTableItemsByRange(this), cell = tableItems.cell; + _$jscoverage['plugins/table.cmds.js'][478]++; + if ((! cell)) { + _$jscoverage['plugins/table.cmds.js'][478]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][479]++; + var ut = getUETable(tableItems.table); + _$jscoverage['plugins/table.cmds.js'][480]++; + if ((ut.selectedTds.length > 0)) { + _$jscoverage['plugins/table.cmds.js'][480]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][481]++; + return ((cell && ((cell.colSpan > 1) || (cell.rowSpan > 1)))? 0: -1); +}), execCommand: (function () { + _$jscoverage['plugins/table.cmds.js'][484]++; + var rng = this.selection.getRange(), bk = rng.createBookmark(true); + _$jscoverage['plugins/table.cmds.js'][486]++; + var cell = getTableItemsByRange(this).cell, ut = getUETable(cell); + _$jscoverage['plugins/table.cmds.js'][488]++; + ut.splitToCells(cell); + _$jscoverage['plugins/table.cmds.js'][489]++; + rng.moveToBookmark(bk).select(); +})}; + _$jscoverage['plugins/table.cmds.js'][492]++; + UE.commands.splittorows = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][494]++; + var tableItems = getTableItemsByRange(this), cell = tableItems.cell; + _$jscoverage['plugins/table.cmds.js'][496]++; + if ((! cell)) { + _$jscoverage['plugins/table.cmds.js'][496]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][497]++; + var ut = getUETable(tableItems.table); + _$jscoverage['plugins/table.cmds.js'][498]++; + if ((ut.selectedTds.length > 0)) { + _$jscoverage['plugins/table.cmds.js'][498]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][499]++; + return ((cell && (cell.rowSpan > 1))? 0: -1); +}), execCommand: (function () { + _$jscoverage['plugins/table.cmds.js'][502]++; + var rng = this.selection.getRange(), bk = rng.createBookmark(true); + _$jscoverage['plugins/table.cmds.js'][504]++; + var cell = getTableItemsByRange(this).cell, ut = getUETable(cell); + _$jscoverage['plugins/table.cmds.js'][506]++; + ut.splitToRows(cell); + _$jscoverage['plugins/table.cmds.js'][507]++; + rng.moveToBookmark(bk).select(); +})}; + _$jscoverage['plugins/table.cmds.js'][510]++; + UE.commands.splittocols = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][512]++; + var tableItems = getTableItemsByRange(this), cell = tableItems.cell; + _$jscoverage['plugins/table.cmds.js'][514]++; + if ((! cell)) { + _$jscoverage['plugins/table.cmds.js'][514]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][515]++; + var ut = getUETable(tableItems.table); + _$jscoverage['plugins/table.cmds.js'][516]++; + if ((ut.selectedTds.length > 0)) { + _$jscoverage['plugins/table.cmds.js'][516]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][517]++; + return ((cell && (cell.colSpan > 1))? 0: -1); +}), execCommand: (function () { + _$jscoverage['plugins/table.cmds.js'][520]++; + var rng = this.selection.getRange(), bk = rng.createBookmark(true); + _$jscoverage['plugins/table.cmds.js'][522]++; + var cell = getTableItemsByRange(this).cell, ut = getUETable(cell); + _$jscoverage['plugins/table.cmds.js'][524]++; + ut.splitToCols(cell); + _$jscoverage['plugins/table.cmds.js'][525]++; + rng.moveToBookmark(bk).select(); +})}; + _$jscoverage['plugins/table.cmds.js'][530]++; + UE.commands.adaptbytext = (UE.commands.adaptbywindow = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][533]++; + return (getTableItemsByRange(this).table? 0: -1); +}), execCommand: (function (cmd) { + _$jscoverage['plugins/table.cmds.js'][536]++; + var tableItems = getTableItemsByRange(this), table = tableItems.table; + _$jscoverage['plugins/table.cmds.js'][538]++; + if (table) { + _$jscoverage['plugins/table.cmds.js'][539]++; + if ((cmd == "adaptbywindow")) { + _$jscoverage['plugins/table.cmds.js'][540]++; + resetTdWidth(table, this); + } + else { + _$jscoverage['plugins/table.cmds.js'][542]++; + var cells = domUtils.getElementsByTagName(table, "td th"); + _$jscoverage['plugins/table.cmds.js'][543]++; + utils.each(cells, (function (cell) { + _$jscoverage['plugins/table.cmds.js'][544]++; + cell.removeAttribute("width"); +})); + _$jscoverage['plugins/table.cmds.js'][546]++; + table.removeAttribute("width"); + } + } +})}); + _$jscoverage['plugins/table.cmds.js'][553]++; + UE.commands.averagedistributecol = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][555]++; + var ut = getUETableBySelected(this); + _$jscoverage['plugins/table.cmds.js'][556]++; + if ((! ut)) { + _$jscoverage['plugins/table.cmds.js'][556]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][557]++; + return ((ut.isFullRow() || ut.isFullCol())? 0: -1); +}), execCommand: (function (cmd) { + _$jscoverage['plugins/table.cmds.js'][560]++; + var me = this, ut = getUETableBySelected(me); + _$jscoverage['plugins/table.cmds.js'][563]++; + function getAverageWidth() { + _$jscoverage['plugins/table.cmds.js'][564]++; + var tb = ut.table, averageWidth, sumWidth = 0, colsNum = 0, tbAttr = getDefaultValue(me, tb); + _$jscoverage['plugins/table.cmds.js'][568]++; + if (ut.isFullRow()) { + _$jscoverage['plugins/table.cmds.js'][569]++; + sumWidth = tb.offsetWidth; + _$jscoverage['plugins/table.cmds.js'][570]++; + colsNum = ut.colsNum; + } + else { + _$jscoverage['plugins/table.cmds.js'][572]++; + var begin = ut.cellsRange.beginColIndex, end = ut.cellsRange.endColIndex, node; + _$jscoverage['plugins/table.cmds.js'][575]++; + for (var i = begin; (i <= end);) { + _$jscoverage['plugins/table.cmds.js'][576]++; + node = ut.selectedTds[i]; + _$jscoverage['plugins/table.cmds.js'][577]++; + sumWidth += node.offsetWidth; + _$jscoverage['plugins/table.cmds.js'][578]++; + i += node.colSpan; + _$jscoverage['plugins/table.cmds.js'][579]++; + colsNum += 1; +} + } + _$jscoverage['plugins/table.cmds.js'][582]++; + averageWidth = (Math.ceil((sumWidth / colsNum)) - (tbAttr.tdBorder * 2) - (tbAttr.tdPadding * 2)); + _$jscoverage['plugins/table.cmds.js'][583]++; + return averageWidth; +} + _$jscoverage['plugins/table.cmds.js'][586]++; + function setAverageWidth(averageWidth) { + _$jscoverage['plugins/table.cmds.js'][587]++; + utils.each(domUtils.getElementsByTagName(ut.table, "th"), (function (node) { + _$jscoverage['plugins/table.cmds.js'][588]++; + node.setAttribute("width", ""); +})); + _$jscoverage['plugins/table.cmds.js'][590]++; + var cells = (ut.isFullRow()? domUtils.getElementsByTagName(ut.table, "td"): ut.selectedTds); + _$jscoverage['plugins/table.cmds.js'][592]++; + utils.each(cells, (function (node) { + _$jscoverage['plugins/table.cmds.js'][593]++; + if ((node.colSpan == 1)) { + _$jscoverage['plugins/table.cmds.js'][594]++; + node.setAttribute("width", averageWidth); + } +})); +} + _$jscoverage['plugins/table.cmds.js'][599]++; + if ((ut && ut.selectedTds.length)) { + _$jscoverage['plugins/table.cmds.js'][600]++; + setAverageWidth(getAverageWidth()); + } +})}; + _$jscoverage['plugins/table.cmds.js'][605]++; + UE.commands.averagedistributerow = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][607]++; + var ut = getUETableBySelected(this); + _$jscoverage['plugins/table.cmds.js'][608]++; + if ((! ut)) { + _$jscoverage['plugins/table.cmds.js'][608]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][609]++; + if ((ut.selectedTds && /th/gi.test(ut.selectedTds[0].tagName))) { + _$jscoverage['plugins/table.cmds.js'][609]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][610]++; + return ((ut.isFullRow() || ut.isFullCol())? 0: -1); +}), execCommand: (function (cmd) { + _$jscoverage['plugins/table.cmds.js'][613]++; + var me = this, ut = getUETableBySelected(me); + _$jscoverage['plugins/table.cmds.js'][616]++; + function getAverageHeight() { + _$jscoverage['plugins/table.cmds.js'][617]++; + var averageHeight, rowNum, sumHeight = 0, tb = ut.table, tbAttr = getDefaultValue(me, tb), tdpadding = parseInt(domUtils.getComputedStyle(tb.getElementsByTagName("td")[0], "padding-top")); + _$jscoverage['plugins/table.cmds.js'][622]++; + if (ut.isFullCol()) { + _$jscoverage['plugins/table.cmds.js'][623]++; + var captionArr = domUtils.getElementsByTagName(tb, "caption"), thArr = domUtils.getElementsByTagName(tb, "th"), captionHeight, thHeight; + _$jscoverage['plugins/table.cmds.js'][627]++; + if ((captionArr.length > 0)) { + _$jscoverage['plugins/table.cmds.js'][628]++; + captionHeight = captionArr[0].offsetHeight; + } + _$jscoverage['plugins/table.cmds.js'][630]++; + if ((thArr.length > 0)) { + _$jscoverage['plugins/table.cmds.js'][631]++; + thHeight = thArr[0].offsetHeight; + } + _$jscoverage['plugins/table.cmds.js'][634]++; + sumHeight = (tb.offsetHeight - (captionHeight || 0) - (thHeight || 0)); + _$jscoverage['plugins/table.cmds.js'][635]++; + rowNum = ((thArr.length == 0)? ut.rowsNum: (ut.rowsNum - 1)); + } + else { + _$jscoverage['plugins/table.cmds.js'][637]++; + var begin = ut.cellsRange.beginRowIndex, end = ut.cellsRange.endRowIndex, count = 0, trs = domUtils.getElementsByTagName(tb, "tr"); + _$jscoverage['plugins/table.cmds.js'][641]++; + for (var i = begin; (i <= end); (i++)) { + _$jscoverage['plugins/table.cmds.js'][642]++; + sumHeight += trs[i].offsetHeight; + _$jscoverage['plugins/table.cmds.js'][643]++; + count += 1; +} + _$jscoverage['plugins/table.cmds.js'][645]++; + rowNum = count; + } + _$jscoverage['plugins/table.cmds.js'][648]++; + if ((browser.ie && (browser.version < 9))) { + _$jscoverage['plugins/table.cmds.js'][649]++; + averageHeight = Math.ceil((sumHeight / rowNum)); + } + else { + _$jscoverage['plugins/table.cmds.js'][651]++; + averageHeight = (Math.ceil((sumHeight / rowNum)) - (tbAttr.tdBorder * 2) - (tdpadding * 2)); + } + _$jscoverage['plugins/table.cmds.js'][653]++; + return averageHeight; +} + _$jscoverage['plugins/table.cmds.js'][656]++; + function setAverageHeight(averageHeight) { + _$jscoverage['plugins/table.cmds.js'][657]++; + var cells = (ut.isFullCol()? domUtils.getElementsByTagName(ut.table, "td"): ut.selectedTds); + _$jscoverage['plugins/table.cmds.js'][658]++; + utils.each(cells, (function (node) { + _$jscoverage['plugins/table.cmds.js'][659]++; + if ((node.rowSpan == 1)) { + _$jscoverage['plugins/table.cmds.js'][660]++; + node.setAttribute("height", averageHeight); + } +})); +} + _$jscoverage['plugins/table.cmds.js'][665]++; + if ((ut && ut.selectedTds.length)) { + _$jscoverage['plugins/table.cmds.js'][666]++; + setAverageHeight(getAverageHeight()); + } +})}; + _$jscoverage['plugins/table.cmds.js'][672]++; + UE.commands.cellalignment = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][674]++; + return (getTableItemsByRange(this).table? 0: -1); +}), execCommand: (function (cmd, data) { + _$jscoverage['plugins/table.cmds.js'][677]++; + var me = this, ut = getUETableBySelected(me); + _$jscoverage['plugins/table.cmds.js'][680]++; + if ((! ut)) { + _$jscoverage['plugins/table.cmds.js'][681]++; + var start = me.selection.getStart(), cell = (start && domUtils.findParentByTagName(start, ["td", "th", "caption"], true)); + _$jscoverage['plugins/table.cmds.js'][683]++; + if ((! /caption/gi.test(cell.tagName))) { + _$jscoverage['plugins/table.cmds.js'][684]++; + domUtils.setAttributes(cell, data); + } + else { + _$jscoverage['plugins/table.cmds.js'][686]++; + cell.style.textAlign = data.align; + _$jscoverage['plugins/table.cmds.js'][687]++; + cell.style.verticalAlign = data.vAlign; + } + _$jscoverage['plugins/table.cmds.js'][689]++; + me.selection.getRange().setCursor(true); + } + else { + _$jscoverage['plugins/table.cmds.js'][691]++; + utils.each(ut.selectedTds, (function (cell) { + _$jscoverage['plugins/table.cmds.js'][692]++; + domUtils.setAttributes(cell, data); +})); + } +}), queryCommandValue: (function (cmd) { + _$jscoverage['plugins/table.cmds.js'][702]++; + var activeMenuCell = getTableItemsByRange(this).cell; + _$jscoverage['plugins/table.cmds.js'][704]++; + if ((! activeMenuCell)) { + _$jscoverage['plugins/table.cmds.js'][705]++; + activeMenuCell = getSelectedArr(this)[0]; + } + _$jscoverage['plugins/table.cmds.js'][708]++; + if ((! activeMenuCell)) { + _$jscoverage['plugins/table.cmds.js'][710]++; + return null; + } + else { + _$jscoverage['plugins/table.cmds.js'][715]++; + var cells = UE.UETable.getUETable(activeMenuCell).selectedTds; + _$jscoverage['plugins/table.cmds.js'][717]++; + ((! cells.length) && (cells = activeMenuCell)); + _$jscoverage['plugins/table.cmds.js'][719]++; + return UE.UETable.getTableCellAlignState(cells); + } +})}; + _$jscoverage['plugins/table.cmds.js'][726]++; + UE.commands.tablealignment = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][728]++; + if ((browser.ie && (browser.version < 8))) { + _$jscoverage['plugins/table.cmds.js'][729]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][731]++; + return (getTableItemsByRange(this).table? 0: -1); +}), execCommand: (function (cmd, value) { + _$jscoverage['plugins/table.cmds.js'][734]++; + var me = this, start = me.selection.getStart(), table = (start && domUtils.findParentByTagName(start, ["table"], true)); + _$jscoverage['plugins/table.cmds.js'][738]++; + if (table) { + _$jscoverage['plugins/table.cmds.js'][739]++; + table.setAttribute("align", value); + } +})}; + _$jscoverage['plugins/table.cmds.js'][745]++; + UE.commands.edittable = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][747]++; + return (getTableItemsByRange(this).table? 0: -1); +}), execCommand: (function (cmd, color) { + _$jscoverage['plugins/table.cmds.js'][750]++; + var rng = this.selection.getRange(), table = domUtils.findParentByTagName(rng.startContainer, "table"); + _$jscoverage['plugins/table.cmds.js'][752]++; + if (table) { + _$jscoverage['plugins/table.cmds.js'][753]++; + var arr = domUtils.getElementsByTagName(table, "td").concat(domUtils.getElementsByTagName(table, "th"), domUtils.getElementsByTagName(table, "caption")); + _$jscoverage['plugins/table.cmds.js'][757]++; + utils.each(arr, (function (node) { + _$jscoverage['plugins/table.cmds.js'][758]++; + node.style.borderColor = color; +})); + } +})}; + _$jscoverage['plugins/table.cmds.js'][764]++; + UE.commands.edittd = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][766]++; + return (getTableItemsByRange(this).table? 0: -1); +}), execCommand: (function (cmd, bkColor) { + _$jscoverage['plugins/table.cmds.js'][769]++; + var me = this, ut = getUETableBySelected(me); + _$jscoverage['plugins/table.cmds.js'][772]++; + if ((! ut)) { + _$jscoverage['plugins/table.cmds.js'][773]++; + var start = me.selection.getStart(), cell = (start && domUtils.findParentByTagName(start, ["td", "th", "caption"], true)); + _$jscoverage['plugins/table.cmds.js'][775]++; + if (cell) { + _$jscoverage['plugins/table.cmds.js'][776]++; + cell.style.backgroundColor = bkColor; + } + } + else { + _$jscoverage['plugins/table.cmds.js'][779]++; + utils.each(ut.selectedTds, (function (cell) { + _$jscoverage['plugins/table.cmds.js'][780]++; + cell.style.backgroundColor = bkColor; +})); + } +})}; + _$jscoverage['plugins/table.cmds.js'][785]++; + UE.commands.sorttable = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][787]++; + var me = this, tableItems = getTableItemsByRange(me); + _$jscoverage['plugins/table.cmds.js'][789]++; + if ((! tableItems.cell)) { + _$jscoverage['plugins/table.cmds.js'][789]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][790]++; + var table = tableItems.table, cells = table.getElementsByTagName("td"); + _$jscoverage['plugins/table.cmds.js'][792]++; + for (var i = 0, cell; (cell = cells[(i++)]);) { + _$jscoverage['plugins/table.cmds.js'][793]++; + if (((cell.rowSpan != 1) || (cell.colSpan != 1))) { + _$jscoverage['plugins/table.cmds.js'][793]++; + return -1; + } +} + _$jscoverage['plugins/table.cmds.js'][795]++; + return 0; +}), execCommand: (function (cmd, fn) { + _$jscoverage['plugins/table.cmds.js'][798]++; + var me = this, range = me.selection.getRange(), bk = range.createBookmark(true), tableItems = getTableItemsByRange(me), cell = tableItems.cell, ut = getUETable(tableItems.table), cellInfo = ut.getCellInfo(cell); + _$jscoverage['plugins/table.cmds.js'][805]++; + ut.sortTable(cellInfo.cellIndex, fn); + _$jscoverage['plugins/table.cmds.js'][806]++; + range.moveToBookmark(bk).select(); +})}; + _$jscoverage['plugins/table.cmds.js'][810]++; + UE.commands.enablesort = (UE.commands.disablesort = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][812]++; + return (getTableItemsByRange(this).table? 0: -1); +}), execCommand: (function (cmd) { + _$jscoverage['plugins/table.cmds.js'][815]++; + var table = getTableItemsByRange(this).table; + _$jscoverage['plugins/table.cmds.js'][816]++; + table.setAttribute("data-sort", ((cmd == "enablesort")? "sortEnabled": "sortDisabled")); +})}); + _$jscoverage['plugins/table.cmds.js'][819]++; + UE.commands.settablebackground = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][821]++; + return ((getSelectedArr(this).length > 1)? 0: -1); +}), execCommand: (function (cmd, value) { + _$jscoverage['plugins/table.cmds.js'][824]++; + var table, cells, ut; + _$jscoverage['plugins/table.cmds.js'][825]++; + cells = getSelectedArr(this); + _$jscoverage['plugins/table.cmds.js'][826]++; + ut = getUETable(cells[0]); + _$jscoverage['plugins/table.cmds.js'][827]++; + ut.setBackground(cells, value); +})}; + _$jscoverage['plugins/table.cmds.js'][831]++; + UE.commands.cleartablebackground = {queryCommandState: (function () { + _$jscoverage['plugins/table.cmds.js'][833]++; + var cells = getSelectedArr(this); + _$jscoverage['plugins/table.cmds.js'][834]++; + if ((! cells.length)) { + _$jscoverage['plugins/table.cmds.js'][834]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][835]++; + for (var i = 0, cell; (cell = cells[(i++)]);) { + _$jscoverage['plugins/table.cmds.js'][836]++; + if ((cell.style.backgroundColor !== "")) { + _$jscoverage['plugins/table.cmds.js'][836]++; + return 0; + } +} + _$jscoverage['plugins/table.cmds.js'][838]++; + return -1; +}), execCommand: (function () { + _$jscoverage['plugins/table.cmds.js'][841]++; + var cells = getSelectedArr(this), ut = getUETable(cells[0]); + _$jscoverage['plugins/table.cmds.js'][843]++; + ut.removeBackground(cells); +})}; + _$jscoverage['plugins/table.cmds.js'][847]++; + UE.commands.interlacetable = (UE.commands.uninterlacetable = {queryCommandState: (function (cmd) { + _$jscoverage['plugins/table.cmds.js'][849]++; + var table = getTableItemsByRange(this).table; + _$jscoverage['plugins/table.cmds.js'][850]++; + if ((! table)) { + _$jscoverage['plugins/table.cmds.js'][850]++; + return -1; + } + _$jscoverage['plugins/table.cmds.js'][851]++; + var interlaced = table.getAttribute("interlaced"); + _$jscoverage['plugins/table.cmds.js'][852]++; + if ((cmd == "interlacetable")) { + _$jscoverage['plugins/table.cmds.js'][855]++; + return ((interlaced === "enabled")? -1: 0); + } + else { + _$jscoverage['plugins/table.cmds.js'][857]++; + return (((! interlaced) || (interlaced === "disabled"))? -1: 0); + } +}), execCommand: (function (cmd, classList) { + _$jscoverage['plugins/table.cmds.js'][861]++; + var table = getTableItemsByRange(this).table; + _$jscoverage['plugins/table.cmds.js'][862]++; + if ((cmd == "interlacetable")) { + _$jscoverage['plugins/table.cmds.js'][863]++; + table.setAttribute("interlaced", "enabled"); + _$jscoverage['plugins/table.cmds.js'][864]++; + this.fireEvent("interlacetable", table, classList); + } + else { + _$jscoverage['plugins/table.cmds.js'][866]++; + table.setAttribute("interlaced", "disabled"); + _$jscoverage['plugins/table.cmds.js'][867]++; + this.fireEvent("uninterlacetable", table); + } +})}); + _$jscoverage['plugins/table.cmds.js'][872]++; + function resetTdWidth(table, editor) { + _$jscoverage['plugins/table.cmds.js'][873]++; + var tds = table.getElementsByTagName("td"); + _$jscoverage['plugins/table.cmds.js'][874]++; + utils.each(tds, (function (td) { + _$jscoverage['plugins/table.cmds.js'][875]++; + td.removeAttribute("width"); +})); + _$jscoverage['plugins/table.cmds.js'][877]++; + table.setAttribute("width", getTableWidth(editor, true, getDefaultValue(editor, table))); + _$jscoverage['plugins/table.cmds.js'][878]++; + setTimeout((function () { + _$jscoverage['plugins/table.cmds.js'][879]++; + utils.each(tds, (function (td) { + _$jscoverage['plugins/table.cmds.js'][880]++; + ((td.colSpan == 1) && td.setAttribute("width", (td.offsetWidth + ""))); +})); +}), 0); +} + _$jscoverage['plugins/table.cmds.js'][885]++; + function getTableWidth(editor, needIEHack, defaultValue) { + _$jscoverage['plugins/table.cmds.js'][886]++; + var body = editor.body; + _$jscoverage['plugins/table.cmds.js'][887]++; + return (body.offsetWidth - (needIEHack? (parseInt(domUtils.getComputedStyle(body, "margin-left"), 10) * 2): 0) - (defaultValue.tableBorder * 2) - (editor.options.offsetWidth || 0)); +} + _$jscoverage['plugins/table.cmds.js'][890]++; + function getSelectedArr(editor) { + _$jscoverage['plugins/table.cmds.js'][891]++; + var cell = getTableItemsByRange(editor).cell; + _$jscoverage['plugins/table.cmds.js'][892]++; + if (cell) { + _$jscoverage['plugins/table.cmds.js'][893]++; + var ut = getUETable(cell); + _$jscoverage['plugins/table.cmds.js'][894]++; + return (ut.selectedTds.length? ut.selectedTds: [cell]); + } + else { + _$jscoverage['plugins/table.cmds.js'][896]++; + return []; + } +} +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/table.core.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/table.core.js new file mode 100644 index 000000000..1b675a02d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/table.core.js @@ -0,0 +1,2011 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/table.core.js']) { + _$jscoverage['plugins/table.core.js'] = []; + _$jscoverage['plugins/table.core.js'][13] = 0; + _$jscoverage['plugins/table.core.js'][14] = 0; + _$jscoverage['plugins/table.core.js'][15] = 0; + _$jscoverage['plugins/table.core.js'][16] = 0; + _$jscoverage['plugins/table.core.js'][17] = 0; + _$jscoverage['plugins/table.core.js'][18] = 0; + _$jscoverage['plugins/table.core.js'][19] = 0; + _$jscoverage['plugins/table.core.js'][23] = 0; + _$jscoverage['plugins/table.core.js'][24] = 0; + _$jscoverage['plugins/table.core.js'][25] = 0; + _$jscoverage['plugins/table.core.js'][28] = 0; + _$jscoverage['plugins/table.core.js'][29] = 0; + _$jscoverage['plugins/table.core.js'][30] = 0; + _$jscoverage['plugins/table.core.js'][33] = 0; + _$jscoverage['plugins/table.core.js'][34] = 0; + _$jscoverage['plugins/table.core.js'][35] = 0; + _$jscoverage['plugins/table.core.js'][36] = 0; + _$jscoverage['plugins/table.core.js'][38] = 0; + _$jscoverage['plugins/table.core.js'][39] = 0; + _$jscoverage['plugins/table.core.js'][40] = 0; + _$jscoverage['plugins/table.core.js'][43] = 0; + _$jscoverage['plugins/table.core.js'][45] = 0; + _$jscoverage['plugins/table.core.js'][46] = 0; + _$jscoverage['plugins/table.core.js'][47] = 0; + _$jscoverage['plugins/table.core.js'][56] = 0; + _$jscoverage['plugins/table.core.js'][58] = 0; + _$jscoverage['plugins/table.core.js'][60] = 0; + _$jscoverage['plugins/table.core.js'][65] = 0; + _$jscoverage['plugins/table.core.js'][67] = 0; + _$jscoverage['plugins/table.core.js'][69] = 0; + _$jscoverage['plugins/table.core.js'][71] = 0; + _$jscoverage['plugins/table.core.js'][72] = 0; + _$jscoverage['plugins/table.core.js'][73] = 0; + _$jscoverage['plugins/table.core.js'][74] = 0; + _$jscoverage['plugins/table.core.js'][75] = 0; + _$jscoverage['plugins/table.core.js'][80] = 0; + _$jscoverage['plugins/table.core.js'][84] = 0; + _$jscoverage['plugins/table.core.js'][92] = 0; + _$jscoverage['plugins/table.core.js'][93] = 0; + _$jscoverage['plugins/table.core.js'][96] = 0; + _$jscoverage['plugins/table.core.js'][97] = 0; + _$jscoverage['plugins/table.core.js'][101] = 0; + _$jscoverage['plugins/table.core.js'][106] = 0; + _$jscoverage['plugins/table.core.js'][113] = 0; + _$jscoverage['plugins/table.core.js'][114] = 0; + _$jscoverage['plugins/table.core.js'][115] = 0; + _$jscoverage['plugins/table.core.js'][116] = 0; + _$jscoverage['plugins/table.core.js'][118] = 0; + _$jscoverage['plugins/table.core.js'][121] = 0; + _$jscoverage['plugins/table.core.js'][122] = 0; + _$jscoverage['plugins/table.core.js'][128] = 0; + _$jscoverage['plugins/table.core.js'][129] = 0; + _$jscoverage['plugins/table.core.js'][130] = 0; + _$jscoverage['plugins/table.core.js'][131] = 0; + _$jscoverage['plugins/table.core.js'][132] = 0; + _$jscoverage['plugins/table.core.js'][133] = 0; + _$jscoverage['plugins/table.core.js'][134] = 0; + _$jscoverage['plugins/table.core.js'][135] = 0; + _$jscoverage['plugins/table.core.js'][136] = 0; + _$jscoverage['plugins/table.core.js'][137] = 0; + _$jscoverage['plugins/table.core.js'][138] = 0; + _$jscoverage['plugins/table.core.js'][139] = 0; + _$jscoverage['plugins/table.core.js'][140] = 0; + _$jscoverage['plugins/table.core.js'][146] = 0; + _$jscoverage['plugins/table.core.js'][147] = 0; + _$jscoverage['plugins/table.core.js'][148] = 0; + _$jscoverage['plugins/table.core.js'][149] = 0; + _$jscoverage['plugins/table.core.js'][150] = 0; + _$jscoverage['plugins/table.core.js'][151] = 0; + _$jscoverage['plugins/table.core.js'][152] = 0; + _$jscoverage['plugins/table.core.js'][153] = 0; + _$jscoverage['plugins/table.core.js'][164] = 0; + _$jscoverage['plugins/table.core.js'][165] = 0; + _$jscoverage['plugins/table.core.js'][166] = 0; + _$jscoverage['plugins/table.core.js'][167] = 0; + _$jscoverage['plugins/table.core.js'][168] = 0; + _$jscoverage['plugins/table.core.js'][170] = 0; + _$jscoverage['plugins/table.core.js'][173] = 0; + _$jscoverage['plugins/table.core.js'][174] = 0; + _$jscoverage['plugins/table.core.js'][175] = 0; + _$jscoverage['plugins/table.core.js'][177] = 0; + _$jscoverage['plugins/table.core.js'][178] = 0; + _$jscoverage['plugins/table.core.js'][179] = 0; + _$jscoverage['plugins/table.core.js'][180] = 0; + _$jscoverage['plugins/table.core.js'][181] = 0; + _$jscoverage['plugins/table.core.js'][184] = 0; + _$jscoverage['plugins/table.core.js'][185] = 0; + _$jscoverage['plugins/table.core.js'][187] = 0; + _$jscoverage['plugins/table.core.js'][188] = 0; + _$jscoverage['plugins/table.core.js'][189] = 0; + _$jscoverage['plugins/table.core.js'][190] = 0; + _$jscoverage['plugins/table.core.js'][191] = 0; + _$jscoverage['plugins/table.core.js'][192] = 0; + _$jscoverage['plugins/table.core.js'][193] = 0; + _$jscoverage['plugins/table.core.js'][194] = 0; + _$jscoverage['plugins/table.core.js'][197] = 0; + _$jscoverage['plugins/table.core.js'][199] = 0; + _$jscoverage['plugins/table.core.js'][200] = 0; + _$jscoverage['plugins/table.core.js'][201] = 0; + _$jscoverage['plugins/table.core.js'][202] = 0; + _$jscoverage['plugins/table.core.js'][203] = 0; + _$jscoverage['plugins/table.core.js'][205] = 0; + _$jscoverage['plugins/table.core.js'][207] = 0; + _$jscoverage['plugins/table.core.js'][213] = 0; + _$jscoverage['plugins/table.core.js'][214] = 0; + _$jscoverage['plugins/table.core.js'][215] = 0; + _$jscoverage['plugins/table.core.js'][216] = 0; + _$jscoverage['plugins/table.core.js'][217] = 0; + _$jscoverage['plugins/table.core.js'][218] = 0; + _$jscoverage['plugins/table.core.js'][219] = 0; + _$jscoverage['plugins/table.core.js'][220] = 0; + _$jscoverage['plugins/table.core.js'][221] = 0; + _$jscoverage['plugins/table.core.js'][223] = 0; + _$jscoverage['plugins/table.core.js'][229] = 0; + _$jscoverage['plugins/table.core.js'][230] = 0; + _$jscoverage['plugins/table.core.js'][232] = 0; + _$jscoverage['plugins/table.core.js'][243] = 0; + _$jscoverage['plugins/table.core.js'][244] = 0; + _$jscoverage['plugins/table.core.js'][246] = 0; + _$jscoverage['plugins/table.core.js'][249] = 0; + _$jscoverage['plugins/table.core.js'][251] = 0; + _$jscoverage['plugins/table.core.js'][252] = 0; + _$jscoverage['plugins/table.core.js'][254] = 0; + _$jscoverage['plugins/table.core.js'][256] = 0; + _$jscoverage['plugins/table.core.js'][260] = 0; + _$jscoverage['plugins/table.core.js'][264] = 0; + _$jscoverage['plugins/table.core.js'][265] = 0; + _$jscoverage['plugins/table.core.js'][267] = 0; + _$jscoverage['plugins/table.core.js'][268] = 0; + _$jscoverage['plugins/table.core.js'][269] = 0; + _$jscoverage['plugins/table.core.js'][270] = 0; + _$jscoverage['plugins/table.core.js'][274] = 0; + _$jscoverage['plugins/table.core.js'][283] = 0; + _$jscoverage['plugins/table.core.js'][284] = 0; + _$jscoverage['plugins/table.core.js'][286] = 0; + _$jscoverage['plugins/table.core.js'][289] = 0; + _$jscoverage['plugins/table.core.js'][291] = 0; + _$jscoverage['plugins/table.core.js'][293] = 0; + _$jscoverage['plugins/table.core.js'][294] = 0; + _$jscoverage['plugins/table.core.js'][296] = 0; + _$jscoverage['plugins/table.core.js'][303] = 0; + _$jscoverage['plugins/table.core.js'][304] = 0; + _$jscoverage['plugins/table.core.js'][308] = 0; + _$jscoverage['plugins/table.core.js'][309] = 0; + _$jscoverage['plugins/table.core.js'][310] = 0; + _$jscoverage['plugins/table.core.js'][311] = 0; + _$jscoverage['plugins/table.core.js'][313] = 0; + _$jscoverage['plugins/table.core.js'][314] = 0; + _$jscoverage['plugins/table.core.js'][317] = 0; + _$jscoverage['plugins/table.core.js'][318] = 0; + _$jscoverage['plugins/table.core.js'][320] = 0; + _$jscoverage['plugins/table.core.js'][324] = 0; + _$jscoverage['plugins/table.core.js'][326] = 0; + _$jscoverage['plugins/table.core.js'][330] = 0; + _$jscoverage['plugins/table.core.js'][337] = 0; + _$jscoverage['plugins/table.core.js'][338] = 0; + _$jscoverage['plugins/table.core.js'][340] = 0; + _$jscoverage['plugins/table.core.js'][341] = 0; + _$jscoverage['plugins/table.core.js'][342] = 0; + _$jscoverage['plugins/table.core.js'][343] = 0; + _$jscoverage['plugins/table.core.js'][344] = 0; + _$jscoverage['plugins/table.core.js'][345] = 0; + _$jscoverage['plugins/table.core.js'][346] = 0; + _$jscoverage['plugins/table.core.js'][347] = 0; + _$jscoverage['plugins/table.core.js'][351] = 0; + _$jscoverage['plugins/table.core.js'][353] = 0; + _$jscoverage['plugins/table.core.js'][360] = 0; + _$jscoverage['plugins/table.core.js'][361] = 0; + _$jscoverage['plugins/table.core.js'][362] = 0; + _$jscoverage['plugins/table.core.js'][363] = 0; + _$jscoverage['plugins/table.core.js'][364] = 0; + _$jscoverage['plugins/table.core.js'][368] = 0; + _$jscoverage['plugins/table.core.js'][369] = 0; + _$jscoverage['plugins/table.core.js'][371] = 0; + _$jscoverage['plugins/table.core.js'][372] = 0; + _$jscoverage['plugins/table.core.js'][373] = 0; + _$jscoverage['plugins/table.core.js'][374] = 0; + _$jscoverage['plugins/table.core.js'][377] = 0; + _$jscoverage['plugins/table.core.js'][378] = 0; + _$jscoverage['plugins/table.core.js'][380] = 0; + _$jscoverage['plugins/table.core.js'][381] = 0; + _$jscoverage['plugins/table.core.js'][383] = 0; + _$jscoverage['plugins/table.core.js'][387] = 0; + _$jscoverage['plugins/table.core.js'][388] = 0; + _$jscoverage['plugins/table.core.js'][389] = 0; + _$jscoverage['plugins/table.core.js'][390] = 0; + _$jscoverage['plugins/table.core.js'][402] = 0; + _$jscoverage['plugins/table.core.js'][403] = 0; + _$jscoverage['plugins/table.core.js'][404] = 0; + _$jscoverage['plugins/table.core.js'][405] = 0; + _$jscoverage['plugins/table.core.js'][406] = 0; + _$jscoverage['plugins/table.core.js'][407] = 0; + _$jscoverage['plugins/table.core.js'][408] = 0; + _$jscoverage['plugins/table.core.js'][409] = 0; + _$jscoverage['plugins/table.core.js'][410] = 0; + _$jscoverage['plugins/table.core.js'][411] = 0; + _$jscoverage['plugins/table.core.js'][412] = 0; + _$jscoverage['plugins/table.core.js'][423] = 0; + _$jscoverage['plugins/table.core.js'][425] = 0; + _$jscoverage['plugins/table.core.js'][426] = 0; + _$jscoverage['plugins/table.core.js'][427] = 0; + _$jscoverage['plugins/table.core.js'][430] = 0; + _$jscoverage['plugins/table.core.js'][431] = 0; + _$jscoverage['plugins/table.core.js'][435] = 0; + _$jscoverage['plugins/table.core.js'][436] = 0; + _$jscoverage['plugins/table.core.js'][449] = 0; + _$jscoverage['plugins/table.core.js'][450] = 0; + _$jscoverage['plugins/table.core.js'][454] = 0; + _$jscoverage['plugins/table.core.js'][455] = 0; + _$jscoverage['plugins/table.core.js'][456] = 0; + _$jscoverage['plugins/table.core.js'][457] = 0; + _$jscoverage['plugins/table.core.js'][465] = 0; + _$jscoverage['plugins/table.core.js'][471] = 0; + _$jscoverage['plugins/table.core.js'][472] = 0; + _$jscoverage['plugins/table.core.js'][473] = 0; + _$jscoverage['plugins/table.core.js'][479] = 0; + _$jscoverage['plugins/table.core.js'][480] = 0; + _$jscoverage['plugins/table.core.js'][486] = 0; + _$jscoverage['plugins/table.core.js'][487] = 0; + _$jscoverage['plugins/table.core.js'][488] = 0; + _$jscoverage['plugins/table.core.js'][489] = 0; + _$jscoverage['plugins/table.core.js'][490] = 0; + _$jscoverage['plugins/table.core.js'][491] = 0; + _$jscoverage['plugins/table.core.js'][496] = 0; + _$jscoverage['plugins/table.core.js'][497] = 0; + _$jscoverage['plugins/table.core.js'][498] = 0; + _$jscoverage['plugins/table.core.js'][499] = 0; + _$jscoverage['plugins/table.core.js'][500] = 0; + _$jscoverage['plugins/table.core.js'][501] = 0; + _$jscoverage['plugins/table.core.js'][506] = 0; + _$jscoverage['plugins/table.core.js'][507] = 0; + _$jscoverage['plugins/table.core.js'][508] = 0; + _$jscoverage['plugins/table.core.js'][509] = 0; + _$jscoverage['plugins/table.core.js'][510] = 0; + _$jscoverage['plugins/table.core.js'][511] = 0; + _$jscoverage['plugins/table.core.js'][516] = 0; + _$jscoverage['plugins/table.core.js'][517] = 0; + _$jscoverage['plugins/table.core.js'][518] = 0; + _$jscoverage['plugins/table.core.js'][519] = 0; + _$jscoverage['plugins/table.core.js'][520] = 0; + _$jscoverage['plugins/table.core.js'][521] = 0; + _$jscoverage['plugins/table.core.js'][526] = 0; + _$jscoverage['plugins/table.core.js'][527] = 0; + _$jscoverage['plugins/table.core.js'][530] = 0; + _$jscoverage['plugins/table.core.js'][539] = 0; + _$jscoverage['plugins/table.core.js'][540] = 0; + _$jscoverage['plugins/table.core.js'][542] = 0; + _$jscoverage['plugins/table.core.js'][543] = 0; + _$jscoverage['plugins/table.core.js'][550] = 0; + _$jscoverage['plugins/table.core.js'][552] = 0; + _$jscoverage['plugins/table.core.js'][557] = 0; + _$jscoverage['plugins/table.core.js'][567] = 0; + _$jscoverage['plugins/table.core.js'][568] = 0; + _$jscoverage['plugins/table.core.js'][573] = 0; + _$jscoverage['plugins/table.core.js'][574] = 0; + _$jscoverage['plugins/table.core.js'][575] = 0; + _$jscoverage['plugins/table.core.js'][576] = 0; + _$jscoverage['plugins/table.core.js'][577] = 0; + _$jscoverage['plugins/table.core.js'][579] = 0; + _$jscoverage['plugins/table.core.js'][580] = 0; + _$jscoverage['plugins/table.core.js'][581] = 0; + _$jscoverage['plugins/table.core.js'][582] = 0; + _$jscoverage['plugins/table.core.js'][583] = 0; + _$jscoverage['plugins/table.core.js'][585] = 0; + _$jscoverage['plugins/table.core.js'][588] = 0; + _$jscoverage['plugins/table.core.js'][594] = 0; + _$jscoverage['plugins/table.core.js'][595] = 0; + _$jscoverage['plugins/table.core.js'][596] = 0; + _$jscoverage['plugins/table.core.js'][602] = 0; + _$jscoverage['plugins/table.core.js'][603] = 0; + _$jscoverage['plugins/table.core.js'][604] = 0; + _$jscoverage['plugins/table.core.js'][605] = 0; + _$jscoverage['plugins/table.core.js'][608] = 0; + _$jscoverage['plugins/table.core.js'][609] = 0; + _$jscoverage['plugins/table.core.js'][612] = 0; + _$jscoverage['plugins/table.core.js'][616] = 0; + _$jscoverage['plugins/table.core.js'][625] = 0; + _$jscoverage['plugins/table.core.js'][626] = 0; + _$jscoverage['plugins/table.core.js'][628] = 0; + _$jscoverage['plugins/table.core.js'][631] = 0; + _$jscoverage['plugins/table.core.js'][633] = 0; + _$jscoverage['plugins/table.core.js'][635] = 0; + _$jscoverage['plugins/table.core.js'][636] = 0; + _$jscoverage['plugins/table.core.js'][638] = 0; + _$jscoverage['plugins/table.core.js'][642] = 0; + _$jscoverage['plugins/table.core.js'][643] = 0; + _$jscoverage['plugins/table.core.js'][645] = 0; + _$jscoverage['plugins/table.core.js'][648] = 0; + _$jscoverage['plugins/table.core.js'][650] = 0; + _$jscoverage['plugins/table.core.js'][652] = 0; + _$jscoverage['plugins/table.core.js'][654] = 0; + _$jscoverage['plugins/table.core.js'][656] = 0; + _$jscoverage['plugins/table.core.js'][663] = 0; + _$jscoverage['plugins/table.core.js'][664] = 0; + _$jscoverage['plugins/table.core.js'][665] = 0; + _$jscoverage['plugins/table.core.js'][666] = 0; + _$jscoverage['plugins/table.core.js'][668] = 0; + _$jscoverage['plugins/table.core.js'][669] = 0; + _$jscoverage['plugins/table.core.js'][670] = 0; + _$jscoverage['plugins/table.core.js'][672] = 0; + _$jscoverage['plugins/table.core.js'][673] = 0; + _$jscoverage['plugins/table.core.js'][680] = 0; + _$jscoverage['plugins/table.core.js'][685] = 0; + _$jscoverage['plugins/table.core.js'][687] = 0; + _$jscoverage['plugins/table.core.js'][689] = 0; + _$jscoverage['plugins/table.core.js'][691] = 0; + _$jscoverage['plugins/table.core.js'][692] = 0; + _$jscoverage['plugins/table.core.js'][698] = 0; + _$jscoverage['plugins/table.core.js'][702] = 0; + _$jscoverage['plugins/table.core.js'][703] = 0; + _$jscoverage['plugins/table.core.js'][704] = 0; + _$jscoverage['plugins/table.core.js'][705] = 0; + _$jscoverage['plugins/table.core.js'][706] = 0; + _$jscoverage['plugins/table.core.js'][713] = 0; + _$jscoverage['plugins/table.core.js'][716] = 0; + _$jscoverage['plugins/table.core.js'][717] = 0; + _$jscoverage['plugins/table.core.js'][719] = 0; + _$jscoverage['plugins/table.core.js'][720] = 0; + _$jscoverage['plugins/table.core.js'][724] = 0; + _$jscoverage['plugins/table.core.js'][725] = 0; + _$jscoverage['plugins/table.core.js'][726] = 0; + _$jscoverage['plugins/table.core.js'][727] = 0; + _$jscoverage['plugins/table.core.js'][728] = 0; + _$jscoverage['plugins/table.core.js'][732] = 0; + _$jscoverage['plugins/table.core.js'][733] = 0; + _$jscoverage['plugins/table.core.js'][734] = 0; + _$jscoverage['plugins/table.core.js'][735] = 0; + _$jscoverage['plugins/table.core.js'][736] = 0; + _$jscoverage['plugins/table.core.js'][737] = 0; + _$jscoverage['plugins/table.core.js'][740] = 0; + _$jscoverage['plugins/table.core.js'][741] = 0; + _$jscoverage['plugins/table.core.js'][743] = 0; + _$jscoverage['plugins/table.core.js'][744] = 0; + _$jscoverage['plugins/table.core.js'][745] = 0; + _$jscoverage['plugins/table.core.js'][748] = 0; + _$jscoverage['plugins/table.core.js'][749] = 0; + _$jscoverage['plugins/table.core.js'][750] = 0; + _$jscoverage['plugins/table.core.js'][753] = 0; + _$jscoverage['plugins/table.core.js'][755] = 0; + _$jscoverage['plugins/table.core.js'][761] = 0; + _$jscoverage['plugins/table.core.js'][766] = 0; + _$jscoverage['plugins/table.core.js'][767] = 0; + _$jscoverage['plugins/table.core.js'][768] = 0; + _$jscoverage['plugins/table.core.js'][769] = 0; + _$jscoverage['plugins/table.core.js'][770] = 0; + _$jscoverage['plugins/table.core.js'][771] = 0; + _$jscoverage['plugins/table.core.js'][774] = 0; + _$jscoverage['plugins/table.core.js'][776] = 0; + _$jscoverage['plugins/table.core.js'][777] = 0; + _$jscoverage['plugins/table.core.js'][779] = 0; + _$jscoverage['plugins/table.core.js'][780] = 0; + _$jscoverage['plugins/table.core.js'][781] = 0; + _$jscoverage['plugins/table.core.js'][783] = 0; + _$jscoverage['plugins/table.core.js'][784] = 0; + _$jscoverage['plugins/table.core.js'][785] = 0; + _$jscoverage['plugins/table.core.js'][790] = 0; + _$jscoverage['plugins/table.core.js'][791] = 0; + _$jscoverage['plugins/table.core.js'][798] = 0; + _$jscoverage['plugins/table.core.js'][802] = 0; + _$jscoverage['plugins/table.core.js'][803] = 0; + _$jscoverage['plugins/table.core.js'][805] = 0; + _$jscoverage['plugins/table.core.js'][806] = 0; + _$jscoverage['plugins/table.core.js'][807] = 0; + _$jscoverage['plugins/table.core.js'][808] = 0; + _$jscoverage['plugins/table.core.js'][809] = 0; + _$jscoverage['plugins/table.core.js'][810] = 0; + _$jscoverage['plugins/table.core.js'][811] = 0; + _$jscoverage['plugins/table.core.js'][815] = 0; + _$jscoverage['plugins/table.core.js'][816] = 0; + _$jscoverage['plugins/table.core.js'][818] = 0; + _$jscoverage['plugins/table.core.js'][820] = 0; + _$jscoverage['plugins/table.core.js'][822] = 0; + _$jscoverage['plugins/table.core.js'][826] = 0; + _$jscoverage['plugins/table.core.js'][828] = 0; + _$jscoverage['plugins/table.core.js'][829] = 0; + _$jscoverage['plugins/table.core.js'][830] = 0; + _$jscoverage['plugins/table.core.js'][833] = 0; + _$jscoverage['plugins/table.core.js'][834] = 0; + _$jscoverage['plugins/table.core.js'][835] = 0; + _$jscoverage['plugins/table.core.js'][836] = 0; + _$jscoverage['plugins/table.core.js'][838] = 0; + _$jscoverage['plugins/table.core.js'][839] = 0; + _$jscoverage['plugins/table.core.js'][840] = 0; + _$jscoverage['plugins/table.core.js'][841] = 0; + _$jscoverage['plugins/table.core.js'][843] = 0; + _$jscoverage['plugins/table.core.js'][846] = 0; + _$jscoverage['plugins/table.core.js'][847] = 0; + _$jscoverage['plugins/table.core.js'][849] = 0; + _$jscoverage['plugins/table.core.js'][852] = 0; + _$jscoverage['plugins/table.core.js'][855] = 0; + _$jscoverage['plugins/table.core.js'][860] = 0; + _$jscoverage['plugins/table.core.js'][861] = 0; + _$jscoverage['plugins/table.core.js'][862] = 0; + _$jscoverage['plugins/table.core.js'][863] = 0; + _$jscoverage['plugins/table.core.js'][864] = 0; + _$jscoverage['plugins/table.core.js'][865] = 0; + _$jscoverage['plugins/table.core.js'][866] = 0; + _$jscoverage['plugins/table.core.js'][867] = 0; + _$jscoverage['plugins/table.core.js'][870] = 0; + _$jscoverage['plugins/table.core.js'][871] = 0; + _$jscoverage['plugins/table.core.js'][872] = 0; + _$jscoverage['plugins/table.core.js'][873] = 0; + _$jscoverage['plugins/table.core.js'][874] = 0; + _$jscoverage['plugins/table.core.js'][879] = 0; + _$jscoverage['plugins/table.core.js'][880] = 0; + _$jscoverage['plugins/table.core.js'][881] = 0; + _$jscoverage['plugins/table.core.js'][882] = 0; + _$jscoverage['plugins/table.core.js'][883] = 0; + _$jscoverage['plugins/table.core.js'][884] = 0; + _$jscoverage['plugins/table.core.js'][885] = 0; + _$jscoverage['plugins/table.core.js'][886] = 0; + _$jscoverage['plugins/table.core.js'][887] = 0; + _$jscoverage['plugins/table.core.js'][888] = 0; + _$jscoverage['plugins/table.core.js'][889] = 0; + _$jscoverage['plugins/table.core.js'][891] = 0; + _$jscoverage['plugins/table.core.js'][893] = 0; + _$jscoverage['plugins/table.core.js'][896] = 0; + _$jscoverage['plugins/table.core.js'][897] = 0; + _$jscoverage['plugins/table.core.js'][898] = 0; + _$jscoverage['plugins/table.core.js'][899] = 0; + _$jscoverage['plugins/table.core.js'][900] = 0; + _$jscoverage['plugins/table.core.js'][902] = 0; + _$jscoverage['plugins/table.core.js'][903] = 0; + _$jscoverage['plugins/table.core.js'][905] = 0; + _$jscoverage['plugins/table.core.js'][906] = 0; + _$jscoverage['plugins/table.core.js'][907] = 0; + _$jscoverage['plugins/table.core.js'][908] = 0; + _$jscoverage['plugins/table.core.js'][910] = 0; + _$jscoverage['plugins/table.core.js'][912] = 0; + _$jscoverage['plugins/table.core.js'][916] = 0; + _$jscoverage['plugins/table.core.js'][917] = 0; + _$jscoverage['plugins/table.core.js'][920] = 0; + _$jscoverage['plugins/table.core.js'][922] = 0; + _$jscoverage['plugins/table.core.js'][923] = 0; + _$jscoverage['plugins/table.core.js'][924] = 0; + _$jscoverage['plugins/table.core.js'][926] = 0; + _$jscoverage['plugins/table.core.js'][927] = 0; + _$jscoverage['plugins/table.core.js'][928] = 0; + _$jscoverage['plugins/table.core.js'][932] = 0; + _$jscoverage['plugins/table.core.js'][938] = 0; + _$jscoverage['plugins/table.core.js'][939] = 0; + _$jscoverage['plugins/table.core.js'][943] = 0; + _$jscoverage['plugins/table.core.js'][944] = 0; + _$jscoverage['plugins/table.core.js'][945] = 0; + _$jscoverage['plugins/table.core.js'][946] = 0; + _$jscoverage['plugins/table.core.js'][948] = 0; + _$jscoverage['plugins/table.core.js'][949] = 0; + _$jscoverage['plugins/table.core.js'][951] = 0; + _$jscoverage['plugins/table.core.js'][953] = 0; + _$jscoverage['plugins/table.core.js'][955] = 0; + _$jscoverage['plugins/table.core.js'][956] = 0; + _$jscoverage['plugins/table.core.js'][959] = 0; + _$jscoverage['plugins/table.core.js'][961] = 0; + _$jscoverage['plugins/table.core.js'][962] = 0; + _$jscoverage['plugins/table.core.js'][966] = 0; + _$jscoverage['plugins/table.core.js'][971] = 0; + _$jscoverage['plugins/table.core.js'][972] = 0; + _$jscoverage['plugins/table.core.js'][974] = 0; + _$jscoverage['plugins/table.core.js'][975] = 0; + _$jscoverage['plugins/table.core.js'][976] = 0; + _$jscoverage['plugins/table.core.js'][978] = 0; + _$jscoverage['plugins/table.core.js'][979] = 0; + _$jscoverage['plugins/table.core.js'][980] = 0; + _$jscoverage['plugins/table.core.js'][981] = 0; + _$jscoverage['plugins/table.core.js'][982] = 0; + _$jscoverage['plugins/table.core.js'][983] = 0; + _$jscoverage['plugins/table.core.js'][985] = 0; + _$jscoverage['plugins/table.core.js'][987] = 0; + _$jscoverage['plugins/table.core.js'][988] = 0; + _$jscoverage['plugins/table.core.js'][991] = 0; + _$jscoverage['plugins/table.core.js'][993] = 0; + _$jscoverage['plugins/table.core.js'][994] = 0; + _$jscoverage['plugins/table.core.js'][996] = 0; + _$jscoverage['plugins/table.core.js'][997] = 0; + _$jscoverage['plugins/table.core.js'][999] = 0; + _$jscoverage['plugins/table.core.js'][1002] = 0; + _$jscoverage['plugins/table.core.js'][1009] = 0; + _$jscoverage['plugins/table.core.js'][1010] = 0; + _$jscoverage['plugins/table.core.js'][1011] = 0; + _$jscoverage['plugins/table.core.js'][1013] = 0; + _$jscoverage['plugins/table.core.js'][1014] = 0; + _$jscoverage['plugins/table.core.js'][1015] = 0; + _$jscoverage['plugins/table.core.js'][1017] = 0; + _$jscoverage['plugins/table.core.js'][1018] = 0; + _$jscoverage['plugins/table.core.js'][1019] = 0; + _$jscoverage['plugins/table.core.js'][1020] = 0; + _$jscoverage['plugins/table.core.js'][1021] = 0; + _$jscoverage['plugins/table.core.js'][1022] = 0; + _$jscoverage['plugins/table.core.js'][1023] = 0; + _$jscoverage['plugins/table.core.js'][1026] = 0; + _$jscoverage['plugins/table.core.js'][1027] = 0; + _$jscoverage['plugins/table.core.js'][1028] = 0; + _$jscoverage['plugins/table.core.js'][1029] = 0; + _$jscoverage['plugins/table.core.js'][1030] = 0; + _$jscoverage['plugins/table.core.js'][1031] = 0; + _$jscoverage['plugins/table.core.js'][1032] = 0; + _$jscoverage['plugins/table.core.js'][1034] = 0; + _$jscoverage['plugins/table.core.js'][1036] = 0; + _$jscoverage['plugins/table.core.js'][1037] = 0; + _$jscoverage['plugins/table.core.js'][1040] = 0; + _$jscoverage['plugins/table.core.js'][1041] = 0; + _$jscoverage['plugins/table.core.js'][1042] = 0; + _$jscoverage['plugins/table.core.js'][1043] = 0; + _$jscoverage['plugins/table.core.js'][1047] = 0; + _$jscoverage['plugins/table.core.js'][1048] = 0; + _$jscoverage['plugins/table.core.js'][1049] = 0; + _$jscoverage['plugins/table.core.js'][1052] = 0; + _$jscoverage['plugins/table.core.js'][1053] = 0; + _$jscoverage['plugins/table.core.js'][1054] = 0; + _$jscoverage['plugins/table.core.js'][1056] = 0; + _$jscoverage['plugins/table.core.js'][1057] = 0; + _$jscoverage['plugins/table.core.js'][1058] = 0; + _$jscoverage['plugins/table.core.js'][1059] = 0; + _$jscoverage['plugins/table.core.js'][1060] = 0; + _$jscoverage['plugins/table.core.js'][1063] = 0; + _$jscoverage['plugins/table.core.js'][1067] = 0; + _$jscoverage['plugins/table.core.js'][1071] = 0; + _$jscoverage['plugins/table.core.js'][1074] = 0; + _$jscoverage['plugins/table.core.js'][1076] = 0; + _$jscoverage['plugins/table.core.js'][1079] = 0; + _$jscoverage['plugins/table.core.js'][1084] = 0; + _$jscoverage['plugins/table.core.js'][1085] = 0; + _$jscoverage['plugins/table.core.js'][1087] = 0; + _$jscoverage['plugins/table.core.js'][1088] = 0; + _$jscoverage['plugins/table.core.js'][1090] = 0; + _$jscoverage['plugins/table.core.js'][1091] = 0; + _$jscoverage['plugins/table.core.js'][1093] = 0; + _$jscoverage['plugins/table.core.js'][1094] = 0; + _$jscoverage['plugins/table.core.js'][1098] = 0; + _$jscoverage['plugins/table.core.js'][1099] = 0; + _$jscoverage['plugins/table.core.js'][1100] = 0; + _$jscoverage['plugins/table.core.js'][1101] = 0; + _$jscoverage['plugins/table.core.js'][1103] = 0; + _$jscoverage['plugins/table.core.js'][1104] = 0; + _$jscoverage['plugins/table.core.js'][1106] = 0; + _$jscoverage['plugins/table.core.js'][1109] = 0; + _$jscoverage['plugins/table.core.js'][1110] = 0; + _$jscoverage['plugins/table.core.js'][1111] = 0; + _$jscoverage['plugins/table.core.js'][1113] = 0; + _$jscoverage['plugins/table.core.js'][1114] = 0; + _$jscoverage['plugins/table.core.js'][1115] = 0; + _$jscoverage['plugins/table.core.js'][1117] = 0; + _$jscoverage['plugins/table.core.js'][1121] = 0; + _$jscoverage['plugins/table.core.js'][1122] = 0; + _$jscoverage['plugins/table.core.js'][1123] = 0; + _$jscoverage['plugins/table.core.js'][1125] = 0; + _$jscoverage['plugins/table.core.js'][1126] = 0; + _$jscoverage['plugins/table.core.js'][1130] = 0; + _$jscoverage['plugins/table.core.js'][1134] = 0; + _$jscoverage['plugins/table.core.js'][1136] = 0; + _$jscoverage['plugins/table.core.js'][1137] = 0; + _$jscoverage['plugins/table.core.js'][1138] = 0; + _$jscoverage['plugins/table.core.js'][1143] = 0; + _$jscoverage['plugins/table.core.js'][1144] = 0; + _$jscoverage['plugins/table.core.js'][1150] = 0; +} +_$jscoverage['plugins/table.core.js'].source = ["/*"," * Created with JetBrains WebStorm."," * User: taoqili"," * Date: 13-1-18"," * Time: 上午11:09"," * To change this template use File | Settings | File Templates."," */","/*"," * UE表格操作类"," * @param table"," * @constructor"," */","(function () {"," var UETable = UE.UETable = function (table) {"," this.table = table;"," this.indexTable = [];"," this.selectedTds = [];"," this.cellsRange = {};"," this.update(table);"," };",""," //===以下为静态工具方法==="," UETable.removeSelectedClass = function (cells) {"," utils.each(cells, function (cell) {"," domUtils.removeClasses(cell, \"selectTdClass\");"," })"," };"," UETable.addSelectedClass = function (cells) {"," utils.each(cells, function (cell) {"," domUtils.addClass(cell, \"selectTdClass\");"," })"," };"," UETable.isEmptyBlock = function (node) {"," var reg = new RegExp(domUtils.fillChar, 'g');"," if (node[browser.ie ? 'innerText' : 'textContent'].replace(/^\\s*$/, '').replace(reg, '').length > 0) {"," return 0;"," }"," for (var i in dtd.$isNotEmpty) if (dtd.$isNotEmpty.hasOwnProperty(i)) {"," if (node.getElementsByTagName(i).length) {"," return 0;"," }"," }"," return 1;"," };"," UETable.getWidth = function (cell) {"," if (!cell)return 0;"," return parseInt(domUtils.getComputedStyle(cell, \"width\"), 10);"," };",""," /*"," * 获取单元格或者单元格组的“对齐”状态。 如果当前的检测对象是一个单元格组, 只有在满足所有单元格的 水平和竖直 对齐属性都相同的"," * 条件时才会返回其状态值,否则将返回null; 如果当前只检测了一个单元格, 则直接返回当前单元格的对齐状态;"," * @param table cell or table cells , 支持单个单元格dom对象 或者 单元格dom对象数组"," * @return { align: 'left' || 'right' || 'center', valign: 'top' || 'middle' || 'bottom' } 或者 null"," */"," UETable.getTableCellAlignState = function ( cells ) {",""," !utils.isArray( cells ) && ( cells = [cells] );",""," var result = {},"," status = ['align', 'valign'],"," tempStatus = null,"," isSame = true;//状态是否相同",""," utils.each( cells, function( cellNode ){",""," utils.each( status, function( currentState ){",""," tempStatus = cellNode.getAttribute( currentState );",""," if( !result[ currentState ] && tempStatus ) {"," result[ currentState ] = tempStatus;"," } else if( !result[ currentState ] || ( tempStatus !== result[ currentState ] ) ) {"," isSame = false;"," return false;"," }",""," } );",""," return isSame;",""," });",""," return isSame ? result : null;",""," };",""," /*"," * 根据当前选区获取相关的table信息"," * @return {Object}"," */"," UETable.getTableItemsByRange = function (editor) {"," var start = editor.selection.getStart();",""," //ff下会选中bookmark"," if( start && start.id && start.id.indexOf('_baidu_bookmark_start_') === 0 ) {"," start = start.nextSibling;"," }",""," //在table或者td边缘有可能存在选中tr的情况"," var cell = start && domUtils.findParentByTagName(start, [\"td\", \"th\"], true),"," tr = cell && cell.parentNode,"," caption = start && domUtils.findParentByTagName(start, 'caption', true),"," table = caption ? caption.parentNode : tr && tr.parentNode.parentNode;",""," return {"," cell:cell,"," tr:tr,"," table:table,"," caption:caption"," }"," };"," UETable.getUETableBySelected = function (editor) {"," var table = UETable.getTableItemsByRange(editor).table;"," if (table && table.ueTable && table.ueTable.selectedTds.length) {"," return table.ueTable;"," }"," return null;"," };",""," UETable.getDefaultValue = function (editor, table) {"," var borderMap = {"," thin:'0px',"," medium:'1px',"," thick:'2px'"," },"," tableBorder, tdPadding, tdBorder, tmpValue;"," if (!table) {"," table = editor.document.createElement('table');"," table.insertRow(0).insertCell(0).innerHTML = 'xxx';"," editor.body.appendChild(table);"," var td = table.getElementsByTagName('td')[0];"," tmpValue = domUtils.getComputedStyle(table, 'border-left-width');"," tableBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);"," tmpValue = domUtils.getComputedStyle(td, 'padding-left');"," tdPadding = parseInt(borderMap[tmpValue] || tmpValue, 10);"," tmpValue = domUtils.getComputedStyle(td, 'border-left-width');"," tdBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);"," domUtils.remove(table);"," return {"," tableBorder:tableBorder,"," tdPadding:tdPadding,"," tdBorder:tdBorder"," };"," } else {"," td = table.getElementsByTagName('td')[0];"," tmpValue = domUtils.getComputedStyle(table, 'border-left-width');"," tableBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);"," tmpValue = domUtils.getComputedStyle(td, 'padding-left');"," tdPadding = parseInt(borderMap[tmpValue] || tmpValue, 10);"," tmpValue = domUtils.getComputedStyle(td, 'border-left-width');"," tdBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);"," return {"," tableBorder:tableBorder,"," tdPadding:tdPadding,"," tdBorder:tdBorder"," };"," }"," };"," /*"," * 根据当前点击的td或者table获取索引对象"," * @param tdOrTable"," */"," UETable.getUETable = function (tdOrTable) {"," var tag = tdOrTable.tagName.toLowerCase();"," tdOrTable = (tag == \"td\" || tag == \"th\" || tag == 'caption') ? domUtils.findParentByTagName(tdOrTable, \"table\", true) : tdOrTable;"," if (!tdOrTable.ueTable) {"," tdOrTable.ueTable = new UETable(tdOrTable);"," }"," return tdOrTable.ueTable;"," };",""," UETable.cloneCell = function(cell,ignoreMerge,keepPro){"," if (!cell || utils.isString(cell)) {"," return this.table.ownerDocument.createElement(cell || 'td');"," }"," var flag = domUtils.hasClass(cell, \"selectTdClass\");"," flag && domUtils.removeClasses(cell, \"selectTdClass\");"," var tmpCell = cell.cloneNode(true);"," if (ignoreMerge) {"," tmpCell.rowSpan = tmpCell.colSpan = 1;"," }"," //去掉宽高"," !keepPro && domUtils.removeAttributes(tmpCell,'width height');"," !keepPro && domUtils.removeAttributes(tmpCell,'style');",""," tmpCell.style.borderLeftStyle = \"\";"," tmpCell.style.borderTopStyle = \"\";"," tmpCell.style.borderLeftColor = cell.style.borderRightColor;"," tmpCell.style.borderLeftWidth = cell.style.borderRightWidth;"," tmpCell.style.borderTopColor = cell.style.borderBottomColor;"," tmpCell.style.borderTopWidth = cell.style.borderBottomWidth;"," flag && domUtils.addClass(cell, \"selectTdClass\");"," return tmpCell;"," }",""," UETable.prototype = {"," getMaxRows:function () {"," var rows = this.table.rows, maxLen = 1;"," for (var i = 0, row; row = rows[i]; i++) {"," var currentMax = 1;"," for (var j = 0, cj; cj = row.cells[j++];) {"," currentMax = Math.max(cj.rowSpan || 1, currentMax);"," }"," maxLen = Math.max(currentMax + i, maxLen);"," }"," return maxLen;"," },"," /*"," * 获取当前表格的最大列数"," */"," getMaxCols:function () {"," var rows = this.table.rows, maxLen = 0, cellRows = {};"," for (var i = 0, row; row = rows[i]; i++) {"," var cellsNum = 0;"," for (var j = 0, cj; cj = row.cells[j++];) {"," cellsNum += (cj.colSpan || 1);"," if (cj.rowSpan && cj.rowSpan > 1) {"," for (var k = 1; k < cj.rowSpan; k++) {"," if (!cellRows['row_' + (i + k)]) {"," cellRows['row_' + (i + k)] = (cj.colSpan || 1);"," } else {"," cellRows['row_' + (i + k)]++"," }"," }",""," }"," }"," cellsNum += cellRows['row_' + i] || 0;"," maxLen = Math.max(cellsNum, maxLen);"," }"," return maxLen;"," },"," getCellColIndex:function (cell) {",""," },"," /*"," * 获取当前cell旁边的单元格,"," * @param cell"," * @param right"," */"," getHSideCell:function (cell, right) {"," try {"," var cellInfo = this.getCellInfo(cell),"," previewRowIndex, previewColIndex;"," var len = this.selectedTds.length,"," range = this.cellsRange;"," //首行或者首列没有前置单元格"," if ((!right && (!len ? !cellInfo.colIndex : !range.beginColIndex)) || (right && (!len ? (cellInfo.colIndex == (this.colsNum - 1)) : (range.endColIndex == this.colsNum - 1)))) return null;",""," previewRowIndex = !len ? cellInfo.rowIndex : range.beginRowIndex;"," previewColIndex = !right ? ( !len ? (cellInfo.colIndex < 1 ? 0 : (cellInfo.colIndex - 1)) : range.beginColIndex - 1)"," : ( !len ? cellInfo.colIndex + 1 : range.endColIndex + 1);"," return this.getCell(this.indexTable[previewRowIndex][previewColIndex].rowIndex, this.indexTable[previewRowIndex][previewColIndex].cellIndex);"," } catch (e) {"," showError(e);"," }"," },"," getTabNextCell:function (cell, preRowIndex) {"," var cellInfo = this.getCellInfo(cell),"," rowIndex = preRowIndex || cellInfo.rowIndex,"," colIndex = cellInfo.colIndex + 1 + (cellInfo.colSpan - 1),"," nextCell;"," try {"," nextCell = this.getCell(this.indexTable[rowIndex][colIndex].rowIndex, this.indexTable[rowIndex][colIndex].cellIndex);"," } catch (e) {"," try {"," rowIndex = rowIndex * 1 + 1;"," colIndex = 0;"," nextCell = this.getCell(this.indexTable[rowIndex][colIndex].rowIndex, this.indexTable[rowIndex][colIndex].cellIndex);"," } catch (e) {"," }"," }"," return nextCell;",""," },"," /*"," * 获取视觉上的后置单元格"," * @param cell"," * @param bottom"," */"," getVSideCell:function (cell, bottom, ignoreRange) {"," try {"," var cellInfo = this.getCellInfo(cell),"," nextRowIndex, nextColIndex;"," var len = this.selectedTds.length && !ignoreRange,"," range = this.cellsRange;"," //末行或者末列没有后置单元格"," if ((!bottom && (cellInfo.rowIndex == 0)) || (bottom && (!len ? (cellInfo.rowIndex + cellInfo.rowSpan > this.rowsNum - 1) : (range.endRowIndex == this.rowsNum - 1)))) return null;",""," nextRowIndex = !bottom ? ( !len ? cellInfo.rowIndex - 1 : range.beginRowIndex - 1)"," : ( !len ? (cellInfo.rowIndex + cellInfo.rowSpan) : range.endRowIndex + 1);"," nextColIndex = !len ? cellInfo.colIndex : range.beginColIndex;"," return this.getCell(this.indexTable[nextRowIndex][nextColIndex].rowIndex, this.indexTable[nextRowIndex][nextColIndex].cellIndex);"," } catch (e) {"," showError(e);"," }"," },"," /*"," * 获取相同结束位置的单元格,xOrY指代了是获取x轴相同还是y轴相同"," */"," getSameEndPosCells:function (cell, xOrY) {"," try {"," var flag = (xOrY.toLowerCase() === \"x\"),"," end = domUtils.getXY(cell)[flag ? 'x' : 'y'] + cell[\"offset\" + (flag ? 'Width' : 'Height')],"," rows = this.table.rows,"," cells = null, returns = [];"," for (var i = 0; i < this.rowsNum; i++) {"," cells = rows[i].cells;"," for (var j = 0, tmpCell; tmpCell = cells[j++];) {"," var tmpEnd = domUtils.getXY(tmpCell)[flag ? 'x' : 'y'] + tmpCell[\"offset\" + (flag ? 'Width' : 'Height')];"," //对应行的td已经被上面行rowSpan了"," if (tmpEnd > end && flag) break;"," if (cell == tmpCell || end == tmpEnd) {"," //只获取单一的单元格"," //todo 仅获取单一单元格在特定情况下会造成returns为空,从而影响后续的拖拽实现,修正这个。需考虑性能"," if (tmpCell[flag ? \"colSpan\" : \"rowSpan\"] == 1) {"," returns.push(tmpCell);"," }"," if (flag) break;"," }"," }"," }"," return returns;"," } catch (e) {"," showError(e);"," }"," },"," setCellContent:function (cell, content) {"," cell.innerHTML = content || (browser.ie ? domUtils.fillChar : \"<br />\");"," },"," cloneCell:UETable.cloneCell,"," /*"," * 获取跟当前单元格的右边竖线为左边的所有未合并单元格"," */"," getSameStartPosXCells:function (cell) {"," try {"," var start = domUtils.getXY(cell).x + cell.offsetWidth,"," rows = this.table.rows, cells , returns = [];"," for (var i = 0; i < this.rowsNum; i++) {"," cells = rows[i].cells;"," for (var j = 0, tmpCell; tmpCell = cells[j++];) {"," var tmpStart = domUtils.getXY(tmpCell).x;"," if (tmpStart > start) break;"," if (tmpStart == start && tmpCell.colSpan == 1) {"," returns.push(tmpCell);"," break;"," }"," }"," }"," return returns;"," } catch (e) {"," showError(e);"," }"," },"," /*"," * 更新table对应的索引表"," */"," update:function (table) {"," this.table = table || this.table;"," this.selectedTds = [];"," this.cellsRange = {};"," this.indexTable = [];"," var rows = this.table.rows,"," rowsNum = this.getMaxRows(),"," dNum = rowsNum - rows.length,"," colsNum = this.getMaxCols();"," while (dNum--) {"," this.table.insertRow(rows.length);"," }"," this.rowsNum = rowsNum;"," this.colsNum = colsNum;"," for (var i = 0, len = rows.length; i < len; i++) {"," this.indexTable[i] = new Array(colsNum);"," }"," //填充索引表"," for (var rowIndex = 0, row; row = rows[rowIndex]; rowIndex++) {"," for (var cellIndex = 0, cell, cells = row.cells; cell = cells[cellIndex]; cellIndex++) {"," //修正整行被rowSpan时导致的行数计算错误"," if (cell.rowSpan > rowsNum) {"," cell.rowSpan = rowsNum;"," }"," var colIndex = cellIndex,"," rowSpan = cell.rowSpan || 1,"," colSpan = cell.colSpan || 1;"," //当已经被上一行rowSpan或者被前一列colSpan了,则跳到下一个单元格进行"," while (this.indexTable[rowIndex][colIndex]) colIndex++;"," for (var j = 0; j < rowSpan; j++) {"," for (var k = 0; k < colSpan; k++) {"," this.indexTable[rowIndex + j][colIndex + k] = {"," rowIndex:rowIndex,"," cellIndex:cellIndex,"," colIndex:colIndex,"," rowSpan:rowSpan,"," colSpan:colSpan"," }"," }"," }"," }"," }"," //修复残缺td"," for (j = 0; j < rowsNum; j++) {"," for (k = 0; k < colsNum; k++) {"," if (this.indexTable[j][k] === undefined) {"," row = rows[j];"," cell = row.cells[row.cells.length - 1];"," cell = cell ? cell.cloneNode(true) : this.table.ownerDocument.createElement(\"td\");"," this.setCellContent(cell);"," if (cell.colSpan !== 1)cell.colSpan = 1;"," if (cell.rowSpan !== 1)cell.rowSpan = 1;"," row.appendChild(cell);"," this.indexTable[j][k] = {"," rowIndex:j,"," cellIndex:cell.cellIndex,"," colIndex:k,"," rowSpan:1,"," colSpan:1"," }"," }"," }"," }"," //当框选后删除行或者列后撤销,需要重建选区。"," var tds = domUtils.getElementsByTagName(this.table, \"td\"),"," selectTds = [];"," utils.each(tds, function (td) {"," if (domUtils.hasClass(td, \"selectTdClass\")) {"," selectTds.push(td);"," }"," });"," if (selectTds.length) {"," var start = selectTds[0],"," end = selectTds[selectTds.length - 1],"," startInfo = this.getCellInfo(start),"," endInfo = this.getCellInfo(end);"," this.selectedTds = selectTds;"," this.cellsRange = {"," beginRowIndex:startInfo.rowIndex,"," beginColIndex:startInfo.colIndex,"," endRowIndex:endInfo.rowIndex + endInfo.rowSpan - 1,"," endColIndex:endInfo.colIndex + endInfo.colSpan - 1"," };"," }",""," },"," /*"," * 获取单元格的索引信息"," */"," getCellInfo:function (cell) {"," if (!cell) return;"," var cellIndex = cell.cellIndex,"," rowIndex = cell.parentNode.rowIndex,"," rowInfo = this.indexTable[rowIndex],"," numCols = this.colsNum;"," for (var colIndex = cellIndex; colIndex < numCols; colIndex++) {"," var cellInfo = rowInfo[colIndex];"," if (cellInfo.rowIndex === rowIndex && cellInfo.cellIndex === cellIndex) {"," return cellInfo;"," }"," }"," },"," /*"," * 根据行列号获取单元格"," */"," getCell:function (rowIndex, cellIndex) {"," return rowIndex < this.rowsNum && this.table.rows[rowIndex].cells[cellIndex] || null;"," },"," /*"," * 删除单元格"," */"," deleteCell:function (cell, rowIndex) {"," rowIndex = typeof rowIndex == 'number' ? rowIndex : cell.parentNode.rowIndex;"," var row = this.table.rows[rowIndex];"," row.deleteCell(cell.cellIndex);"," },"," /*"," * 根据始末两个单元格获取被框选的所有单元格范围"," */"," getCellsRange:function (cellA, cellB) {"," function checkRange(beginRowIndex, beginColIndex, endRowIndex, endColIndex) {"," var tmpBeginRowIndex = beginRowIndex,"," tmpBeginColIndex = beginColIndex,"," tmpEndRowIndex = endRowIndex,"," tmpEndColIndex = endColIndex,"," cellInfo, colIndex, rowIndex;"," // 通过indexTable检查是否存在超出TableRange上边界的情况"," if (beginRowIndex > 0) {"," for (colIndex = beginColIndex; colIndex < endColIndex; colIndex++) {"," cellInfo = me.indexTable[beginRowIndex][colIndex];"," rowIndex = cellInfo.rowIndex;"," if (rowIndex < beginRowIndex) {"," tmpBeginRowIndex = Math.min(rowIndex, tmpBeginRowIndex);"," }"," }"," }"," // 通过indexTable检查是否存在超出TableRange右边界的情况"," if (endColIndex < me.colsNum) {"," for (rowIndex = beginRowIndex; rowIndex < endRowIndex; rowIndex++) {"," cellInfo = me.indexTable[rowIndex][endColIndex];"," colIndex = cellInfo.colIndex + cellInfo.colSpan - 1;"," if (colIndex > endColIndex) {"," tmpEndColIndex = Math.max(colIndex, tmpEndColIndex);"," }"," }"," }"," // 检查是否有超出TableRange下边界的情况"," if (endRowIndex < me.rowsNum) {"," for (colIndex = beginColIndex; colIndex < endColIndex; colIndex++) {"," cellInfo = me.indexTable[endRowIndex][colIndex];"," rowIndex = cellInfo.rowIndex + cellInfo.rowSpan - 1;"," if (rowIndex > endRowIndex) {"," tmpEndRowIndex = Math.max(rowIndex, tmpEndRowIndex);"," }"," }"," }"," // 检查是否有超出TableRange左边界的情况"," if (beginColIndex > 0) {"," for (rowIndex = beginRowIndex; rowIndex < endRowIndex; rowIndex++) {"," cellInfo = me.indexTable[rowIndex][beginColIndex];"," colIndex = cellInfo.colIndex;"," if (colIndex < beginColIndex) {"," tmpBeginColIndex = Math.min(cellInfo.colIndex, tmpBeginColIndex);"," }"," }"," }"," //递归调用直至所有完成所有框选单元格的扩展"," if (tmpBeginRowIndex != beginRowIndex || tmpBeginColIndex != beginColIndex || tmpEndRowIndex != endRowIndex || tmpEndColIndex != endColIndex) {"," return checkRange(tmpBeginRowIndex, tmpBeginColIndex, tmpEndRowIndex, tmpEndColIndex);"," } else {"," // 不需要扩展TableRange的情况"," return {"," beginRowIndex:beginRowIndex,"," beginColIndex:beginColIndex,"," endRowIndex:endRowIndex,"," endColIndex:endColIndex"," };"," }"," }",""," try {"," var me = this,"," cellAInfo = me.getCellInfo(cellA);"," if (cellA === cellB) {"," return {"," beginRowIndex:cellAInfo.rowIndex,"," beginColIndex:cellAInfo.colIndex,"," endRowIndex:cellAInfo.rowIndex + cellAInfo.rowSpan - 1,"," endColIndex:cellAInfo.colIndex + cellAInfo.colSpan - 1"," };"," }"," var cellBInfo = me.getCellInfo(cellB);"," // 计算TableRange的四个边"," var beginRowIndex = Math.min(cellAInfo.rowIndex, cellBInfo.rowIndex),"," beginColIndex = Math.min(cellAInfo.colIndex, cellBInfo.colIndex),"," endRowIndex = Math.max(cellAInfo.rowIndex + cellAInfo.rowSpan - 1, cellBInfo.rowIndex + cellBInfo.rowSpan - 1),"," endColIndex = Math.max(cellAInfo.colIndex + cellAInfo.colSpan - 1, cellBInfo.colIndex + cellBInfo.colSpan - 1);",""," return checkRange(beginRowIndex, beginColIndex, endRowIndex, endColIndex);"," } catch (e) {"," //throw e;"," }"," },"," /*"," * 依据cellsRange获取对应的单元格集合"," */"," getCells:function (range) {"," //每次获取cells之前必须先清除上次的选择,否则会对后续获取操作造成影响"," this.clearSelected();"," var beginRowIndex = range.beginRowIndex,"," beginColIndex = range.beginColIndex,"," endRowIndex = range.endRowIndex,"," endColIndex = range.endColIndex,"," cellInfo, rowIndex, colIndex, tdHash = {}, returnTds = [];"," for (var i = beginRowIndex; i <= endRowIndex; i++) {"," for (var j = beginColIndex; j <= endColIndex; j++) {"," cellInfo = this.indexTable[i][j];"," rowIndex = cellInfo.rowIndex;"," colIndex = cellInfo.colIndex;"," // 如果Cells里已经包含了此Cell则跳过"," var key = rowIndex + '|' + colIndex;"," if (tdHash[key]) continue;"," tdHash[key] = 1;"," if (rowIndex < i || colIndex < j || rowIndex + cellInfo.rowSpan - 1 > endRowIndex || colIndex + cellInfo.colSpan - 1 > endColIndex) {"," return null;"," }"," returnTds.push(this.getCell(rowIndex, cellInfo.cellIndex));"," }"," }"," return returnTds;"," },"," /*"," * 清理已经选中的单元格"," */"," clearSelected:function () {"," UETable.removeSelectedClass(this.selectedTds);"," this.selectedTds = [];"," this.cellsRange = {};"," },"," /*"," * 根据range设置已经选中的单元格"," */"," setSelected:function (range) {"," var cells = this.getCells(range);"," UETable.addSelectedClass(cells);"," this.selectedTds = cells;"," this.cellsRange = range;"," },"," isFullRow:function () {"," var range = this.cellsRange;"," return (range.endColIndex - range.beginColIndex + 1) == this.colsNum;"," },"," isFullCol:function () {"," var range = this.cellsRange,"," table = this.table,"," ths = table.getElementsByTagName(\"th\"),"," rows = range.endRowIndex - range.beginRowIndex + 1;"," return !ths.length ? rows == this.rowsNum : rows == this.rowsNum || (rows == this.rowsNum - 1);",""," },"," /*"," * 获取视觉上的前置单元格,默认是左边,top传入时"," * @param cell"," * @param top"," */"," getNextCell:function (cell, bottom, ignoreRange) {"," try {"," var cellInfo = this.getCellInfo(cell),"," nextRowIndex, nextColIndex;"," var len = this.selectedTds.length && !ignoreRange,"," range = this.cellsRange;"," //末行或者末列没有后置单元格"," if ((!bottom && (cellInfo.rowIndex == 0)) || (bottom && (!len ? (cellInfo.rowIndex + cellInfo.rowSpan > this.rowsNum - 1) : (range.endRowIndex == this.rowsNum - 1)))) return null;",""," nextRowIndex = !bottom ? ( !len ? cellInfo.rowIndex - 1 : range.beginRowIndex - 1)"," : ( !len ? (cellInfo.rowIndex + cellInfo.rowSpan) : range.endRowIndex + 1);"," nextColIndex = !len ? cellInfo.colIndex : range.beginColIndex;"," return this.getCell(this.indexTable[nextRowIndex][nextColIndex].rowIndex, this.indexTable[nextRowIndex][nextColIndex].cellIndex);"," } catch (e) {"," showError(e);"," }"," },"," getPreviewCell:function (cell, top) {"," try {"," var cellInfo = this.getCellInfo(cell),"," previewRowIndex, previewColIndex;"," var len = this.selectedTds.length,"," range = this.cellsRange;"," //首行或者首列没有前置单元格"," if ((!top && (!len ? !cellInfo.colIndex : !range.beginColIndex)) || (top && (!len ? (cellInfo.rowIndex > (this.colsNum - 1)) : (range.endColIndex == this.colsNum - 1)))) return null;",""," previewRowIndex = !top ? ( !len ? cellInfo.rowIndex : range.beginRowIndex )"," : ( !len ? (cellInfo.rowIndex < 1 ? 0 : (cellInfo.rowIndex - 1)) : range.beginRowIndex);"," previewColIndex = !top ? ( !len ? (cellInfo.colIndex < 1 ? 0 : (cellInfo.colIndex - 1)) : range.beginColIndex - 1)"," : ( !len ? cellInfo.colIndex : range.endColIndex + 1);"," return this.getCell(this.indexTable[previewRowIndex][previewColIndex].rowIndex, this.indexTable[previewRowIndex][previewColIndex].cellIndex);"," } catch (e) {"," showError(e);"," }"," },"," /*"," * 移动单元格中的内容"," */"," moveContent:function (cellTo, cellFrom) {"," if (UETable.isEmptyBlock(cellFrom)) return;"," if (UETable.isEmptyBlock(cellTo)) {"," cellTo.innerHTML = cellFrom.innerHTML;"," return;"," }"," var child = cellTo.lastChild;"," if (child.nodeType == 3 || !dtd.$block[child.tagName]) {"," cellTo.appendChild(cellTo.ownerDocument.createElement('br'))"," }"," while (child = cellFrom.firstChild) {"," cellTo.appendChild(child);"," }"," },"," /*"," * 向右合并单元格"," */"," mergeRight:function (cell) {"," var cellInfo = this.getCellInfo(cell),"," rightColIndex = cellInfo.colIndex + cellInfo.colSpan,"," rightCellInfo = this.indexTable[cellInfo.rowIndex][rightColIndex],"," rightCell = this.getCell(rightCellInfo.rowIndex, rightCellInfo.cellIndex);"," //合并"," cell.colSpan = cellInfo.colSpan + rightCellInfo.colSpan;"," //被合并的单元格不应存在宽度属性"," cell.removeAttribute(\"width\");"," //移动内容"," this.moveContent(cell, rightCell);"," //删掉被合并的Cell"," this.deleteCell(rightCell, rightCellInfo.rowIndex);"," this.update();"," },"," /*"," * 向下合并单元格"," */"," mergeDown:function (cell) {"," var cellInfo = this.getCellInfo(cell),"," downRowIndex = cellInfo.rowIndex + cellInfo.rowSpan,"," downCellInfo = this.indexTable[downRowIndex][cellInfo.colIndex],"," downCell = this.getCell(downCellInfo.rowIndex, downCellInfo.cellIndex);"," cell.rowSpan = cellInfo.rowSpan + downCellInfo.rowSpan;"," cell.removeAttribute(\"height\");"," this.moveContent(cell, downCell);"," this.deleteCell(downCell, downCellInfo.rowIndex);"," this.update();"," },"," /*"," * 合并整个range中的内容"," */"," mergeRange:function () {"," //由于合并操作可以在任意时刻进行,所以无法通过鼠标位置等信息实时生成range,只能通过缓存实例中的cellsRange对象来访问"," var range = this.cellsRange,"," leftTopCell = this.getCell(range.beginRowIndex, this.indexTable[range.beginRowIndex][range.beginColIndex].cellIndex);",""," if (leftTopCell.tagName == \"TH\" && range.endRowIndex !== range.beginRowIndex) {"," var index = this.indexTable,"," info = this.getCellInfo(leftTopCell);"," leftTopCell = this.getCell(1, index[1][info.colIndex].cellIndex);"," range = this.getCellsRange(leftTopCell, this.getCell(index[this.rowsNum - 1][info.colIndex].rowIndex, index[this.rowsNum - 1][info.colIndex].cellIndex));"," }",""," // 删除剩余的Cells"," var cells = this.getCells(range);"," for(var i= 0,ci;ci=cells[i++];){"," if (ci !== leftTopCell) {"," this.moveContent(leftTopCell, ci);"," this.deleteCell(ci);"," }"," }"," // 修改左上角Cell的rowSpan和colSpan,并调整宽度属性设置"," leftTopCell.rowSpan = range.endRowIndex - range.beginRowIndex + 1;"," leftTopCell.rowSpan > 1 && leftTopCell.removeAttribute(\"height\");"," leftTopCell.colSpan = range.endColIndex - range.beginColIndex + 1;"," leftTopCell.colSpan > 1 && leftTopCell.removeAttribute(\"width\");"," if (leftTopCell.rowSpan == this.rowsNum && leftTopCell.colSpan != 1) {"," leftTopCell.colSpan = 1;"," }",""," if (leftTopCell.colSpan == this.colsNum && leftTopCell.rowSpan != 1) {"," var rowIndex = leftTopCell.parentNode.rowIndex;"," //解决IE下的表格操作问题"," if( this.table.deleteRow ) {"," for (var i = rowIndex+ 1, curIndex=rowIndex+ 1, len=leftTopCell.rowSpan; i < len; i++) {"," this.table.deleteRow(curIndex);"," }"," } else {"," for (var i = 0, len=leftTopCell.rowSpan - 1; i < len; i++) {"," var row = this.table.rows[rowIndex + 1];"," row.parentNode.removeChild(row);"," }"," }"," leftTopCell.rowSpan = 1;"," }"," this.update();"," },"," /*"," * 插入一行单元格"," */"," insertRow:function (rowIndex, sourceCell) {"," var numCols = this.colsNum,"," table = this.table,"," row = table.insertRow(rowIndex), cell,"," width = parseInt((table.offsetWidth - numCols * 20 - numCols - 1) / numCols, 10);"," //首行直接插入,无需考虑部分单元格被rowspan的情况"," if (rowIndex == 0 || rowIndex == this.rowsNum) {"," for (var colIndex = 0; colIndex < numCols; colIndex++) {"," cell = this.cloneCell(sourceCell, true);"," this.setCellContent(cell);"," cell.getAttribute('vAlign') && cell.setAttribute('vAlign', cell.getAttribute('vAlign'));"," row.appendChild(cell);"," }"," } else {"," var infoRow = this.indexTable[rowIndex],"," cellIndex = 0;"," for (colIndex = 0; colIndex < numCols; colIndex++) {"," var cellInfo = infoRow[colIndex];"," //如果存在某个单元格的rowspan穿过待插入行的位置,则修改该单元格的rowspan即可,无需插入单元格"," if (cellInfo.rowIndex < rowIndex) {"," cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);"," cell.rowSpan = cellInfo.rowSpan + 1;"," } else {"," cell = this.cloneCell(sourceCell, true);"," this.setCellContent(cell);"," row.appendChild(cell);"," }"," }"," }"," //框选时插入不触发contentchange,需要手动更新索引。"," this.update();"," return row;"," },"," /*"," * 删除一行单元格"," * @param rowIndex"," */"," deleteRow:function (rowIndex) {"," var row = this.table.rows[rowIndex],"," infoRow = this.indexTable[rowIndex],"," colsNum = this.colsNum,"," count = 0; //处理计数"," for (var colIndex = 0; colIndex < colsNum;) {"," var cellInfo = infoRow[colIndex],"," cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);"," if (cell.rowSpan > 1) {"," if (cellInfo.rowIndex == rowIndex) {"," var clone = cell.cloneNode(true);"," clone.rowSpan = cell.rowSpan - 1;"," clone.innerHTML = \"\";"," cell.rowSpan = 1;"," var nextRowIndex = rowIndex + 1,"," nextRow = this.table.rows[nextRowIndex],"," insertCellIndex,"," preMerged = this.getPreviewMergedCellsNum(nextRowIndex, colIndex) - count;"," if (preMerged < colIndex) {"," insertCellIndex = colIndex - preMerged - 1;"," //nextRow.insertCell(insertCellIndex);"," domUtils.insertAfter(nextRow.cells[insertCellIndex], clone);"," } else {"," if (nextRow.cells.length) nextRow.insertBefore(clone, nextRow.cells[0])"," }"," count += 1;"," //cell.parentNode.removeChild(cell);"," }"," }"," colIndex += cell.colSpan || 1;"," }"," var deleteTds = [], cacheMap = {};"," for (colIndex = 0; colIndex < colsNum; colIndex++) {"," var tmpRowIndex = infoRow[colIndex].rowIndex,"," tmpCellIndex = infoRow[colIndex].cellIndex,"," key = tmpRowIndex + \"_\" + tmpCellIndex;"," if (cacheMap[key])continue;"," cacheMap[key] = 1;"," cell = this.getCell(tmpRowIndex, tmpCellIndex);"," deleteTds.push(cell);"," }"," var mergeTds = [];"," utils.each(deleteTds, function (td) {"," if (td.rowSpan == 1) {"," td.parentNode.removeChild(td);"," } else {"," mergeTds.push(td);"," }"," });"," utils.each(mergeTds, function (td) {"," td.rowSpan--;"," });"," row.parentNode.removeChild(row);"," //浏览器方法本身存在bug,采用自定义方法删除"," //this.table.deleteRow(rowIndex);"," this.update();"," },"," insertCol:function (colIndex, sourceCell, defaultValue) {"," var rowsNum = this.rowsNum,"," rowIndex = 0,"," tableRow, cell,"," backWidth = parseInt((this.table.offsetWidth - (this.colsNum + 1) * 20 - (this.colsNum + 1)) / (this.colsNum + 1), 10);",""," function replaceTdToTh(rowIndex, cell, tableRow) {"," if (rowIndex == 0) {"," var th = cell.nextSibling || cell.previousSibling;"," if (th.tagName == 'TH') {"," th = cell.ownerDocument.createElement(\"th\");"," th.appendChild(cell.firstChild);"," tableRow.insertBefore(th, cell);"," domUtils.remove(cell)"," }"," }else{"," if (cell.tagName == 'TH') {"," var td = cell.ownerDocument.createElement(\"td\");"," td.appendChild(cell.firstChild);"," tableRow.insertBefore(td, cell);"," domUtils.remove(cell)"," }"," }"," }",""," var preCell;"," if (colIndex == 0 || colIndex == this.colsNum) {"," for (; rowIndex < rowsNum; rowIndex++) {"," tableRow = this.table.rows[rowIndex];"," preCell = tableRow.cells[colIndex == 0 ? colIndex : tableRow.cells.length];"," cell = this.cloneCell(sourceCell, true); //tableRow.insertCell(colIndex == 0 ? colIndex : tableRow.cells.length);"," this.setCellContent(cell);"," cell.setAttribute('vAlign', cell.getAttribute('vAlign'));"," preCell && cell.setAttribute('width', preCell.getAttribute('width'));"," if (!colIndex) {"," tableRow.insertBefore(cell, tableRow.cells[0]);"," } else {"," domUtils.insertAfter(tableRow.cells[tableRow.cells.length - 1], cell);"," }"," replaceTdToTh(rowIndex, cell, tableRow)"," }"," } else {"," for (; rowIndex < rowsNum; rowIndex++) {"," var cellInfo = this.indexTable[rowIndex][colIndex];"," if (cellInfo.colIndex < colIndex) {"," cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);"," cell.colSpan = cellInfo.colSpan + 1;"," } else {"," tableRow = this.table.rows[rowIndex];"," preCell = tableRow.cells[cellInfo.cellIndex];",""," cell = this.cloneCell(sourceCell, true);//tableRow.insertCell(cellInfo.cellIndex);"," this.setCellContent(cell);"," cell.setAttribute('vAlign', cell.getAttribute('vAlign'));"," preCell && cell.setAttribute('width', preCell.getAttribute('width'));"," //防止IE下报错"," preCell ? tableRow.insertBefore(cell, preCell) : tableRow.appendChild(cell);"," }"," replaceTdToTh(rowIndex, cell, tableRow);"," }"," }"," //框选时插入不触发contentchange,需要手动更新索引"," this.update();"," this.updateWidth(backWidth, defaultValue || {tdPadding:10, tdBorder:1});"," },"," updateWidth:function (width, defaultValue) {"," var table = this.table,"," tmpWidth = UETable.getWidth(table) - defaultValue.tdPadding * 2 - defaultValue.tdBorder + width;"," if (tmpWidth < table.ownerDocument.body.offsetWidth) {"," table.setAttribute(\"width\", tmpWidth);"," return;"," }"," var tds = domUtils.getElementsByTagName(this.table, \"td\");"," utils.each(tds, function (td) {"," td.setAttribute(\"width\", width);"," })"," },"," deleteCol:function (colIndex) {"," var indexTable = this.indexTable,"," tableRows = this.table.rows,"," backTableWidth = this.table.getAttribute(\"width\"),"," backTdWidth = 0,"," rowsNum = this.rowsNum,"," cacheMap = {};"," for (var rowIndex = 0; rowIndex < rowsNum;) {"," var infoRow = indexTable[rowIndex],"," cellInfo = infoRow[colIndex],"," key = cellInfo.rowIndex + '_' + cellInfo.colIndex;"," // 跳过已经处理过的Cell"," if (cacheMap[key])continue;"," cacheMap[key] = 1;"," var cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);"," if (!backTdWidth) backTdWidth = cell && parseInt(cell.offsetWidth / cell.colSpan, 10).toFixed(0);"," // 如果Cell的colSpan大于1, 就修改colSpan, 否则就删掉这个Cell"," if (cell.colSpan > 1) {"," cell.colSpan--;"," } else {"," tableRows[rowIndex].deleteCell(cellInfo.cellIndex);"," }"," rowIndex += cellInfo.rowSpan || 1;"," }"," this.table.setAttribute(\"width\", backTableWidth - backTdWidth);"," this.update();"," },"," splitToCells:function (cell) {"," var me = this,"," cells = this.splitToRows(cell);"," utils.each(cells, function (cell) {"," me.splitToCols(cell);"," })"," },"," splitToRows:function (cell) {"," var cellInfo = this.getCellInfo(cell),"," rowIndex = cellInfo.rowIndex,"," colIndex = cellInfo.colIndex,"," results = [];"," // 修改Cell的rowSpan"," cell.rowSpan = 1;"," results.push(cell);"," // 补齐单元格"," for (var i = rowIndex, endRow = rowIndex + cellInfo.rowSpan; i < endRow; i++) {"," if (i == rowIndex)continue;"," var tableRow = this.table.rows[i],"," tmpCell = tableRow.insertCell(colIndex - this.getPreviewMergedCellsNum(i, colIndex));"," tmpCell.colSpan = cellInfo.colSpan;"," this.setCellContent(tmpCell);"," tmpCell.setAttribute('vAlign', cell.getAttribute('vAlign'));"," tmpCell.setAttribute('align', cell.getAttribute('align'));"," if (cell.style.cssText) {"," tmpCell.style.cssText = cell.style.cssText;"," }"," results.push(tmpCell);"," }"," this.update();"," return results;"," },"," getPreviewMergedCellsNum:function (rowIndex, colIndex) {"," var indexRow = this.indexTable[rowIndex],"," num = 0;"," for (var i = 0; i < colIndex;) {"," var colSpan = indexRow[i].colSpan,"," tmpRowIndex = indexRow[i].rowIndex;"," num += (colSpan - (tmpRowIndex == rowIndex ? 1 : 0));"," i += colSpan;"," }"," return num;"," },"," splitToCols:function (cell) {"," var backWidth = (cell.offsetWidth / cell.colSpan - 22).toFixed(0),",""," cellInfo = this.getCellInfo(cell),"," rowIndex = cellInfo.rowIndex,"," colIndex = cellInfo.colIndex,"," results = [];"," // 修改Cell的rowSpan"," cell.colSpan = 1;"," cell.setAttribute(\"width\", backWidth);"," results.push(cell);"," // 补齐单元格"," for (var j = colIndex, endCol = colIndex + cellInfo.colSpan; j < endCol; j++) {"," if (j == colIndex)continue;"," var tableRow = this.table.rows[rowIndex],"," tmpCell = tableRow.insertCell(this.indexTable[rowIndex][j].cellIndex + 1);"," tmpCell.rowSpan = cellInfo.rowSpan;"," this.setCellContent(tmpCell);"," tmpCell.setAttribute('vAlign', cell.getAttribute('vAlign'));"," tmpCell.setAttribute('align', cell.getAttribute('align'));"," tmpCell.setAttribute('width', backWidth);"," if (cell.style.cssText) {"," tmpCell.style.cssText = cell.style.cssText;"," }"," //处理th的情况"," if (cell.tagName == 'TH') {"," var th = cell.ownerDocument.createElement('th');"," th.appendChild(tmpCell.firstChild);"," th.setAttribute('vAlign', cell.getAttribute('vAlign'));"," th.rowSpan = tmpCell.rowSpan;"," tableRow.insertBefore(th, tmpCell);"," domUtils.remove(tmpCell);"," }"," results.push(tmpCell);"," }"," this.update();"," return results;"," },"," isLastCell:function (cell, rowsNum, colsNum) {"," rowsNum = rowsNum || this.rowsNum;"," colsNum = colsNum || this.colsNum;"," var cellInfo = this.getCellInfo(cell);"," return ((cellInfo.rowIndex + cellInfo.rowSpan) == rowsNum) &&"," ((cellInfo.colIndex + cellInfo.colSpan) == colsNum);"," },"," getLastCell:function (cells) {"," cells = cells || this.table.getElementsByTagName(\"td\");"," var firstInfo = this.getCellInfo(cells[0]);"," var me = this, last = cells[0],"," tr = last.parentNode,"," cellsNum = 0, cols = 0, rows;"," utils.each(cells, function (cell) {"," if (cell.parentNode == tr)cols += cell.colSpan || 1;"," cellsNum += cell.rowSpan * cell.colSpan || 1;"," });"," rows = cellsNum / cols;"," utils.each(cells, function (cell) {"," if (me.isLastCell(cell, rows, cols)) {"," last = cell;"," return false;"," }"," });"," return last;",""," },"," selectRow:function (rowIndex) {"," var indexRow = this.indexTable[rowIndex],"," start = this.getCell(indexRow[0].rowIndex, indexRow[0].cellIndex),"," end = this.getCell(indexRow[this.colsNum - 1].rowIndex, indexRow[this.colsNum - 1].cellIndex),"," range = this.getCellsRange(start, end);"," this.setSelected(range);"," },"," selectTable:function () {"," var tds = this.table.getElementsByTagName(\"td\"),"," range = this.getCellsRange(tds[0], tds[tds.length - 1]);"," this.setSelected(range);"," },"," sortTable:function (sortByCellIndex, compareFn) {"," var table = this.table,"," rows = table.rows,"," trArray = [],"," flag = rows[0].cells[0].tagName === \"TH\","," lastRowIndex = 0;"," if(this.selectedTds.length){"," var range = this.cellsRange,"," len = range.endRowIndex + 1;"," for (var i = range.beginRowIndex; i < len; i++) {"," trArray[i] = rows[i];"," }"," trArray.splice(0,range.beginRowIndex);"," lastRowIndex = (range.endRowIndex +1) === this.rowsNum ? 0 : range.endRowIndex +1;"," }else{"," for (var i = 0,len = rows.length; i < len; i++) {"," trArray[i] = rows[i];"," }"," }"," //th不参与排序"," flag && trArray.splice(0, 1);"," trArray = utils.sort(trArray,function (tr1, tr2) {"," var txt = function(node){"," return node.innerText||node.textContent;"," };"," return compareFn ? (typeof compareFn === \"number\" ? compareFn : compareFn.call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex])) : function () {"," var value1 = txt(tr1.cells[sortByCellIndex]),"," value2 = txt(tr2.cells[sortByCellIndex]);"," return value1.localeCompare(value2);"," }();"," });"," var fragment = table.ownerDocument.createDocumentFragment();"," for (var j = 0, len = trArray.length; j < len; j++) {"," fragment.appendChild(trArray[j]);"," }"," var tbody = table.getElementsByTagName(\"tbody\")[0];"," if(!lastRowIndex){"," tbody.appendChild(fragment);"," }else{"," tbody.insertBefore(fragment,rows[lastRowIndex- range.endRowIndex + range.beginRowIndex - 1])"," }"," },"," setBackground:function (cells, value) {"," if (typeof value === \"string\") {"," utils.each(cells, function (cell) {"," cell.style.backgroundColor = value;"," })"," } else if (typeof value === \"object\") {"," value = utils.extend({"," repeat:true,"," colorList:[\"#ddd\", \"#fff\"]"," }, value);"," var rowIndex = this.getCellInfo(cells[0]).rowIndex,"," count = 0,"," colors = value.colorList,"," getColor = function (list, index, repeat) {"," return list[index] ? list[index] : repeat ? list[index % list.length] : \"\";"," };"," for (var i = 0, cell; cell = cells[i++];) {"," var cellInfo = this.getCellInfo(cell);"," cell.style.backgroundColor = getColor(colors, ((rowIndex + count) == cellInfo.rowIndex) ? count : ++count, value.repeat);"," }"," }"," },"," removeBackground:function (cells) {"," utils.each(cells, function (cell) {"," cell.style.backgroundColor = \"\";"," })"," }","",""," };"," function showError(e) {"," }","})();"]; +_$jscoverage['plugins/table.core.js'][13]++; +(function () { + _$jscoverage['plugins/table.core.js'][14]++; + var UETable = (UE.UETable = (function (table) { + _$jscoverage['plugins/table.core.js'][15]++; + this.table = table; + _$jscoverage['plugins/table.core.js'][16]++; + this.indexTable = []; + _$jscoverage['plugins/table.core.js'][17]++; + this.selectedTds = []; + _$jscoverage['plugins/table.core.js'][18]++; + this.cellsRange = {}; + _$jscoverage['plugins/table.core.js'][19]++; + this.update(table); +})); + _$jscoverage['plugins/table.core.js'][23]++; + UETable.removeSelectedClass = (function (cells) { + _$jscoverage['plugins/table.core.js'][24]++; + utils.each(cells, (function (cell) { + _$jscoverage['plugins/table.core.js'][25]++; + domUtils.removeClasses(cell, "selectTdClass"); +})); +}); + _$jscoverage['plugins/table.core.js'][28]++; + UETable.addSelectedClass = (function (cells) { + _$jscoverage['plugins/table.core.js'][29]++; + utils.each(cells, (function (cell) { + _$jscoverage['plugins/table.core.js'][30]++; + domUtils.addClass(cell, "selectTdClass"); +})); +}); + _$jscoverage['plugins/table.core.js'][33]++; + UETable.isEmptyBlock = (function (node) { + _$jscoverage['plugins/table.core.js'][34]++; + var reg = new RegExp(domUtils.fillChar, "g"); + _$jscoverage['plugins/table.core.js'][35]++; + if ((node[(browser.ie? "innerText": "textContent")].replace(/^\s*$/, "").replace(reg, "").length > 0)) { + _$jscoverage['plugins/table.core.js'][36]++; + return 0; + } + _$jscoverage['plugins/table.core.js'][38]++; + for (var i in dtd.$isNotEmpty) { + _$jscoverage['plugins/table.core.js'][38]++; + if (dtd.$isNotEmpty.hasOwnProperty(i)) { + _$jscoverage['plugins/table.core.js'][39]++; + if (node.getElementsByTagName(i).length) { + _$jscoverage['plugins/table.core.js'][40]++; + return 0; + } + } +} + _$jscoverage['plugins/table.core.js'][43]++; + return 1; +}); + _$jscoverage['plugins/table.core.js'][45]++; + UETable.getWidth = (function (cell) { + _$jscoverage['plugins/table.core.js'][46]++; + if ((! cell)) { + _$jscoverage['plugins/table.core.js'][46]++; + return 0; + } + _$jscoverage['plugins/table.core.js'][47]++; + return parseInt(domUtils.getComputedStyle(cell, "width"), 10); +}); + _$jscoverage['plugins/table.core.js'][56]++; + UETable.getTableCellAlignState = (function (cells) { + _$jscoverage['plugins/table.core.js'][58]++; + ((! utils.isArray(cells)) && (cells = [cells])); + _$jscoverage['plugins/table.core.js'][60]++; + var result = {}, status = ["align", "valign"], tempStatus = null, isSame = true; + _$jscoverage['plugins/table.core.js'][65]++; + utils.each(cells, (function (cellNode) { + _$jscoverage['plugins/table.core.js'][67]++; + utils.each(status, (function (currentState) { + _$jscoverage['plugins/table.core.js'][69]++; + tempStatus = cellNode.getAttribute(currentState); + _$jscoverage['plugins/table.core.js'][71]++; + if (((! result[currentState]) && tempStatus)) { + _$jscoverage['plugins/table.core.js'][72]++; + result[currentState] = tempStatus; + } + else { + _$jscoverage['plugins/table.core.js'][73]++; + if (((! result[currentState]) || (tempStatus !== result[currentState]))) { + _$jscoverage['plugins/table.core.js'][74]++; + isSame = false; + _$jscoverage['plugins/table.core.js'][75]++; + return false; + } + } +})); + _$jscoverage['plugins/table.core.js'][80]++; + return isSame; +})); + _$jscoverage['plugins/table.core.js'][84]++; + return (isSame? result: null); +}); + _$jscoverage['plugins/table.core.js'][92]++; + UETable.getTableItemsByRange = (function (editor) { + _$jscoverage['plugins/table.core.js'][93]++; + var start = editor.selection.getStart(); + _$jscoverage['plugins/table.core.js'][96]++; + if ((start && start.id && (start.id.indexOf("_baidu_bookmark_start_") === 0))) { + _$jscoverage['plugins/table.core.js'][97]++; + start = start.nextSibling; + } + _$jscoverage['plugins/table.core.js'][101]++; + var cell = (start && domUtils.findParentByTagName(start, ["td", "th"], true)), tr = (cell && cell.parentNode), caption = (start && domUtils.findParentByTagName(start, "caption", true)), table = (caption? caption.parentNode: (tr && tr.parentNode.parentNode)); + _$jscoverage['plugins/table.core.js'][106]++; + return ({cell: cell, tr: tr, table: table, caption: caption}); +}); + _$jscoverage['plugins/table.core.js'][113]++; + UETable.getUETableBySelected = (function (editor) { + _$jscoverage['plugins/table.core.js'][114]++; + var table = UETable.getTableItemsByRange(editor).table; + _$jscoverage['plugins/table.core.js'][115]++; + if ((table && table.ueTable && table.ueTable.selectedTds.length)) { + _$jscoverage['plugins/table.core.js'][116]++; + return table.ueTable; + } + _$jscoverage['plugins/table.core.js'][118]++; + return null; +}); + _$jscoverage['plugins/table.core.js'][121]++; + UETable.getDefaultValue = (function (editor, table) { + _$jscoverage['plugins/table.core.js'][122]++; + var borderMap = {thin: "0px", medium: "1px", thick: "2px"}, tableBorder, tdPadding, tdBorder, tmpValue; + _$jscoverage['plugins/table.core.js'][128]++; + if ((! table)) { + _$jscoverage['plugins/table.core.js'][129]++; + table = editor.document.createElement("table"); + _$jscoverage['plugins/table.core.js'][130]++; + table.insertRow(0).insertCell(0).innerHTML = "xxx"; + _$jscoverage['plugins/table.core.js'][131]++; + editor.body.appendChild(table); + _$jscoverage['plugins/table.core.js'][132]++; + var td = table.getElementsByTagName("td")[0]; + _$jscoverage['plugins/table.core.js'][133]++; + tmpValue = domUtils.getComputedStyle(table, "border-left-width"); + _$jscoverage['plugins/table.core.js'][134]++; + tableBorder = parseInt((borderMap[tmpValue] || tmpValue), 10); + _$jscoverage['plugins/table.core.js'][135]++; + tmpValue = domUtils.getComputedStyle(td, "padding-left"); + _$jscoverage['plugins/table.core.js'][136]++; + tdPadding = parseInt((borderMap[tmpValue] || tmpValue), 10); + _$jscoverage['plugins/table.core.js'][137]++; + tmpValue = domUtils.getComputedStyle(td, "border-left-width"); + _$jscoverage['plugins/table.core.js'][138]++; + tdBorder = parseInt((borderMap[tmpValue] || tmpValue), 10); + _$jscoverage['plugins/table.core.js'][139]++; + domUtils.remove(table); + _$jscoverage['plugins/table.core.js'][140]++; + return ({tableBorder: tableBorder, tdPadding: tdPadding, tdBorder: tdBorder}); + } + else { + _$jscoverage['plugins/table.core.js'][146]++; + td = table.getElementsByTagName("td")[0]; + _$jscoverage['plugins/table.core.js'][147]++; + tmpValue = domUtils.getComputedStyle(table, "border-left-width"); + _$jscoverage['plugins/table.core.js'][148]++; + tableBorder = parseInt((borderMap[tmpValue] || tmpValue), 10); + _$jscoverage['plugins/table.core.js'][149]++; + tmpValue = domUtils.getComputedStyle(td, "padding-left"); + _$jscoverage['plugins/table.core.js'][150]++; + tdPadding = parseInt((borderMap[tmpValue] || tmpValue), 10); + _$jscoverage['plugins/table.core.js'][151]++; + tmpValue = domUtils.getComputedStyle(td, "border-left-width"); + _$jscoverage['plugins/table.core.js'][152]++; + tdBorder = parseInt((borderMap[tmpValue] || tmpValue), 10); + _$jscoverage['plugins/table.core.js'][153]++; + return ({tableBorder: tableBorder, tdPadding: tdPadding, tdBorder: tdBorder}); + } +}); + _$jscoverage['plugins/table.core.js'][164]++; + UETable.getUETable = (function (tdOrTable) { + _$jscoverage['plugins/table.core.js'][165]++; + var tag = tdOrTable.tagName.toLowerCase(); + _$jscoverage['plugins/table.core.js'][166]++; + tdOrTable = (((tag == "td") || (tag == "th") || (tag == "caption"))? domUtils.findParentByTagName(tdOrTable, "table", true): tdOrTable); + _$jscoverage['plugins/table.core.js'][167]++; + if ((! tdOrTable.ueTable)) { + _$jscoverage['plugins/table.core.js'][168]++; + tdOrTable.ueTable = new UETable(tdOrTable); + } + _$jscoverage['plugins/table.core.js'][170]++; + return tdOrTable.ueTable; +}); + _$jscoverage['plugins/table.core.js'][173]++; + UETable.cloneCell = (function (cell, ignoreMerge, keepPro) { + _$jscoverage['plugins/table.core.js'][174]++; + if (((! cell) || utils.isString(cell))) { + _$jscoverage['plugins/table.core.js'][175]++; + return this.table.ownerDocument.createElement((cell || "td")); + } + _$jscoverage['plugins/table.core.js'][177]++; + var flag = domUtils.hasClass(cell, "selectTdClass"); + _$jscoverage['plugins/table.core.js'][178]++; + (flag && domUtils.removeClasses(cell, "selectTdClass")); + _$jscoverage['plugins/table.core.js'][179]++; + var tmpCell = cell.cloneNode(true); + _$jscoverage['plugins/table.core.js'][180]++; + if (ignoreMerge) { + _$jscoverage['plugins/table.core.js'][181]++; + tmpCell.rowSpan = (tmpCell.colSpan = 1); + } + _$jscoverage['plugins/table.core.js'][184]++; + ((! keepPro) && domUtils.removeAttributes(tmpCell, "width height")); + _$jscoverage['plugins/table.core.js'][185]++; + ((! keepPro) && domUtils.removeAttributes(tmpCell, "style")); + _$jscoverage['plugins/table.core.js'][187]++; + tmpCell.style.borderLeftStyle = ""; + _$jscoverage['plugins/table.core.js'][188]++; + tmpCell.style.borderTopStyle = ""; + _$jscoverage['plugins/table.core.js'][189]++; + tmpCell.style.borderLeftColor = cell.style.borderRightColor; + _$jscoverage['plugins/table.core.js'][190]++; + tmpCell.style.borderLeftWidth = cell.style.borderRightWidth; + _$jscoverage['plugins/table.core.js'][191]++; + tmpCell.style.borderTopColor = cell.style.borderBottomColor; + _$jscoverage['plugins/table.core.js'][192]++; + tmpCell.style.borderTopWidth = cell.style.borderBottomWidth; + _$jscoverage['plugins/table.core.js'][193]++; + (flag && domUtils.addClass(cell, "selectTdClass")); + _$jscoverage['plugins/table.core.js'][194]++; + return tmpCell; +}); + _$jscoverage['plugins/table.core.js'][197]++; + UETable.prototype = {getMaxRows: (function () { + _$jscoverage['plugins/table.core.js'][199]++; + var rows = this.table.rows, maxLen = 1; + _$jscoverage['plugins/table.core.js'][200]++; + for (var i = 0, row; (row = rows[i]); (i++)) { + _$jscoverage['plugins/table.core.js'][201]++; + var currentMax = 1; + _$jscoverage['plugins/table.core.js'][202]++; + for (var j = 0, cj; (cj = row.cells[(j++)]);) { + _$jscoverage['plugins/table.core.js'][203]++; + currentMax = Math.max((cj.rowSpan || 1), currentMax); +} + _$jscoverage['plugins/table.core.js'][205]++; + maxLen = Math.max((currentMax + i), maxLen); +} + _$jscoverage['plugins/table.core.js'][207]++; + return maxLen; +}), getMaxCols: (function () { + _$jscoverage['plugins/table.core.js'][213]++; + var rows = this.table.rows, maxLen = 0, cellRows = {}; + _$jscoverage['plugins/table.core.js'][214]++; + for (var i = 0, row; (row = rows[i]); (i++)) { + _$jscoverage['plugins/table.core.js'][215]++; + var cellsNum = 0; + _$jscoverage['plugins/table.core.js'][216]++; + for (var j = 0, cj; (cj = row.cells[(j++)]);) { + _$jscoverage['plugins/table.core.js'][217]++; + cellsNum += (cj.colSpan || 1); + _$jscoverage['plugins/table.core.js'][218]++; + if ((cj.rowSpan && (cj.rowSpan > 1))) { + _$jscoverage['plugins/table.core.js'][219]++; + for (var k = 1; (k < cj.rowSpan); (k++)) { + _$jscoverage['plugins/table.core.js'][220]++; + if ((! cellRows[("row_" + (i + k))])) { + _$jscoverage['plugins/table.core.js'][221]++; + cellRows[("row_" + (i + k))] = (cj.colSpan || 1); + } + else { + _$jscoverage['plugins/table.core.js'][223]++; + (cellRows[("row_" + (i + k))]++); + } +} + } +} + _$jscoverage['plugins/table.core.js'][229]++; + cellsNum += (cellRows[("row_" + i)] || 0); + _$jscoverage['plugins/table.core.js'][230]++; + maxLen = Math.max(cellsNum, maxLen); +} + _$jscoverage['plugins/table.core.js'][232]++; + return maxLen; +}), getCellColIndex: (function (cell) { +}), getHSideCell: (function (cell, right) { + _$jscoverage['plugins/table.core.js'][243]++; + try { + _$jscoverage['plugins/table.core.js'][244]++; + var cellInfo = this.getCellInfo(cell), previewRowIndex, previewColIndex; + _$jscoverage['plugins/table.core.js'][246]++; + var len = this.selectedTds.length, range = this.cellsRange; + _$jscoverage['plugins/table.core.js'][249]++; + if ((((! right) && ((! len)? (! cellInfo.colIndex): (! range.beginColIndex))) || (right && ((! len)? (cellInfo.colIndex == (this.colsNum - 1)): (range.endColIndex == (this.colsNum - 1)))))) { + _$jscoverage['plugins/table.core.js'][249]++; + return null; + } + _$jscoverage['plugins/table.core.js'][251]++; + previewRowIndex = ((! len)? cellInfo.rowIndex: range.beginRowIndex); + _$jscoverage['plugins/table.core.js'][252]++; + previewColIndex = ((! right)? ((! len)? ((cellInfo.colIndex < 1)? 0: (cellInfo.colIndex - 1)): (range.beginColIndex - 1)): ((! len)? (cellInfo.colIndex + 1): (range.endColIndex + 1))); + _$jscoverage['plugins/table.core.js'][254]++; + return this.getCell(this.indexTable[previewRowIndex][previewColIndex].rowIndex, this.indexTable[previewRowIndex][previewColIndex].cellIndex); + } + catch (e) { + _$jscoverage['plugins/table.core.js'][256]++; + showError(e); + } +}), getTabNextCell: (function (cell, preRowIndex) { + _$jscoverage['plugins/table.core.js'][260]++; + var cellInfo = this.getCellInfo(cell), rowIndex = (preRowIndex || cellInfo.rowIndex), colIndex = (cellInfo.colIndex + 1 + (cellInfo.colSpan - 1)), nextCell; + _$jscoverage['plugins/table.core.js'][264]++; + try { + _$jscoverage['plugins/table.core.js'][265]++; + nextCell = this.getCell(this.indexTable[rowIndex][colIndex].rowIndex, this.indexTable[rowIndex][colIndex].cellIndex); + } + catch (e) { + _$jscoverage['plugins/table.core.js'][267]++; + try { + _$jscoverage['plugins/table.core.js'][268]++; + rowIndex = ((rowIndex * 1) + 1); + _$jscoverage['plugins/table.core.js'][269]++; + colIndex = 0; + _$jscoverage['plugins/table.core.js'][270]++; + nextCell = this.getCell(this.indexTable[rowIndex][colIndex].rowIndex, this.indexTable[rowIndex][colIndex].cellIndex); + } + catch (e) { + } + } + _$jscoverage['plugins/table.core.js'][274]++; + return nextCell; +}), getVSideCell: (function (cell, bottom, ignoreRange) { + _$jscoverage['plugins/table.core.js'][283]++; + try { + _$jscoverage['plugins/table.core.js'][284]++; + var cellInfo = this.getCellInfo(cell), nextRowIndex, nextColIndex; + _$jscoverage['plugins/table.core.js'][286]++; + var len = (this.selectedTds.length && (! ignoreRange)), range = this.cellsRange; + _$jscoverage['plugins/table.core.js'][289]++; + if ((((! bottom) && (cellInfo.rowIndex == 0)) || (bottom && ((! len)? ((cellInfo.rowIndex + cellInfo.rowSpan) > (this.rowsNum - 1)): (range.endRowIndex == (this.rowsNum - 1)))))) { + _$jscoverage['plugins/table.core.js'][289]++; + return null; + } + _$jscoverage['plugins/table.core.js'][291]++; + nextRowIndex = ((! bottom)? ((! len)? (cellInfo.rowIndex - 1): (range.beginRowIndex - 1)): ((! len)? (cellInfo.rowIndex + cellInfo.rowSpan): (range.endRowIndex + 1))); + _$jscoverage['plugins/table.core.js'][293]++; + nextColIndex = ((! len)? cellInfo.colIndex: range.beginColIndex); + _$jscoverage['plugins/table.core.js'][294]++; + return this.getCell(this.indexTable[nextRowIndex][nextColIndex].rowIndex, this.indexTable[nextRowIndex][nextColIndex].cellIndex); + } + catch (e) { + _$jscoverage['plugins/table.core.js'][296]++; + showError(e); + } +}), getSameEndPosCells: (function (cell, xOrY) { + _$jscoverage['plugins/table.core.js'][303]++; + try { + _$jscoverage['plugins/table.core.js'][304]++; + var flag = (xOrY.toLowerCase() === "x"), end = (domUtils.getXY(cell)[(flag? "x": "y")] + cell[("offset" + (flag? "Width": "Height"))]), rows = this.table.rows, cells = null, returns = []; + _$jscoverage['plugins/table.core.js'][308]++; + for (var i = 0; (i < this.rowsNum); (i++)) { + _$jscoverage['plugins/table.core.js'][309]++; + cells = rows[i].cells; + _$jscoverage['plugins/table.core.js'][310]++; + for (var j = 0, tmpCell; (tmpCell = cells[(j++)]);) { + _$jscoverage['plugins/table.core.js'][311]++; + var tmpEnd = (domUtils.getXY(tmpCell)[(flag? "x": "y")] + tmpCell[("offset" + (flag? "Width": "Height"))]); + _$jscoverage['plugins/table.core.js'][313]++; + if (((tmpEnd > end) && flag)) { + _$jscoverage['plugins/table.core.js'][313]++; + break; + } + _$jscoverage['plugins/table.core.js'][314]++; + if (((cell == tmpCell) || (end == tmpEnd))) { + _$jscoverage['plugins/table.core.js'][317]++; + if ((tmpCell[(flag? "colSpan": "rowSpan")] == 1)) { + _$jscoverage['plugins/table.core.js'][318]++; + returns.push(tmpCell); + } + _$jscoverage['plugins/table.core.js'][320]++; + if (flag) { + _$jscoverage['plugins/table.core.js'][320]++; + break; + } + } +} +} + _$jscoverage['plugins/table.core.js'][324]++; + return returns; + } + catch (e) { + _$jscoverage['plugins/table.core.js'][326]++; + showError(e); + } +}), setCellContent: (function (cell, content) { + _$jscoverage['plugins/table.core.js'][330]++; + cell.innerHTML = (content || (browser.ie? domUtils.fillChar: "
    ")); +}), cloneCell: UETable.cloneCell, getSameStartPosXCells: (function (cell) { + _$jscoverage['plugins/table.core.js'][337]++; + try { + _$jscoverage['plugins/table.core.js'][338]++; + var start = (domUtils.getXY(cell).x + cell.offsetWidth), rows = this.table.rows, cells, returns = []; + _$jscoverage['plugins/table.core.js'][340]++; + for (var i = 0; (i < this.rowsNum); (i++)) { + _$jscoverage['plugins/table.core.js'][341]++; + cells = rows[i].cells; + _$jscoverage['plugins/table.core.js'][342]++; + for (var j = 0, tmpCell; (tmpCell = cells[(j++)]);) { + _$jscoverage['plugins/table.core.js'][343]++; + var tmpStart = domUtils.getXY(tmpCell).x; + _$jscoverage['plugins/table.core.js'][344]++; + if ((tmpStart > start)) { + _$jscoverage['plugins/table.core.js'][344]++; + break; + } + _$jscoverage['plugins/table.core.js'][345]++; + if (((tmpStart == start) && (tmpCell.colSpan == 1))) { + _$jscoverage['plugins/table.core.js'][346]++; + returns.push(tmpCell); + _$jscoverage['plugins/table.core.js'][347]++; + break; + } +} +} + _$jscoverage['plugins/table.core.js'][351]++; + return returns; + } + catch (e) { + _$jscoverage['plugins/table.core.js'][353]++; + showError(e); + } +}), update: (function (table) { + _$jscoverage['plugins/table.core.js'][360]++; + this.table = (table || this.table); + _$jscoverage['plugins/table.core.js'][361]++; + this.selectedTds = []; + _$jscoverage['plugins/table.core.js'][362]++; + this.cellsRange = {}; + _$jscoverage['plugins/table.core.js'][363]++; + this.indexTable = []; + _$jscoverage['plugins/table.core.js'][364]++; + var rows = this.table.rows, rowsNum = this.getMaxRows(), dNum = (rowsNum - rows.length), colsNum = this.getMaxCols(); + _$jscoverage['plugins/table.core.js'][368]++; + while ((dNum--)) { + _$jscoverage['plugins/table.core.js'][369]++; + this.table.insertRow(rows.length); +} + _$jscoverage['plugins/table.core.js'][371]++; + this.rowsNum = rowsNum; + _$jscoverage['plugins/table.core.js'][372]++; + this.colsNum = colsNum; + _$jscoverage['plugins/table.core.js'][373]++; + for (var i = 0, len = rows.length; (i < len); (i++)) { + _$jscoverage['plugins/table.core.js'][374]++; + this.indexTable[i] = new Array(colsNum); +} + _$jscoverage['plugins/table.core.js'][377]++; + for (var rowIndex = 0, row; (row = rows[rowIndex]); (rowIndex++)) { + _$jscoverage['plugins/table.core.js'][378]++; + for (var cellIndex = 0, cell, cells = row.cells; (cell = cells[cellIndex]); (cellIndex++)) { + _$jscoverage['plugins/table.core.js'][380]++; + if ((cell.rowSpan > rowsNum)) { + _$jscoverage['plugins/table.core.js'][381]++; + cell.rowSpan = rowsNum; + } + _$jscoverage['plugins/table.core.js'][383]++; + var colIndex = cellIndex, rowSpan = (cell.rowSpan || 1), colSpan = (cell.colSpan || 1); + _$jscoverage['plugins/table.core.js'][387]++; + while (this.indexTable[rowIndex][colIndex]) { + _$jscoverage['plugins/table.core.js'][387]++; + (colIndex++); +} + _$jscoverage['plugins/table.core.js'][388]++; + for (var j = 0; (j < rowSpan); (j++)) { + _$jscoverage['plugins/table.core.js'][389]++; + for (var k = 0; (k < colSpan); (k++)) { + _$jscoverage['plugins/table.core.js'][390]++; + this.indexTable[(rowIndex + j)][(colIndex + k)] = {rowIndex: rowIndex, cellIndex: cellIndex, colIndex: colIndex, rowSpan: rowSpan, colSpan: colSpan}; +} +} +} +} + _$jscoverage['plugins/table.core.js'][402]++; + for (j = 0; (j < rowsNum); (j++)) { + _$jscoverage['plugins/table.core.js'][403]++; + for (k = 0; (k < colsNum); (k++)) { + _$jscoverage['plugins/table.core.js'][404]++; + if ((this.indexTable[j][k] === undefined)) { + _$jscoverage['plugins/table.core.js'][405]++; + row = rows[j]; + _$jscoverage['plugins/table.core.js'][406]++; + cell = row.cells[(row.cells.length - 1)]; + _$jscoverage['plugins/table.core.js'][407]++; + cell = (cell? cell.cloneNode(true): this.table.ownerDocument.createElement("td")); + _$jscoverage['plugins/table.core.js'][408]++; + this.setCellContent(cell); + _$jscoverage['plugins/table.core.js'][409]++; + if ((cell.colSpan !== 1)) { + _$jscoverage['plugins/table.core.js'][409]++; + cell.colSpan = 1; + } + _$jscoverage['plugins/table.core.js'][410]++; + if ((cell.rowSpan !== 1)) { + _$jscoverage['plugins/table.core.js'][410]++; + cell.rowSpan = 1; + } + _$jscoverage['plugins/table.core.js'][411]++; + row.appendChild(cell); + _$jscoverage['plugins/table.core.js'][412]++; + this.indexTable[j][k] = {rowIndex: j, cellIndex: cell.cellIndex, colIndex: k, rowSpan: 1, colSpan: 1}; + } +} +} + _$jscoverage['plugins/table.core.js'][423]++; + var tds = domUtils.getElementsByTagName(this.table, "td"), selectTds = []; + _$jscoverage['plugins/table.core.js'][425]++; + utils.each(tds, (function (td) { + _$jscoverage['plugins/table.core.js'][426]++; + if (domUtils.hasClass(td, "selectTdClass")) { + _$jscoverage['plugins/table.core.js'][427]++; + selectTds.push(td); + } +})); + _$jscoverage['plugins/table.core.js'][430]++; + if (selectTds.length) { + _$jscoverage['plugins/table.core.js'][431]++; + var start = selectTds[0], end = selectTds[(selectTds.length - 1)], startInfo = this.getCellInfo(start), endInfo = this.getCellInfo(end); + _$jscoverage['plugins/table.core.js'][435]++; + this.selectedTds = selectTds; + _$jscoverage['plugins/table.core.js'][436]++; + this.cellsRange = {beginRowIndex: startInfo.rowIndex, beginColIndex: startInfo.colIndex, endRowIndex: ((endInfo.rowIndex + endInfo.rowSpan) - 1), endColIndex: ((endInfo.colIndex + endInfo.colSpan) - 1)}; + } +}), getCellInfo: (function (cell) { + _$jscoverage['plugins/table.core.js'][449]++; + if ((! cell)) { + _$jscoverage['plugins/table.core.js'][449]++; + return; + } + _$jscoverage['plugins/table.core.js'][450]++; + var cellIndex = cell.cellIndex, rowIndex = cell.parentNode.rowIndex, rowInfo = this.indexTable[rowIndex], numCols = this.colsNum; + _$jscoverage['plugins/table.core.js'][454]++; + for (var colIndex = cellIndex; (colIndex < numCols); (colIndex++)) { + _$jscoverage['plugins/table.core.js'][455]++; + var cellInfo = rowInfo[colIndex]; + _$jscoverage['plugins/table.core.js'][456]++; + if (((cellInfo.rowIndex === rowIndex) && (cellInfo.cellIndex === cellIndex))) { + _$jscoverage['plugins/table.core.js'][457]++; + return cellInfo; + } +} +}), getCell: (function (rowIndex, cellIndex) { + _$jscoverage['plugins/table.core.js'][465]++; + return (((rowIndex < this.rowsNum) && this.table.rows[rowIndex].cells[cellIndex]) || null); +}), deleteCell: (function (cell, rowIndex) { + _$jscoverage['plugins/table.core.js'][471]++; + rowIndex = (((typeof rowIndex) == "number")? rowIndex: cell.parentNode.rowIndex); + _$jscoverage['plugins/table.core.js'][472]++; + var row = this.table.rows[rowIndex]; + _$jscoverage['plugins/table.core.js'][473]++; + row.deleteCell(cell.cellIndex); +}), getCellsRange: (function (cellA, cellB) { + _$jscoverage['plugins/table.core.js'][479]++; + function checkRange(beginRowIndex, beginColIndex, endRowIndex, endColIndex) { + _$jscoverage['plugins/table.core.js'][480]++; + var tmpBeginRowIndex = beginRowIndex, tmpBeginColIndex = beginColIndex, tmpEndRowIndex = endRowIndex, tmpEndColIndex = endColIndex, cellInfo, colIndex, rowIndex; + _$jscoverage['plugins/table.core.js'][486]++; + if ((beginRowIndex > 0)) { + _$jscoverage['plugins/table.core.js'][487]++; + for (colIndex = beginColIndex; (colIndex < endColIndex); (colIndex++)) { + _$jscoverage['plugins/table.core.js'][488]++; + cellInfo = me.indexTable[beginRowIndex][colIndex]; + _$jscoverage['plugins/table.core.js'][489]++; + rowIndex = cellInfo.rowIndex; + _$jscoverage['plugins/table.core.js'][490]++; + if ((rowIndex < beginRowIndex)) { + _$jscoverage['plugins/table.core.js'][491]++; + tmpBeginRowIndex = Math.min(rowIndex, tmpBeginRowIndex); + } +} + } + _$jscoverage['plugins/table.core.js'][496]++; + if ((endColIndex < me.colsNum)) { + _$jscoverage['plugins/table.core.js'][497]++; + for (rowIndex = beginRowIndex; (rowIndex < endRowIndex); (rowIndex++)) { + _$jscoverage['plugins/table.core.js'][498]++; + cellInfo = me.indexTable[rowIndex][endColIndex]; + _$jscoverage['plugins/table.core.js'][499]++; + colIndex = ((cellInfo.colIndex + cellInfo.colSpan) - 1); + _$jscoverage['plugins/table.core.js'][500]++; + if ((colIndex > endColIndex)) { + _$jscoverage['plugins/table.core.js'][501]++; + tmpEndColIndex = Math.max(colIndex, tmpEndColIndex); + } +} + } + _$jscoverage['plugins/table.core.js'][506]++; + if ((endRowIndex < me.rowsNum)) { + _$jscoverage['plugins/table.core.js'][507]++; + for (colIndex = beginColIndex; (colIndex < endColIndex); (colIndex++)) { + _$jscoverage['plugins/table.core.js'][508]++; + cellInfo = me.indexTable[endRowIndex][colIndex]; + _$jscoverage['plugins/table.core.js'][509]++; + rowIndex = ((cellInfo.rowIndex + cellInfo.rowSpan) - 1); + _$jscoverage['plugins/table.core.js'][510]++; + if ((rowIndex > endRowIndex)) { + _$jscoverage['plugins/table.core.js'][511]++; + tmpEndRowIndex = Math.max(rowIndex, tmpEndRowIndex); + } +} + } + _$jscoverage['plugins/table.core.js'][516]++; + if ((beginColIndex > 0)) { + _$jscoverage['plugins/table.core.js'][517]++; + for (rowIndex = beginRowIndex; (rowIndex < endRowIndex); (rowIndex++)) { + _$jscoverage['plugins/table.core.js'][518]++; + cellInfo = me.indexTable[rowIndex][beginColIndex]; + _$jscoverage['plugins/table.core.js'][519]++; + colIndex = cellInfo.colIndex; + _$jscoverage['plugins/table.core.js'][520]++; + if ((colIndex < beginColIndex)) { + _$jscoverage['plugins/table.core.js'][521]++; + tmpBeginColIndex = Math.min(cellInfo.colIndex, tmpBeginColIndex); + } +} + } + _$jscoverage['plugins/table.core.js'][526]++; + if (((tmpBeginRowIndex != beginRowIndex) || (tmpBeginColIndex != beginColIndex) || (tmpEndRowIndex != endRowIndex) || (tmpEndColIndex != endColIndex))) { + _$jscoverage['plugins/table.core.js'][527]++; + return checkRange(tmpBeginRowIndex, tmpBeginColIndex, tmpEndRowIndex, tmpEndColIndex); + } + else { + _$jscoverage['plugins/table.core.js'][530]++; + return ({beginRowIndex: beginRowIndex, beginColIndex: beginColIndex, endRowIndex: endRowIndex, endColIndex: endColIndex}); + } +} + _$jscoverage['plugins/table.core.js'][539]++; + try { + _$jscoverage['plugins/table.core.js'][540]++; + var me = this, cellAInfo = me.getCellInfo(cellA); + _$jscoverage['plugins/table.core.js'][542]++; + if ((cellA === cellB)) { + _$jscoverage['plugins/table.core.js'][543]++; + return ({beginRowIndex: cellAInfo.rowIndex, beginColIndex: cellAInfo.colIndex, endRowIndex: ((cellAInfo.rowIndex + cellAInfo.rowSpan) - 1), endColIndex: ((cellAInfo.colIndex + cellAInfo.colSpan) - 1)}); + } + _$jscoverage['plugins/table.core.js'][550]++; + var cellBInfo = me.getCellInfo(cellB); + _$jscoverage['plugins/table.core.js'][552]++; + var beginRowIndex = Math.min(cellAInfo.rowIndex, cellBInfo.rowIndex), beginColIndex = Math.min(cellAInfo.colIndex, cellBInfo.colIndex), endRowIndex = Math.max(((cellAInfo.rowIndex + cellAInfo.rowSpan) - 1), ((cellBInfo.rowIndex + cellBInfo.rowSpan) - 1)), endColIndex = Math.max(((cellAInfo.colIndex + cellAInfo.colSpan) - 1), ((cellBInfo.colIndex + cellBInfo.colSpan) - 1)); + _$jscoverage['plugins/table.core.js'][557]++; + return checkRange(beginRowIndex, beginColIndex, endRowIndex, endColIndex); + } + catch (e) { + } +}), getCells: (function (range) { + _$jscoverage['plugins/table.core.js'][567]++; + this.clearSelected(); + _$jscoverage['plugins/table.core.js'][568]++; + var beginRowIndex = range.beginRowIndex, beginColIndex = range.beginColIndex, endRowIndex = range.endRowIndex, endColIndex = range.endColIndex, cellInfo, rowIndex, colIndex, tdHash = {}, returnTds = []; + _$jscoverage['plugins/table.core.js'][573]++; + for (var i = beginRowIndex; (i <= endRowIndex); (i++)) { + _$jscoverage['plugins/table.core.js'][574]++; + for (var j = beginColIndex; (j <= endColIndex); (j++)) { + _$jscoverage['plugins/table.core.js'][575]++; + cellInfo = this.indexTable[i][j]; + _$jscoverage['plugins/table.core.js'][576]++; + rowIndex = cellInfo.rowIndex; + _$jscoverage['plugins/table.core.js'][577]++; + colIndex = cellInfo.colIndex; + _$jscoverage['plugins/table.core.js'][579]++; + var key = (rowIndex + "|" + colIndex); + _$jscoverage['plugins/table.core.js'][580]++; + if (tdHash[key]) { + _$jscoverage['plugins/table.core.js'][580]++; + continue; + } + _$jscoverage['plugins/table.core.js'][581]++; + tdHash[key] = 1; + _$jscoverage['plugins/table.core.js'][582]++; + if (((rowIndex < i) || (colIndex < j) || (((rowIndex + cellInfo.rowSpan) - 1) > endRowIndex) || (((colIndex + cellInfo.colSpan) - 1) > endColIndex))) { + _$jscoverage['plugins/table.core.js'][583]++; + return null; + } + _$jscoverage['plugins/table.core.js'][585]++; + returnTds.push(this.getCell(rowIndex, cellInfo.cellIndex)); +} +} + _$jscoverage['plugins/table.core.js'][588]++; + return returnTds; +}), clearSelected: (function () { + _$jscoverage['plugins/table.core.js'][594]++; + UETable.removeSelectedClass(this.selectedTds); + _$jscoverage['plugins/table.core.js'][595]++; + this.selectedTds = []; + _$jscoverage['plugins/table.core.js'][596]++; + this.cellsRange = {}; +}), setSelected: (function (range) { + _$jscoverage['plugins/table.core.js'][602]++; + var cells = this.getCells(range); + _$jscoverage['plugins/table.core.js'][603]++; + UETable.addSelectedClass(cells); + _$jscoverage['plugins/table.core.js'][604]++; + this.selectedTds = cells; + _$jscoverage['plugins/table.core.js'][605]++; + this.cellsRange = range; +}), isFullRow: (function () { + _$jscoverage['plugins/table.core.js'][608]++; + var range = this.cellsRange; + _$jscoverage['plugins/table.core.js'][609]++; + return (((range.endColIndex - range.beginColIndex) + 1) == this.colsNum); +}), isFullCol: (function () { + _$jscoverage['plugins/table.core.js'][612]++; + var range = this.cellsRange, table = this.table, ths = table.getElementsByTagName("th"), rows = ((range.endRowIndex - range.beginRowIndex) + 1); + _$jscoverage['plugins/table.core.js'][616]++; + return ((! ths.length)? (rows == this.rowsNum): ((rows == this.rowsNum) || (rows == (this.rowsNum - 1)))); +}), getNextCell: (function (cell, bottom, ignoreRange) { + _$jscoverage['plugins/table.core.js'][625]++; + try { + _$jscoverage['plugins/table.core.js'][626]++; + var cellInfo = this.getCellInfo(cell), nextRowIndex, nextColIndex; + _$jscoverage['plugins/table.core.js'][628]++; + var len = (this.selectedTds.length && (! ignoreRange)), range = this.cellsRange; + _$jscoverage['plugins/table.core.js'][631]++; + if ((((! bottom) && (cellInfo.rowIndex == 0)) || (bottom && ((! len)? ((cellInfo.rowIndex + cellInfo.rowSpan) > (this.rowsNum - 1)): (range.endRowIndex == (this.rowsNum - 1)))))) { + _$jscoverage['plugins/table.core.js'][631]++; + return null; + } + _$jscoverage['plugins/table.core.js'][633]++; + nextRowIndex = ((! bottom)? ((! len)? (cellInfo.rowIndex - 1): (range.beginRowIndex - 1)): ((! len)? (cellInfo.rowIndex + cellInfo.rowSpan): (range.endRowIndex + 1))); + _$jscoverage['plugins/table.core.js'][635]++; + nextColIndex = ((! len)? cellInfo.colIndex: range.beginColIndex); + _$jscoverage['plugins/table.core.js'][636]++; + return this.getCell(this.indexTable[nextRowIndex][nextColIndex].rowIndex, this.indexTable[nextRowIndex][nextColIndex].cellIndex); + } + catch (e) { + _$jscoverage['plugins/table.core.js'][638]++; + showError(e); + } +}), getPreviewCell: (function (cell, top) { + _$jscoverage['plugins/table.core.js'][642]++; + try { + _$jscoverage['plugins/table.core.js'][643]++; + var cellInfo = this.getCellInfo(cell), previewRowIndex, previewColIndex; + _$jscoverage['plugins/table.core.js'][645]++; + var len = this.selectedTds.length, range = this.cellsRange; + _$jscoverage['plugins/table.core.js'][648]++; + if ((((! top) && ((! len)? (! cellInfo.colIndex): (! range.beginColIndex))) || (top && ((! len)? (cellInfo.rowIndex > (this.colsNum - 1)): (range.endColIndex == (this.colsNum - 1)))))) { + _$jscoverage['plugins/table.core.js'][648]++; + return null; + } + _$jscoverage['plugins/table.core.js'][650]++; + previewRowIndex = ((! top)? ((! len)? cellInfo.rowIndex: range.beginRowIndex): ((! len)? ((cellInfo.rowIndex < 1)? 0: (cellInfo.rowIndex - 1)): range.beginRowIndex)); + _$jscoverage['plugins/table.core.js'][652]++; + previewColIndex = ((! top)? ((! len)? ((cellInfo.colIndex < 1)? 0: (cellInfo.colIndex - 1)): (range.beginColIndex - 1)): ((! len)? cellInfo.colIndex: (range.endColIndex + 1))); + _$jscoverage['plugins/table.core.js'][654]++; + return this.getCell(this.indexTable[previewRowIndex][previewColIndex].rowIndex, this.indexTable[previewRowIndex][previewColIndex].cellIndex); + } + catch (e) { + _$jscoverage['plugins/table.core.js'][656]++; + showError(e); + } +}), moveContent: (function (cellTo, cellFrom) { + _$jscoverage['plugins/table.core.js'][663]++; + if (UETable.isEmptyBlock(cellFrom)) { + _$jscoverage['plugins/table.core.js'][663]++; + return; + } + _$jscoverage['plugins/table.core.js'][664]++; + if (UETable.isEmptyBlock(cellTo)) { + _$jscoverage['plugins/table.core.js'][665]++; + cellTo.innerHTML = cellFrom.innerHTML; + _$jscoverage['plugins/table.core.js'][666]++; + return; + } + _$jscoverage['plugins/table.core.js'][668]++; + var child = cellTo.lastChild; + _$jscoverage['plugins/table.core.js'][669]++; + if (((child.nodeType == 3) || (! dtd.$block[child.tagName]))) { + _$jscoverage['plugins/table.core.js'][670]++; + cellTo.appendChild(cellTo.ownerDocument.createElement("br")); + } + _$jscoverage['plugins/table.core.js'][672]++; + while ((child = cellFrom.firstChild)) { + _$jscoverage['plugins/table.core.js'][673]++; + cellTo.appendChild(child); +} +}), mergeRight: (function (cell) { + _$jscoverage['plugins/table.core.js'][680]++; + var cellInfo = this.getCellInfo(cell), rightColIndex = (cellInfo.colIndex + cellInfo.colSpan), rightCellInfo = this.indexTable[cellInfo.rowIndex][rightColIndex], rightCell = this.getCell(rightCellInfo.rowIndex, rightCellInfo.cellIndex); + _$jscoverage['plugins/table.core.js'][685]++; + cell.colSpan = (cellInfo.colSpan + rightCellInfo.colSpan); + _$jscoverage['plugins/table.core.js'][687]++; + cell.removeAttribute("width"); + _$jscoverage['plugins/table.core.js'][689]++; + this.moveContent(cell, rightCell); + _$jscoverage['plugins/table.core.js'][691]++; + this.deleteCell(rightCell, rightCellInfo.rowIndex); + _$jscoverage['plugins/table.core.js'][692]++; + this.update(); +}), mergeDown: (function (cell) { + _$jscoverage['plugins/table.core.js'][698]++; + var cellInfo = this.getCellInfo(cell), downRowIndex = (cellInfo.rowIndex + cellInfo.rowSpan), downCellInfo = this.indexTable[downRowIndex][cellInfo.colIndex], downCell = this.getCell(downCellInfo.rowIndex, downCellInfo.cellIndex); + _$jscoverage['plugins/table.core.js'][702]++; + cell.rowSpan = (cellInfo.rowSpan + downCellInfo.rowSpan); + _$jscoverage['plugins/table.core.js'][703]++; + cell.removeAttribute("height"); + _$jscoverage['plugins/table.core.js'][704]++; + this.moveContent(cell, downCell); + _$jscoverage['plugins/table.core.js'][705]++; + this.deleteCell(downCell, downCellInfo.rowIndex); + _$jscoverage['plugins/table.core.js'][706]++; + this.update(); +}), mergeRange: (function () { + _$jscoverage['plugins/table.core.js'][713]++; + var range = this.cellsRange, leftTopCell = this.getCell(range.beginRowIndex, this.indexTable[range.beginRowIndex][range.beginColIndex].cellIndex); + _$jscoverage['plugins/table.core.js'][716]++; + if (((leftTopCell.tagName == "TH") && (range.endRowIndex !== range.beginRowIndex))) { + _$jscoverage['plugins/table.core.js'][717]++; + var index = this.indexTable, info = this.getCellInfo(leftTopCell); + _$jscoverage['plugins/table.core.js'][719]++; + leftTopCell = this.getCell(1, index[1][info.colIndex].cellIndex); + _$jscoverage['plugins/table.core.js'][720]++; + range = this.getCellsRange(leftTopCell, this.getCell(index[(this.rowsNum - 1)][info.colIndex].rowIndex, index[(this.rowsNum - 1)][info.colIndex].cellIndex)); + } + _$jscoverage['plugins/table.core.js'][724]++; + var cells = this.getCells(range); + _$jscoverage['plugins/table.core.js'][725]++; + for (var i = 0, ci; (ci = cells[(i++)]);) { + _$jscoverage['plugins/table.core.js'][726]++; + if ((ci !== leftTopCell)) { + _$jscoverage['plugins/table.core.js'][727]++; + this.moveContent(leftTopCell, ci); + _$jscoverage['plugins/table.core.js'][728]++; + this.deleteCell(ci); + } +} + _$jscoverage['plugins/table.core.js'][732]++; + leftTopCell.rowSpan = ((range.endRowIndex - range.beginRowIndex) + 1); + _$jscoverage['plugins/table.core.js'][733]++; + ((leftTopCell.rowSpan > 1) && leftTopCell.removeAttribute("height")); + _$jscoverage['plugins/table.core.js'][734]++; + leftTopCell.colSpan = ((range.endColIndex - range.beginColIndex) + 1); + _$jscoverage['plugins/table.core.js'][735]++; + ((leftTopCell.colSpan > 1) && leftTopCell.removeAttribute("width")); + _$jscoverage['plugins/table.core.js'][736]++; + if (((leftTopCell.rowSpan == this.rowsNum) && (leftTopCell.colSpan != 1))) { + _$jscoverage['plugins/table.core.js'][737]++; + leftTopCell.colSpan = 1; + } + _$jscoverage['plugins/table.core.js'][740]++; + if (((leftTopCell.colSpan == this.colsNum) && (leftTopCell.rowSpan != 1))) { + _$jscoverage['plugins/table.core.js'][741]++; + var rowIndex = leftTopCell.parentNode.rowIndex; + _$jscoverage['plugins/table.core.js'][743]++; + if (this.table.deleteRow) { + _$jscoverage['plugins/table.core.js'][744]++; + for (var i = (rowIndex + 1), curIndex = (rowIndex + 1), len = leftTopCell.rowSpan; (i < len); (i++)) { + _$jscoverage['plugins/table.core.js'][745]++; + this.table.deleteRow(curIndex); +} + } + else { + _$jscoverage['plugins/table.core.js'][748]++; + for (var i = 0, len = (leftTopCell.rowSpan - 1); (i < len); (i++)) { + _$jscoverage['plugins/table.core.js'][749]++; + var row = this.table.rows[(rowIndex + 1)]; + _$jscoverage['plugins/table.core.js'][750]++; + row.parentNode.removeChild(row); +} + } + _$jscoverage['plugins/table.core.js'][753]++; + leftTopCell.rowSpan = 1; + } + _$jscoverage['plugins/table.core.js'][755]++; + this.update(); +}), insertRow: (function (rowIndex, sourceCell) { + _$jscoverage['plugins/table.core.js'][761]++; + var numCols = this.colsNum, table = this.table, row = table.insertRow(rowIndex), cell, width = parseInt(((table.offsetWidth - (numCols * 20) - numCols - 1) / numCols), 10); + _$jscoverage['plugins/table.core.js'][766]++; + if (((rowIndex == 0) || (rowIndex == this.rowsNum))) { + _$jscoverage['plugins/table.core.js'][767]++; + for (var colIndex = 0; (colIndex < numCols); (colIndex++)) { + _$jscoverage['plugins/table.core.js'][768]++; + cell = this.cloneCell(sourceCell, true); + _$jscoverage['plugins/table.core.js'][769]++; + this.setCellContent(cell); + _$jscoverage['plugins/table.core.js'][770]++; + (cell.getAttribute("vAlign") && cell.setAttribute("vAlign", cell.getAttribute("vAlign"))); + _$jscoverage['plugins/table.core.js'][771]++; + row.appendChild(cell); +} + } + else { + _$jscoverage['plugins/table.core.js'][774]++; + var infoRow = this.indexTable[rowIndex], cellIndex = 0; + _$jscoverage['plugins/table.core.js'][776]++; + for (colIndex = 0; (colIndex < numCols); (colIndex++)) { + _$jscoverage['plugins/table.core.js'][777]++; + var cellInfo = infoRow[colIndex]; + _$jscoverage['plugins/table.core.js'][779]++; + if ((cellInfo.rowIndex < rowIndex)) { + _$jscoverage['plugins/table.core.js'][780]++; + cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex); + _$jscoverage['plugins/table.core.js'][781]++; + cell.rowSpan = (cellInfo.rowSpan + 1); + } + else { + _$jscoverage['plugins/table.core.js'][783]++; + cell = this.cloneCell(sourceCell, true); + _$jscoverage['plugins/table.core.js'][784]++; + this.setCellContent(cell); + _$jscoverage['plugins/table.core.js'][785]++; + row.appendChild(cell); + } +} + } + _$jscoverage['plugins/table.core.js'][790]++; + this.update(); + _$jscoverage['plugins/table.core.js'][791]++; + return row; +}), deleteRow: (function (rowIndex) { + _$jscoverage['plugins/table.core.js'][798]++; + var row = this.table.rows[rowIndex], infoRow = this.indexTable[rowIndex], colsNum = this.colsNum, count = 0; + _$jscoverage['plugins/table.core.js'][802]++; + for (var colIndex = 0; (colIndex < colsNum);) { + _$jscoverage['plugins/table.core.js'][803]++; + var cellInfo = infoRow[colIndex], cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex); + _$jscoverage['plugins/table.core.js'][805]++; + if ((cell.rowSpan > 1)) { + _$jscoverage['plugins/table.core.js'][806]++; + if ((cellInfo.rowIndex == rowIndex)) { + _$jscoverage['plugins/table.core.js'][807]++; + var clone = cell.cloneNode(true); + _$jscoverage['plugins/table.core.js'][808]++; + clone.rowSpan = (cell.rowSpan - 1); + _$jscoverage['plugins/table.core.js'][809]++; + clone.innerHTML = ""; + _$jscoverage['plugins/table.core.js'][810]++; + cell.rowSpan = 1; + _$jscoverage['plugins/table.core.js'][811]++; + var nextRowIndex = (rowIndex + 1), nextRow = this.table.rows[nextRowIndex], insertCellIndex, preMerged = (this.getPreviewMergedCellsNum(nextRowIndex, colIndex) - count); + _$jscoverage['plugins/table.core.js'][815]++; + if ((preMerged < colIndex)) { + _$jscoverage['plugins/table.core.js'][816]++; + insertCellIndex = (colIndex - preMerged - 1); + _$jscoverage['plugins/table.core.js'][818]++; + domUtils.insertAfter(nextRow.cells[insertCellIndex], clone); + } + else { + _$jscoverage['plugins/table.core.js'][820]++; + if (nextRow.cells.length) { + _$jscoverage['plugins/table.core.js'][820]++; + nextRow.insertBefore(clone, nextRow.cells[0]); + } + } + _$jscoverage['plugins/table.core.js'][822]++; + count += 1; + } + } + _$jscoverage['plugins/table.core.js'][826]++; + colIndex += (cell.colSpan || 1); +} + _$jscoverage['plugins/table.core.js'][828]++; + var deleteTds = [], cacheMap = {}; + _$jscoverage['plugins/table.core.js'][829]++; + for (colIndex = 0; (colIndex < colsNum); (colIndex++)) { + _$jscoverage['plugins/table.core.js'][830]++; + var tmpRowIndex = infoRow[colIndex].rowIndex, tmpCellIndex = infoRow[colIndex].cellIndex, key = (tmpRowIndex + "_" + tmpCellIndex); + _$jscoverage['plugins/table.core.js'][833]++; + if (cacheMap[key]) { + _$jscoverage['plugins/table.core.js'][833]++; + continue; + } + _$jscoverage['plugins/table.core.js'][834]++; + cacheMap[key] = 1; + _$jscoverage['plugins/table.core.js'][835]++; + cell = this.getCell(tmpRowIndex, tmpCellIndex); + _$jscoverage['plugins/table.core.js'][836]++; + deleteTds.push(cell); +} + _$jscoverage['plugins/table.core.js'][838]++; + var mergeTds = []; + _$jscoverage['plugins/table.core.js'][839]++; + utils.each(deleteTds, (function (td) { + _$jscoverage['plugins/table.core.js'][840]++; + if ((td.rowSpan == 1)) { + _$jscoverage['plugins/table.core.js'][841]++; + td.parentNode.removeChild(td); + } + else { + _$jscoverage['plugins/table.core.js'][843]++; + mergeTds.push(td); + } +})); + _$jscoverage['plugins/table.core.js'][846]++; + utils.each(mergeTds, (function (td) { + _$jscoverage['plugins/table.core.js'][847]++; + (td.rowSpan--); +})); + _$jscoverage['plugins/table.core.js'][849]++; + row.parentNode.removeChild(row); + _$jscoverage['plugins/table.core.js'][852]++; + this.update(); +}), insertCol: (function (colIndex, sourceCell, defaultValue) { + _$jscoverage['plugins/table.core.js'][855]++; + var rowsNum = this.rowsNum, rowIndex = 0, tableRow, cell, backWidth = parseInt(((this.table.offsetWidth - ((this.colsNum + 1) * 20) - (this.colsNum + 1)) / (this.colsNum + 1)), 10); + _$jscoverage['plugins/table.core.js'][860]++; + function replaceTdToTh(rowIndex, cell, tableRow) { + _$jscoverage['plugins/table.core.js'][861]++; + if ((rowIndex == 0)) { + _$jscoverage['plugins/table.core.js'][862]++; + var th = (cell.nextSibling || cell.previousSibling); + _$jscoverage['plugins/table.core.js'][863]++; + if ((th.tagName == "TH")) { + _$jscoverage['plugins/table.core.js'][864]++; + th = cell.ownerDocument.createElement("th"); + _$jscoverage['plugins/table.core.js'][865]++; + th.appendChild(cell.firstChild); + _$jscoverage['plugins/table.core.js'][866]++; + tableRow.insertBefore(th, cell); + _$jscoverage['plugins/table.core.js'][867]++; + domUtils.remove(cell); + } + } + else { + _$jscoverage['plugins/table.core.js'][870]++; + if ((cell.tagName == "TH")) { + _$jscoverage['plugins/table.core.js'][871]++; + var td = cell.ownerDocument.createElement("td"); + _$jscoverage['plugins/table.core.js'][872]++; + td.appendChild(cell.firstChild); + _$jscoverage['plugins/table.core.js'][873]++; + tableRow.insertBefore(td, cell); + _$jscoverage['plugins/table.core.js'][874]++; + domUtils.remove(cell); + } + } +} + _$jscoverage['plugins/table.core.js'][879]++; + var preCell; + _$jscoverage['plugins/table.core.js'][880]++; + if (((colIndex == 0) || (colIndex == this.colsNum))) { + _$jscoverage['plugins/table.core.js'][881]++; + for (; (rowIndex < rowsNum); (rowIndex++)) { + _$jscoverage['plugins/table.core.js'][882]++; + tableRow = this.table.rows[rowIndex]; + _$jscoverage['plugins/table.core.js'][883]++; + preCell = tableRow.cells[((colIndex == 0)? colIndex: tableRow.cells.length)]; + _$jscoverage['plugins/table.core.js'][884]++; + cell = this.cloneCell(sourceCell, true); + _$jscoverage['plugins/table.core.js'][885]++; + this.setCellContent(cell); + _$jscoverage['plugins/table.core.js'][886]++; + cell.setAttribute("vAlign", cell.getAttribute("vAlign")); + _$jscoverage['plugins/table.core.js'][887]++; + (preCell && cell.setAttribute("width", preCell.getAttribute("width"))); + _$jscoverage['plugins/table.core.js'][888]++; + if ((! colIndex)) { + _$jscoverage['plugins/table.core.js'][889]++; + tableRow.insertBefore(cell, tableRow.cells[0]); + } + else { + _$jscoverage['plugins/table.core.js'][891]++; + domUtils.insertAfter(tableRow.cells[(tableRow.cells.length - 1)], cell); + } + _$jscoverage['plugins/table.core.js'][893]++; + replaceTdToTh(rowIndex, cell, tableRow); +} + } + else { + _$jscoverage['plugins/table.core.js'][896]++; + for (; (rowIndex < rowsNum); (rowIndex++)) { + _$jscoverage['plugins/table.core.js'][897]++; + var cellInfo = this.indexTable[rowIndex][colIndex]; + _$jscoverage['plugins/table.core.js'][898]++; + if ((cellInfo.colIndex < colIndex)) { + _$jscoverage['plugins/table.core.js'][899]++; + cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex); + _$jscoverage['plugins/table.core.js'][900]++; + cell.colSpan = (cellInfo.colSpan + 1); + } + else { + _$jscoverage['plugins/table.core.js'][902]++; + tableRow = this.table.rows[rowIndex]; + _$jscoverage['plugins/table.core.js'][903]++; + preCell = tableRow.cells[cellInfo.cellIndex]; + _$jscoverage['plugins/table.core.js'][905]++; + cell = this.cloneCell(sourceCell, true); + _$jscoverage['plugins/table.core.js'][906]++; + this.setCellContent(cell); + _$jscoverage['plugins/table.core.js'][907]++; + cell.setAttribute("vAlign", cell.getAttribute("vAlign")); + _$jscoverage['plugins/table.core.js'][908]++; + (preCell && cell.setAttribute("width", preCell.getAttribute("width"))); + _$jscoverage['plugins/table.core.js'][910]++; + (preCell? tableRow.insertBefore(cell, preCell): tableRow.appendChild(cell)); + } + _$jscoverage['plugins/table.core.js'][912]++; + replaceTdToTh(rowIndex, cell, tableRow); +} + } + _$jscoverage['plugins/table.core.js'][916]++; + this.update(); + _$jscoverage['plugins/table.core.js'][917]++; + this.updateWidth(backWidth, (defaultValue || {tdPadding: 10, tdBorder: 1})); +}), updateWidth: (function (width, defaultValue) { + _$jscoverage['plugins/table.core.js'][920]++; + var table = this.table, tmpWidth = ((UETable.getWidth(table) - (defaultValue.tdPadding * 2) - defaultValue.tdBorder) + width); + _$jscoverage['plugins/table.core.js'][922]++; + if ((tmpWidth < table.ownerDocument.body.offsetWidth)) { + _$jscoverage['plugins/table.core.js'][923]++; + table.setAttribute("width", tmpWidth); + _$jscoverage['plugins/table.core.js'][924]++; + return; + } + _$jscoverage['plugins/table.core.js'][926]++; + var tds = domUtils.getElementsByTagName(this.table, "td"); + _$jscoverage['plugins/table.core.js'][927]++; + utils.each(tds, (function (td) { + _$jscoverage['plugins/table.core.js'][928]++; + td.setAttribute("width", width); +})); +}), deleteCol: (function (colIndex) { + _$jscoverage['plugins/table.core.js'][932]++; + var indexTable = this.indexTable, tableRows = this.table.rows, backTableWidth = this.table.getAttribute("width"), backTdWidth = 0, rowsNum = this.rowsNum, cacheMap = {}; + _$jscoverage['plugins/table.core.js'][938]++; + for (var rowIndex = 0; (rowIndex < rowsNum);) { + _$jscoverage['plugins/table.core.js'][939]++; + var infoRow = indexTable[rowIndex], cellInfo = infoRow[colIndex], key = (cellInfo.rowIndex + "_" + cellInfo.colIndex); + _$jscoverage['plugins/table.core.js'][943]++; + if (cacheMap[key]) { + _$jscoverage['plugins/table.core.js'][943]++; + continue; + } + _$jscoverage['plugins/table.core.js'][944]++; + cacheMap[key] = 1; + _$jscoverage['plugins/table.core.js'][945]++; + var cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex); + _$jscoverage['plugins/table.core.js'][946]++; + if ((! backTdWidth)) { + _$jscoverage['plugins/table.core.js'][946]++; + backTdWidth = (cell && parseInt((cell.offsetWidth / cell.colSpan), 10).toFixed(0)); + } + _$jscoverage['plugins/table.core.js'][948]++; + if ((cell.colSpan > 1)) { + _$jscoverage['plugins/table.core.js'][949]++; + (cell.colSpan--); + } + else { + _$jscoverage['plugins/table.core.js'][951]++; + tableRows[rowIndex].deleteCell(cellInfo.cellIndex); + } + _$jscoverage['plugins/table.core.js'][953]++; + rowIndex += (cellInfo.rowSpan || 1); +} + _$jscoverage['plugins/table.core.js'][955]++; + this.table.setAttribute("width", (backTableWidth - backTdWidth)); + _$jscoverage['plugins/table.core.js'][956]++; + this.update(); +}), splitToCells: (function (cell) { + _$jscoverage['plugins/table.core.js'][959]++; + var me = this, cells = this.splitToRows(cell); + _$jscoverage['plugins/table.core.js'][961]++; + utils.each(cells, (function (cell) { + _$jscoverage['plugins/table.core.js'][962]++; + me.splitToCols(cell); +})); +}), splitToRows: (function (cell) { + _$jscoverage['plugins/table.core.js'][966]++; + var cellInfo = this.getCellInfo(cell), rowIndex = cellInfo.rowIndex, colIndex = cellInfo.colIndex, results = []; + _$jscoverage['plugins/table.core.js'][971]++; + cell.rowSpan = 1; + _$jscoverage['plugins/table.core.js'][972]++; + results.push(cell); + _$jscoverage['plugins/table.core.js'][974]++; + for (var i = rowIndex, endRow = (rowIndex + cellInfo.rowSpan); (i < endRow); (i++)) { + _$jscoverage['plugins/table.core.js'][975]++; + if ((i == rowIndex)) { + _$jscoverage['plugins/table.core.js'][975]++; + continue; + } + _$jscoverage['plugins/table.core.js'][976]++; + var tableRow = this.table.rows[i], tmpCell = tableRow.insertCell((colIndex - this.getPreviewMergedCellsNum(i, colIndex))); + _$jscoverage['plugins/table.core.js'][978]++; + tmpCell.colSpan = cellInfo.colSpan; + _$jscoverage['plugins/table.core.js'][979]++; + this.setCellContent(tmpCell); + _$jscoverage['plugins/table.core.js'][980]++; + tmpCell.setAttribute("vAlign", cell.getAttribute("vAlign")); + _$jscoverage['plugins/table.core.js'][981]++; + tmpCell.setAttribute("align", cell.getAttribute("align")); + _$jscoverage['plugins/table.core.js'][982]++; + if (cell.style.cssText) { + _$jscoverage['plugins/table.core.js'][983]++; + tmpCell.style.cssText = cell.style.cssText; + } + _$jscoverage['plugins/table.core.js'][985]++; + results.push(tmpCell); +} + _$jscoverage['plugins/table.core.js'][987]++; + this.update(); + _$jscoverage['plugins/table.core.js'][988]++; + return results; +}), getPreviewMergedCellsNum: (function (rowIndex, colIndex) { + _$jscoverage['plugins/table.core.js'][991]++; + var indexRow = this.indexTable[rowIndex], num = 0; + _$jscoverage['plugins/table.core.js'][993]++; + for (var i = 0; (i < colIndex);) { + _$jscoverage['plugins/table.core.js'][994]++; + var colSpan = indexRow[i].colSpan, tmpRowIndex = indexRow[i].rowIndex; + _$jscoverage['plugins/table.core.js'][996]++; + num += (colSpan - ((tmpRowIndex == rowIndex)? 1: 0)); + _$jscoverage['plugins/table.core.js'][997]++; + i += colSpan; +} + _$jscoverage['plugins/table.core.js'][999]++; + return num; +}), splitToCols: (function (cell) { + _$jscoverage['plugins/table.core.js'][1002]++; + var backWidth = ((cell.offsetWidth / cell.colSpan) - 22).toFixed(0), cellInfo = this.getCellInfo(cell), rowIndex = cellInfo.rowIndex, colIndex = cellInfo.colIndex, results = []; + _$jscoverage['plugins/table.core.js'][1009]++; + cell.colSpan = 1; + _$jscoverage['plugins/table.core.js'][1010]++; + cell.setAttribute("width", backWidth); + _$jscoverage['plugins/table.core.js'][1011]++; + results.push(cell); + _$jscoverage['plugins/table.core.js'][1013]++; + for (var j = colIndex, endCol = (colIndex + cellInfo.colSpan); (j < endCol); (j++)) { + _$jscoverage['plugins/table.core.js'][1014]++; + if ((j == colIndex)) { + _$jscoverage['plugins/table.core.js'][1014]++; + continue; + } + _$jscoverage['plugins/table.core.js'][1015]++; + var tableRow = this.table.rows[rowIndex], tmpCell = tableRow.insertCell((this.indexTable[rowIndex][j].cellIndex + 1)); + _$jscoverage['plugins/table.core.js'][1017]++; + tmpCell.rowSpan = cellInfo.rowSpan; + _$jscoverage['plugins/table.core.js'][1018]++; + this.setCellContent(tmpCell); + _$jscoverage['plugins/table.core.js'][1019]++; + tmpCell.setAttribute("vAlign", cell.getAttribute("vAlign")); + _$jscoverage['plugins/table.core.js'][1020]++; + tmpCell.setAttribute("align", cell.getAttribute("align")); + _$jscoverage['plugins/table.core.js'][1021]++; + tmpCell.setAttribute("width", backWidth); + _$jscoverage['plugins/table.core.js'][1022]++; + if (cell.style.cssText) { + _$jscoverage['plugins/table.core.js'][1023]++; + tmpCell.style.cssText = cell.style.cssText; + } + _$jscoverage['plugins/table.core.js'][1026]++; + if ((cell.tagName == "TH")) { + _$jscoverage['plugins/table.core.js'][1027]++; + var th = cell.ownerDocument.createElement("th"); + _$jscoverage['plugins/table.core.js'][1028]++; + th.appendChild(tmpCell.firstChild); + _$jscoverage['plugins/table.core.js'][1029]++; + th.setAttribute("vAlign", cell.getAttribute("vAlign")); + _$jscoverage['plugins/table.core.js'][1030]++; + th.rowSpan = tmpCell.rowSpan; + _$jscoverage['plugins/table.core.js'][1031]++; + tableRow.insertBefore(th, tmpCell); + _$jscoverage['plugins/table.core.js'][1032]++; + domUtils.remove(tmpCell); + } + _$jscoverage['plugins/table.core.js'][1034]++; + results.push(tmpCell); +} + _$jscoverage['plugins/table.core.js'][1036]++; + this.update(); + _$jscoverage['plugins/table.core.js'][1037]++; + return results; +}), isLastCell: (function (cell, rowsNum, colsNum) { + _$jscoverage['plugins/table.core.js'][1040]++; + rowsNum = (rowsNum || this.rowsNum); + _$jscoverage['plugins/table.core.js'][1041]++; + colsNum = (colsNum || this.colsNum); + _$jscoverage['plugins/table.core.js'][1042]++; + var cellInfo = this.getCellInfo(cell); + _$jscoverage['plugins/table.core.js'][1043]++; + return (((cellInfo.rowIndex + cellInfo.rowSpan) == rowsNum) && ((cellInfo.colIndex + cellInfo.colSpan) == colsNum)); +}), getLastCell: (function (cells) { + _$jscoverage['plugins/table.core.js'][1047]++; + cells = (cells || this.table.getElementsByTagName("td")); + _$jscoverage['plugins/table.core.js'][1048]++; + var firstInfo = this.getCellInfo(cells[0]); + _$jscoverage['plugins/table.core.js'][1049]++; + var me = this, last = cells[0], tr = last.parentNode, cellsNum = 0, cols = 0, rows; + _$jscoverage['plugins/table.core.js'][1052]++; + utils.each(cells, (function (cell) { + _$jscoverage['plugins/table.core.js'][1053]++; + if ((cell.parentNode == tr)) { + _$jscoverage['plugins/table.core.js'][1053]++; + cols += (cell.colSpan || 1); + } + _$jscoverage['plugins/table.core.js'][1054]++; + cellsNum += ((cell.rowSpan * cell.colSpan) || 1); +})); + _$jscoverage['plugins/table.core.js'][1056]++; + rows = (cellsNum / cols); + _$jscoverage['plugins/table.core.js'][1057]++; + utils.each(cells, (function (cell) { + _$jscoverage['plugins/table.core.js'][1058]++; + if (me.isLastCell(cell, rows, cols)) { + _$jscoverage['plugins/table.core.js'][1059]++; + last = cell; + _$jscoverage['plugins/table.core.js'][1060]++; + return false; + } +})); + _$jscoverage['plugins/table.core.js'][1063]++; + return last; +}), selectRow: (function (rowIndex) { + _$jscoverage['plugins/table.core.js'][1067]++; + var indexRow = this.indexTable[rowIndex], start = this.getCell(indexRow[0].rowIndex, indexRow[0].cellIndex), end = this.getCell(indexRow[(this.colsNum - 1)].rowIndex, indexRow[(this.colsNum - 1)].cellIndex), range = this.getCellsRange(start, end); + _$jscoverage['plugins/table.core.js'][1071]++; + this.setSelected(range); +}), selectTable: (function () { + _$jscoverage['plugins/table.core.js'][1074]++; + var tds = this.table.getElementsByTagName("td"), range = this.getCellsRange(tds[0], tds[(tds.length - 1)]); + _$jscoverage['plugins/table.core.js'][1076]++; + this.setSelected(range); +}), sortTable: (function (sortByCellIndex, compareFn) { + _$jscoverage['plugins/table.core.js'][1079]++; + var table = this.table, rows = table.rows, trArray = [], flag = (rows[0].cells[0].tagName === "TH"), lastRowIndex = 0; + _$jscoverage['plugins/table.core.js'][1084]++; + if (this.selectedTds.length) { + _$jscoverage['plugins/table.core.js'][1085]++; + var range = this.cellsRange, len = (range.endRowIndex + 1); + _$jscoverage['plugins/table.core.js'][1087]++; + for (var i = range.beginRowIndex; (i < len); (i++)) { + _$jscoverage['plugins/table.core.js'][1088]++; + trArray[i] = rows[i]; +} + _$jscoverage['plugins/table.core.js'][1090]++; + trArray.splice(0, range.beginRowIndex); + _$jscoverage['plugins/table.core.js'][1091]++; + lastRowIndex = (((range.endRowIndex + 1) === this.rowsNum)? 0: (range.endRowIndex + 1)); + } + else { + _$jscoverage['plugins/table.core.js'][1093]++; + for (var i = 0, len = rows.length; (i < len); (i++)) { + _$jscoverage['plugins/table.core.js'][1094]++; + trArray[i] = rows[i]; +} + } + _$jscoverage['plugins/table.core.js'][1098]++; + (flag && trArray.splice(0, 1)); + _$jscoverage['plugins/table.core.js'][1099]++; + trArray = utils.sort(trArray, (function (tr1, tr2) { + _$jscoverage['plugins/table.core.js'][1100]++; + var txt = (function (node) { + _$jscoverage['plugins/table.core.js'][1101]++; + return (node.innerText || node.textContent); +}); + _$jscoverage['plugins/table.core.js'][1103]++; + return (compareFn? (((typeof compareFn) === "number")? compareFn: compareFn.call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex])): (function () { + _$jscoverage['plugins/table.core.js'][1104]++; + var value1 = txt(tr1.cells[sortByCellIndex]), value2 = txt(tr2.cells[sortByCellIndex]); + _$jscoverage['plugins/table.core.js'][1106]++; + return value1.localeCompare(value2); +})()); +})); + _$jscoverage['plugins/table.core.js'][1109]++; + var fragment = table.ownerDocument.createDocumentFragment(); + _$jscoverage['plugins/table.core.js'][1110]++; + for (var j = 0, len = trArray.length; (j < len); (j++)) { + _$jscoverage['plugins/table.core.js'][1111]++; + fragment.appendChild(trArray[j]); +} + _$jscoverage['plugins/table.core.js'][1113]++; + var tbody = table.getElementsByTagName("tbody")[0]; + _$jscoverage['plugins/table.core.js'][1114]++; + if ((! lastRowIndex)) { + _$jscoverage['plugins/table.core.js'][1115]++; + tbody.appendChild(fragment); + } + else { + _$jscoverage['plugins/table.core.js'][1117]++; + tbody.insertBefore(fragment, rows[(((lastRowIndex - range.endRowIndex) + range.beginRowIndex) - 1)]); + } +}), setBackground: (function (cells, value) { + _$jscoverage['plugins/table.core.js'][1121]++; + if (((typeof value) === "string")) { + _$jscoverage['plugins/table.core.js'][1122]++; + utils.each(cells, (function (cell) { + _$jscoverage['plugins/table.core.js'][1123]++; + cell.style.backgroundColor = value; +})); + } + else { + _$jscoverage['plugins/table.core.js'][1125]++; + if (((typeof value) === "object")) { + _$jscoverage['plugins/table.core.js'][1126]++; + value = utils.extend({repeat: true, colorList: ["#ddd", "#fff"]}, value); + _$jscoverage['plugins/table.core.js'][1130]++; + var rowIndex = this.getCellInfo(cells[0]).rowIndex, count = 0, colors = value.colorList, getColor = (function (list, index, repeat) { + _$jscoverage['plugins/table.core.js'][1134]++; + return (list[index]? list[index]: (repeat? list[(index % list.length)]: "")); +}); + _$jscoverage['plugins/table.core.js'][1136]++; + for (var i = 0, cell; (cell = cells[(i++)]);) { + _$jscoverage['plugins/table.core.js'][1137]++; + var cellInfo = this.getCellInfo(cell); + _$jscoverage['plugins/table.core.js'][1138]++; + cell.style.backgroundColor = getColor(colors, (((rowIndex + count) == cellInfo.rowIndex)? count: (++count)), value.repeat); +} + } + } +}), removeBackground: (function (cells) { + _$jscoverage['plugins/table.core.js'][1143]++; + utils.each(cells, (function (cell) { + _$jscoverage['plugins/table.core.js'][1144]++; + cell.style.backgroundColor = ""; +})); +})}; + _$jscoverage['plugins/table.core.js'][1150]++; + function showError(e) { +} +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/template.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/template.js new file mode 100644 index 000000000..f46cd1d8b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/template.js @@ -0,0 +1,108 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/template.js']) { + _$jscoverage['plugins/template.js'] = []; + _$jscoverage['plugins/template.js'][2] = 0; + _$jscoverage['plugins/template.js'][3] = 0; + _$jscoverage['plugins/template.js'][5] = 0; + _$jscoverage['plugins/template.js'][8] = 0; + _$jscoverage['plugins/template.js'][9] = 0; + _$jscoverage['plugins/template.js'][11] = 0; + _$jscoverage['plugins/template.js'][12] = 0; + _$jscoverage['plugins/template.js'][13] = 0; + _$jscoverage['plugins/template.js'][16] = 0; + _$jscoverage['plugins/template.js'][18] = 0; + _$jscoverage['plugins/template.js'][19] = 0; + _$jscoverage['plugins/template.js'][20] = 0; + _$jscoverage['plugins/template.js'][21] = 0; + _$jscoverage['plugins/template.js'][22] = 0; + _$jscoverage['plugins/template.js'][23] = 0; + _$jscoverage['plugins/template.js'][24] = 0; + _$jscoverage['plugins/template.js'][27] = 0; + _$jscoverage['plugins/template.js'][28] = 0; +} +_$jscoverage['plugins/template.js'].source = ["","UE.plugins['template'] = function () {"," UE.commands['template'] = {"," execCommand:function (cmd, obj) {"," obj.html && this.execCommand(\"inserthtml\", obj.html);"," }"," };"," this.addListener(\"click\", function (type, evt) {"," var el = evt.target || evt.srcElement,"," range = this.selection.getRange();"," var tnode = domUtils.findParent(el, function (node) {"," if (node.className && domUtils.hasClass(node, \"ue_t\")) {"," return node;"," }"," }, true);"," tnode && range.selectNode(tnode).shrinkBoundary().select();"," });"," this.addListener(\"keydown\", function (type, evt) {"," var range = this.selection.getRange();"," if (!range.collapsed) {"," if (!evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {"," var tnode = domUtils.findParent(range.startContainer, function (node) {"," if (node.className && domUtils.hasClass(node, \"ue_t\")) {"," return node;"," }"," }, true);"," if (tnode) {"," domUtils.removeClasses(tnode, [\"ue_t\"]);"," }"," }"," }"," });","};"]; +_$jscoverage['plugins/template.js'][2]++; +UE.plugins.template = (function () { + _$jscoverage['plugins/template.js'][3]++; + UE.commands.template = {execCommand: (function (cmd, obj) { + _$jscoverage['plugins/template.js'][5]++; + (obj.html && this.execCommand("inserthtml", obj.html)); +})}; + _$jscoverage['plugins/template.js'][8]++; + this.addListener("click", (function (type, evt) { + _$jscoverage['plugins/template.js'][9]++; + var el = (evt.target || evt.srcElement), range = this.selection.getRange(); + _$jscoverage['plugins/template.js'][11]++; + var tnode = domUtils.findParent(el, (function (node) { + _$jscoverage['plugins/template.js'][12]++; + if ((node.className && domUtils.hasClass(node, "ue_t"))) { + _$jscoverage['plugins/template.js'][13]++; + return node; + } +}), true); + _$jscoverage['plugins/template.js'][16]++; + (tnode && range.selectNode(tnode).shrinkBoundary().select()); +})); + _$jscoverage['plugins/template.js'][18]++; + this.addListener("keydown", (function (type, evt) { + _$jscoverage['plugins/template.js'][19]++; + var range = this.selection.getRange(); + _$jscoverage['plugins/template.js'][20]++; + if ((! range.collapsed)) { + _$jscoverage['plugins/template.js'][21]++; + if (((! evt.ctrlKey) && (! evt.metaKey) && (! evt.shiftKey) && (! evt.altKey))) { + _$jscoverage['plugins/template.js'][22]++; + var tnode = domUtils.findParent(range.startContainer, (function (node) { + _$jscoverage['plugins/template.js'][23]++; + if ((node.className && domUtils.hasClass(node, "ue_t"))) { + _$jscoverage['plugins/template.js'][24]++; + return node; + } +}), true); + _$jscoverage['plugins/template.js'][27]++; + if (tnode) { + _$jscoverage['plugins/template.js'][28]++; + domUtils.removeClasses(tnode, ["ue_t"]); + } + } + } +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/time.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/time.js new file mode 100644 index 000000000..d9a0725a5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/time.js @@ -0,0 +1,53 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/time.js']) { + _$jscoverage['plugins/time.js'] = []; + _$jscoverage['plugins/time.js'][28] = 0; + _$jscoverage['plugins/time.js'][30] = 0; + _$jscoverage['plugins/time.js'][31] = 0; +} +_$jscoverage['plugins/time.js'].source = ["/**"," * 插入时间和日期"," * @file"," * @since 1.2.6.1"," */","","/**"," * 插入当前时间,插入的格式:12:59:59"," * @command time"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'time');"," * ```"," */","","/**"," * 插入当前日期,插入格式:2013-08-30"," * @command date"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'date');"," * ```"," */","UE.commands['time'] = UE.commands[\"date\"] = {"," execCommand : function(cmd){"," var date = new Date;"," this.execCommand('insertHtml',cmd == \"time\" ?"," (date.getHours()+\":\"+ (date.getMinutes()<10 ? \"0\"+date.getMinutes() : date.getMinutes())+\":\"+(date.getSeconds()<10 ? \"0\"+date.getSeconds() : date.getSeconds())) :"," (date.getFullYear()+\"-\"+((date.getMonth()+1)<10 ? \"0\"+(date.getMonth()+1) : date.getMonth()+1)+\"-\"+(date.getDate()<10?\"0\"+date.getDate():date.getDate())));"," }","};","","",""]; +_$jscoverage['plugins/time.js'][28]++; +UE.commands.time = (UE.commands.date = {execCommand: (function (cmd) { + _$jscoverage['plugins/time.js'][30]++; + var date = new Date(); + _$jscoverage['plugins/time.js'][31]++; + this.execCommand("insertHtml", ((cmd == "time")? (date.getHours() + ":" + ((date.getMinutes() < 10)? ("0" + date.getMinutes()): date.getMinutes()) + ":" + ((date.getSeconds() < 10)? ("0" + date.getSeconds()): date.getSeconds())): (date.getFullYear() + "-" + (((date.getMonth() + 1) < 10)? ("0" + (date.getMonth() + 1)): (date.getMonth() + 1)) + "-" + ((date.getDate() < 10)? ("0" + date.getDate()): date.getDate())))); +})}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/undo.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/undo.js new file mode 100644 index 000000000..a4e260b61 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/undo.js @@ -0,0 +1,568 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/undo.js']) { + _$jscoverage['plugins/undo.js'] = []; + _$jscoverage['plugins/undo.js'][10] = 0; + _$jscoverage['plugins/undo.js'][11] = 0; + _$jscoverage['plugins/undo.js'][12] = 0; + _$jscoverage['plugins/undo.js'][16] = 0; + _$jscoverage['plugins/undo.js'][19] = 0; + _$jscoverage['plugins/undo.js'][20] = 0; + _$jscoverage['plugins/undo.js'][21] = 0; + _$jscoverage['plugins/undo.js'][22] = 0; + _$jscoverage['plugins/undo.js'][23] = 0; + _$jscoverage['plugins/undo.js'][24] = 0; + _$jscoverage['plugins/undo.js'][25] = 0; + _$jscoverage['plugins/undo.js'][27] = 0; + _$jscoverage['plugins/undo.js'][30] = 0; + _$jscoverage['plugins/undo.js'][31] = 0; + _$jscoverage['plugins/undo.js'][32] = 0; + _$jscoverage['plugins/undo.js'][34] = 0; + _$jscoverage['plugins/undo.js'][35] = 0; + _$jscoverage['plugins/undo.js'][37] = 0; + _$jscoverage['plugins/undo.js'][40] = 0; + _$jscoverage['plugins/undo.js'][41] = 0; + _$jscoverage['plugins/undo.js'][42] = 0; + _$jscoverage['plugins/undo.js'][43] = 0; + _$jscoverage['plugins/undo.js'][44] = 0; + _$jscoverage['plugins/undo.js'][45] = 0; + _$jscoverage['plugins/undo.js'][46] = 0; + _$jscoverage['plugins/undo.js'][47] = 0; + _$jscoverage['plugins/undo.js'][48] = 0; + _$jscoverage['plugins/undo.js'][49] = 0; + _$jscoverage['plugins/undo.js'][51] = 0; + _$jscoverage['plugins/undo.js'][52] = 0; + _$jscoverage['plugins/undo.js'][53] = 0; + _$jscoverage['plugins/undo.js'][54] = 0; + _$jscoverage['plugins/undo.js'][57] = 0; + _$jscoverage['plugins/undo.js'][60] = 0; + _$jscoverage['plugins/undo.js'][61] = 0; + _$jscoverage['plugins/undo.js'][62] = 0; + _$jscoverage['plugins/undo.js'][63] = 0; + _$jscoverage['plugins/undo.js'][64] = 0; + _$jscoverage['plugins/undo.js'][65] = 0; + _$jscoverage['plugins/undo.js'][68] = 0; + _$jscoverage['plugins/undo.js'][72] = 0; + _$jscoverage['plugins/undo.js'][73] = 0; + _$jscoverage['plugins/undo.js'][74] = 0; + _$jscoverage['plugins/undo.js'][75] = 0; + _$jscoverage['plugins/undo.js'][76] = 0; + _$jscoverage['plugins/undo.js'][77] = 0; + _$jscoverage['plugins/undo.js'][78] = 0; + _$jscoverage['plugins/undo.js'][81] = 0; + _$jscoverage['plugins/undo.js'][82] = 0; + _$jscoverage['plugins/undo.js'][84] = 0; + _$jscoverage['plugins/undo.js'][85] = 0; + _$jscoverage['plugins/undo.js'][86] = 0; + _$jscoverage['plugins/undo.js'][87] = 0; + _$jscoverage['plugins/undo.js'][92] = 0; + _$jscoverage['plugins/undo.js'][93] = 0; + _$jscoverage['plugins/undo.js'][94] = 0; + _$jscoverage['plugins/undo.js'][97] = 0; + _$jscoverage['plugins/undo.js'][98] = 0; + _$jscoverage['plugins/undo.js'][100] = 0; + _$jscoverage['plugins/undo.js'][103] = 0; + _$jscoverage['plugins/undo.js'][104] = 0; + _$jscoverage['plugins/undo.js'][105] = 0; + _$jscoverage['plugins/undo.js'][107] = 0; + _$jscoverage['plugins/undo.js'][108] = 0; + _$jscoverage['plugins/undo.js'][109] = 0; + _$jscoverage['plugins/undo.js'][110] = 0; + _$jscoverage['plugins/undo.js'][111] = 0; + _$jscoverage['plugins/undo.js'][112] = 0; + _$jscoverage['plugins/undo.js'][116] = 0; + _$jscoverage['plugins/undo.js'][118] = 0; + _$jscoverage['plugins/undo.js'][123] = 0; + _$jscoverage['plugins/undo.js'][124] = 0; + _$jscoverage['plugins/undo.js'][125] = 0; + _$jscoverage['plugins/undo.js'][128] = 0; + _$jscoverage['plugins/undo.js'][131] = 0; + _$jscoverage['plugins/undo.js'][133] = 0; + _$jscoverage['plugins/undo.js'][134] = 0; + _$jscoverage['plugins/undo.js'][136] = 0; + _$jscoverage['plugins/undo.js'][137] = 0; + _$jscoverage['plugins/undo.js'][139] = 0; + _$jscoverage['plugins/undo.js'][140] = 0; + _$jscoverage['plugins/undo.js'][142] = 0; + _$jscoverage['plugins/undo.js'][145] = 0; + _$jscoverage['plugins/undo.js'][146] = 0; + _$jscoverage['plugins/undo.js'][147] = 0; + _$jscoverage['plugins/undo.js'][149] = 0; + _$jscoverage['plugins/undo.js'][150] = 0; + _$jscoverage['plugins/undo.js'][151] = 0; + _$jscoverage['plugins/undo.js'][152] = 0; + _$jscoverage['plugins/undo.js'][153] = 0; + _$jscoverage['plugins/undo.js'][154] = 0; + _$jscoverage['plugins/undo.js'][156] = 0; + _$jscoverage['plugins/undo.js'][157] = 0; + _$jscoverage['plugins/undo.js'][158] = 0; + _$jscoverage['plugins/undo.js'][162] = 0; + _$jscoverage['plugins/undo.js'][163] = 0; + _$jscoverage['plugins/undo.js'][164] = 0; + _$jscoverage['plugins/undo.js'][165] = 0; + _$jscoverage['plugins/undo.js'][168] = 0; + _$jscoverage['plugins/undo.js'][169] = 0; + _$jscoverage['plugins/undo.js'][170] = 0; + _$jscoverage['plugins/undo.js'][173] = 0; + _$jscoverage['plugins/undo.js'][174] = 0; + _$jscoverage['plugins/undo.js'][176] = 0; + _$jscoverage['plugins/undo.js'][177] = 0; + _$jscoverage['plugins/undo.js'][178] = 0; + _$jscoverage['plugins/undo.js'][181] = 0; + _$jscoverage['plugins/undo.js'][183] = 0; + _$jscoverage['plugins/undo.js'][186] = 0; + _$jscoverage['plugins/undo.js'][191] = 0; + _$jscoverage['plugins/undo.js'][200] = 0; + _$jscoverage['plugins/undo.js'][201] = 0; + _$jscoverage['plugins/undo.js'][202] = 0; + _$jscoverage['plugins/undo.js'][203] = 0; + _$jscoverage['plugins/undo.js'][205] = 0; + _$jscoverage['plugins/undo.js'][206] = 0; + _$jscoverage['plugins/undo.js'][210] = 0; + _$jscoverage['plugins/undo.js'][215] = 0; + _$jscoverage['plugins/undo.js'][216] = 0; + _$jscoverage['plugins/undo.js'][218] = 0; + _$jscoverage['plugins/undo.js'][219] = 0; + _$jscoverage['plugins/undo.js'][220] = 0; + _$jscoverage['plugins/undo.js'][221] = 0; + _$jscoverage['plugins/undo.js'][222] = 0; + _$jscoverage['plugins/undo.js'][224] = 0; + _$jscoverage['plugins/undo.js'][225] = 0; + _$jscoverage['plugins/undo.js'][226] = 0; + _$jscoverage['plugins/undo.js'][227] = 0; + _$jscoverage['plugins/undo.js'][229] = 0; + _$jscoverage['plugins/undo.js'][230] = 0; + _$jscoverage['plugins/undo.js'][232] = 0; + _$jscoverage['plugins/undo.js'][233] = 0; + _$jscoverage['plugins/undo.js'][235] = 0; + _$jscoverage['plugins/undo.js'][236] = 0; + _$jscoverage['plugins/undo.js'][237] = 0; + _$jscoverage['plugins/undo.js'][238] = 0; + _$jscoverage['plugins/undo.js'][240] = 0; + _$jscoverage['plugins/undo.js'][241] = 0; + _$jscoverage['plugins/undo.js'][242] = 0; + _$jscoverage['plugins/undo.js'][243] = 0; + _$jscoverage['plugins/undo.js'][244] = 0; + _$jscoverage['plugins/undo.js'][245] = 0; + _$jscoverage['plugins/undo.js'][248] = 0; + _$jscoverage['plugins/undo.js'][250] = 0; + _$jscoverage['plugins/undo.js'][253] = 0; + _$jscoverage['plugins/undo.js'][254] = 0; + _$jscoverage['plugins/undo.js'][255] = 0; + _$jscoverage['plugins/undo.js'][256] = 0; + _$jscoverage['plugins/undo.js'][260] = 0; + _$jscoverage['plugins/undo.js'][261] = 0; + _$jscoverage['plugins/undo.js'][262] = 0; + _$jscoverage['plugins/undo.js'][263] = 0; + _$jscoverage['plugins/undo.js'][264] = 0; + _$jscoverage['plugins/undo.js'][265] = 0; + _$jscoverage['plugins/undo.js'][266] = 0; + _$jscoverage['plugins/undo.js'][267] = 0; +} +_$jscoverage['plugins/undo.js'].source = ["///import core","///commands 撤销和重做","///commandsName Undo,Redo","///commandsTitle 撤销,重做","/*"," * @description 回退"," * @author zhanyi"," */","","UE.plugins['undo'] = function () {"," var saveSceneTimer;"," var me = this,"," maxUndoCount = me.options.maxUndoCount || 20,"," maxInputCount = me.options.maxInputCount || 20,"," fillchar = new RegExp(domUtils.fillChar + '|<\\/hr>', 'gi');// ie会产生多余的</hr>"," var noNeedFillCharTags = {"," ol:1,ul:1,table:1,tbody:1,tr:1,body:1"," };"," var orgState = me.options.autoClearEmptyNode;"," function compareAddr(indexA, indexB) {"," if (indexA.length != indexB.length)"," return 0;"," for (var i = 0, l = indexA.length; i < l; i++) {"," if (indexA[i] != indexB[i])"," return 0"," }"," return 1;"," }",""," function compareRangeAddress(rngAddrA, rngAddrB) {"," if (rngAddrA.collapsed != rngAddrB.collapsed) {"," return 0;"," }"," if (!compareAddr(rngAddrA.startAddress, rngAddrB.startAddress) || !compareAddr(rngAddrA.endAddress, rngAddrB.endAddress)) {"," return 0;"," }"," return 1;"," }",""," function UndoManager() {"," this.list = [];"," this.index = 0;"," this.hasUndo = false;"," this.hasRedo = false;"," this.undo = function () {"," if (this.hasUndo) {"," if (!this.list[this.index - 1] && this.list.length == 1) {"," this.reset();"," return;"," }"," while (this.list[this.index].content == this.list[this.index - 1].content) {"," this.index--;"," if (this.index == 0) {"," return this.restore(0);"," }"," }"," this.restore(--this.index);"," }"," };"," this.redo = function () {"," if (this.hasRedo) {"," while (this.list[this.index].content == this.list[this.index + 1].content) {"," this.index++;"," if (this.index == this.list.length - 1) {"," return this.restore(this.index);"," }"," }"," this.restore(++this.index);"," }"," };",""," this.restore = function () {"," var me = this.editor;"," var scene = this.list[this.index];"," var root = UE.htmlparser(scene.content.replace(fillchar, ''));"," me.options.autoClearEmptyNode = false;"," me.filterInputRule(root);"," me.options.autoClearEmptyNode = orgState;"," //trace:873"," //去掉展位符"," me.document.body.innerHTML = root.toHtml();"," me.fireEvent('afterscencerestore');"," //处理undo后空格不展位的问题"," if (browser.ie) {"," utils.each(domUtils.getElementsByTagName(me.document,'td th caption p'),function(node){"," if(domUtils.isEmptyNode(node)){"," domUtils.fillNode(me.document, node);"," }"," })"," }",""," try{"," var rng = new dom.Range(me.document).moveToAddress(scene.address);"," rng.select(noNeedFillCharTags[rng.startContainer.nodeName.toLowerCase()]);"," }catch(e){}",""," this.update();"," this.clearKey();"," //不能把自己reset了"," me.fireEvent('reset', true);"," };",""," this.getScene = function () {"," var me = this.editor;"," var rng = me.selection.getRange(),"," rngAddress = rng.createAddress(false,true);"," me.fireEvent('beforegetscene');"," var root = UE.htmlparser(me.body.innerHTML);"," me.options.autoClearEmptyNode = false;"," me.filterOutputRule(root);"," me.options.autoClearEmptyNode = orgState;"," var cont = root.toHtml();"," //trace:3461"," //这个会引起回退时导致空格丢失的情况","// browser.ie && (cont = cont.replace(/>&nbsp;</g, '><').replace(/\\s*</g, '<').replace(/>\\s*/g, '>'));"," me.fireEvent('aftergetscene');",""," return {"," address:rngAddress,"," content:cont"," }"," };"," this.save = function (notCompareRange,notSetCursor) {"," clearTimeout(saveSceneTimer);"," var currentScene = this.getScene(notSetCursor),"," lastScene = this.list[this.index];"," //内容相同位置相同不存"," if (lastScene && lastScene.content == currentScene.content &&"," ( notCompareRange ? 1 : compareRangeAddress(lastScene.address, currentScene.address) )"," ) {"," return;"," }"," this.list = this.list.slice(0, this.index + 1);"," this.list.push(currentScene);"," //如果大于最大数量了,就把最前的剔除"," if (this.list.length > maxUndoCount) {"," this.list.shift();"," }"," this.index = this.list.length - 1;"," this.clearKey();"," //跟新undo/redo状态"," this.update();",""," };"," this.update = function () {"," this.hasRedo = !!this.list[this.index + 1];"," this.hasUndo = !!this.list[this.index - 1];"," };"," this.reset = function () {"," this.list = [];"," this.index = 0;"," this.hasUndo = false;"," this.hasRedo = false;"," this.clearKey();"," };"," this.clearKey = function () {"," keycont = 0;"," lastKeyCode = null;"," };"," }",""," me.undoManger = new UndoManager();"," me.undoManger.editor = me;"," function saveScene() {"," this.undoManger.save();"," }",""," me.addListener('saveScene', function () {"," var args = Array.prototype.splice.call(arguments,1);"," this.undoManger.save.apply(this.undoManger,args);"," });",""," me.addListener('beforeexeccommand', saveScene);"," me.addListener('afterexeccommand', saveScene);",""," me.addListener('reset', function (type, exclude) {"," if (!exclude) {"," this.undoManger.reset();"," }"," });"," me.commands['redo'] = me.commands['undo'] = {"," execCommand:function (cmdName) {"," this.undoManger[cmdName]();"," },"," queryCommandState:function (cmdName) {"," return this.undoManger['has' + (cmdName.toLowerCase() == 'undo' ? 'Undo' : 'Redo')] ? 0 : -1;"," },"," notNeedUndo:1"," };",""," var keys = {"," // /*Backspace*/ 8:1, /*Delete*/ 46:1,"," /*Shift*/ 16:1, /*Ctrl*/ 17:1, /*Alt*/ 18:1,"," 37:1, 38:1, 39:1, 40:1",""," },"," keycont = 0,"," lastKeyCode;"," //输入法状态下不计算字符数"," var inputType = false;"," me.addListener('ready', function () {"," domUtils.on(this.body, 'compositionstart', function () {"," inputType = true;"," });"," domUtils.on(this.body, 'compositionend', function () {"," inputType = false;"," })"," });"," //快捷键"," me.addshortcutkey({"," \"Undo\":\"ctrl+90\", //undo"," \"Redo\":\"ctrl+89\" //redo",""," });"," var isCollapsed = true;"," me.addListener('keydown', function (type, evt) {",""," var me = this;"," var keyCode = evt.keyCode || evt.which;"," if (!keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {"," if (inputType)"," return;",""," if(!me.selection.getRange().collapsed){"," me.undoManger.save(false,true);"," isCollapsed = false;"," return;"," }"," if (me.undoManger.list.length == 0) {"," me.undoManger.save(true);"," }"," clearTimeout(saveSceneTimer);"," function save(cont){",""," if (cont.selection.getRange().collapsed)"," cont.fireEvent('contentchange');"," cont.undoManger.save(false,true);"," cont.fireEvent('selectionchange');"," }"," saveSceneTimer = setTimeout(function(){"," if(inputType){"," var interalTimer = setInterval(function(){"," if(!inputType){"," save(me);"," clearInterval(interalTimer)"," }"," },300)"," return;"," }"," save(me);"," },200);",""," lastKeyCode = keyCode;"," keycont++;"," if (keycont >= maxInputCount ) {"," save(me)"," }"," }"," });"," me.addListener('keyup', function (type, evt) {"," var keyCode = evt.keyCode || evt.which;"," if (!keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {"," if (inputType)"," return;"," if(!isCollapsed){"," this.undoManger.save(false,true);"," isCollapsed = true;"," }"," }"," });","","};"]; +_$jscoverage['plugins/undo.js'][10]++; +UE.plugins.undo = (function () { + _$jscoverage['plugins/undo.js'][11]++; + var saveSceneTimer; + _$jscoverage['plugins/undo.js'][12]++; + var me = this, maxUndoCount = (me.options.maxUndoCount || 20), maxInputCount = (me.options.maxInputCount || 20), fillchar = new RegExp((domUtils.fillChar + "|"), "gi"); + _$jscoverage['plugins/undo.js'][16]++; + var noNeedFillCharTags = {ol: 1, ul: 1, table: 1, tbody: 1, tr: 1, body: 1}; + _$jscoverage['plugins/undo.js'][19]++; + var orgState = me.options.autoClearEmptyNode; + _$jscoverage['plugins/undo.js'][20]++; + function compareAddr(indexA, indexB) { + _$jscoverage['plugins/undo.js'][21]++; + if ((indexA.length != indexB.length)) { + _$jscoverage['plugins/undo.js'][22]++; + return 0; + } + _$jscoverage['plugins/undo.js'][23]++; + for (var i = 0, l = indexA.length; (i < l); (i++)) { + _$jscoverage['plugins/undo.js'][24]++; + if ((indexA[i] != indexB[i])) { + _$jscoverage['plugins/undo.js'][25]++; + return 0; + } +} + _$jscoverage['plugins/undo.js'][27]++; + return 1; +} + _$jscoverage['plugins/undo.js'][30]++; + function compareRangeAddress(rngAddrA, rngAddrB) { + _$jscoverage['plugins/undo.js'][31]++; + if ((rngAddrA.collapsed != rngAddrB.collapsed)) { + _$jscoverage['plugins/undo.js'][32]++; + return 0; + } + _$jscoverage['plugins/undo.js'][34]++; + if (((! compareAddr(rngAddrA.startAddress, rngAddrB.startAddress)) || (! compareAddr(rngAddrA.endAddress, rngAddrB.endAddress)))) { + _$jscoverage['plugins/undo.js'][35]++; + return 0; + } + _$jscoverage['plugins/undo.js'][37]++; + return 1; +} + _$jscoverage['plugins/undo.js'][40]++; + function UndoManager() { + _$jscoverage['plugins/undo.js'][41]++; + this.list = []; + _$jscoverage['plugins/undo.js'][42]++; + this.index = 0; + _$jscoverage['plugins/undo.js'][43]++; + this.hasUndo = false; + _$jscoverage['plugins/undo.js'][44]++; + this.hasRedo = false; + _$jscoverage['plugins/undo.js'][45]++; + this.undo = (function () { + _$jscoverage['plugins/undo.js'][46]++; + if (this.hasUndo) { + _$jscoverage['plugins/undo.js'][47]++; + if (((! this.list[(this.index - 1)]) && (this.list.length == 1))) { + _$jscoverage['plugins/undo.js'][48]++; + this.reset(); + _$jscoverage['plugins/undo.js'][49]++; + return; + } + _$jscoverage['plugins/undo.js'][51]++; + while ((this.list[this.index].content == this.list[(this.index - 1)].content)) { + _$jscoverage['plugins/undo.js'][52]++; + (this.index--); + _$jscoverage['plugins/undo.js'][53]++; + if ((this.index == 0)) { + _$jscoverage['plugins/undo.js'][54]++; + return this.restore(0); + } +} + _$jscoverage['plugins/undo.js'][57]++; + this.restore((--this.index)); + } +}); + _$jscoverage['plugins/undo.js'][60]++; + this.redo = (function () { + _$jscoverage['plugins/undo.js'][61]++; + if (this.hasRedo) { + _$jscoverage['plugins/undo.js'][62]++; + while ((this.list[this.index].content == this.list[(this.index + 1)].content)) { + _$jscoverage['plugins/undo.js'][63]++; + (this.index++); + _$jscoverage['plugins/undo.js'][64]++; + if ((this.index == (this.list.length - 1))) { + _$jscoverage['plugins/undo.js'][65]++; + return this.restore(this.index); + } +} + _$jscoverage['plugins/undo.js'][68]++; + this.restore((++this.index)); + } +}); + _$jscoverage['plugins/undo.js'][72]++; + this.restore = (function () { + _$jscoverage['plugins/undo.js'][73]++; + var me = this.editor; + _$jscoverage['plugins/undo.js'][74]++; + var scene = this.list[this.index]; + _$jscoverage['plugins/undo.js'][75]++; + var root = UE.htmlparser(scene.content.replace(fillchar, "")); + _$jscoverage['plugins/undo.js'][76]++; + me.options.autoClearEmptyNode = false; + _$jscoverage['plugins/undo.js'][77]++; + me.filterInputRule(root); + _$jscoverage['plugins/undo.js'][78]++; + me.options.autoClearEmptyNode = orgState; + _$jscoverage['plugins/undo.js'][81]++; + me.document.body.innerHTML = root.toHtml(); + _$jscoverage['plugins/undo.js'][82]++; + me.fireEvent("afterscencerestore"); + _$jscoverage['plugins/undo.js'][84]++; + if (browser.ie) { + _$jscoverage['plugins/undo.js'][85]++; + utils.each(domUtils.getElementsByTagName(me.document, "td th caption p"), (function (node) { + _$jscoverage['plugins/undo.js'][86]++; + if (domUtils.isEmptyNode(node)) { + _$jscoverage['plugins/undo.js'][87]++; + domUtils.fillNode(me.document, node); + } +})); + } + _$jscoverage['plugins/undo.js'][92]++; + try { + _$jscoverage['plugins/undo.js'][93]++; + var rng = new (dom.Range)(me.document).moveToAddress(scene.address); + _$jscoverage['plugins/undo.js'][94]++; + rng.select(noNeedFillCharTags[rng.startContainer.nodeName.toLowerCase()]); + } + catch (e) { + } + _$jscoverage['plugins/undo.js'][97]++; + this.update(); + _$jscoverage['plugins/undo.js'][98]++; + this.clearKey(); + _$jscoverage['plugins/undo.js'][100]++; + me.fireEvent("reset", true); +}); + _$jscoverage['plugins/undo.js'][103]++; + this.getScene = (function () { + _$jscoverage['plugins/undo.js'][104]++; + var me = this.editor; + _$jscoverage['plugins/undo.js'][105]++; + var rng = me.selection.getRange(), rngAddress = rng.createAddress(false, true); + _$jscoverage['plugins/undo.js'][107]++; + me.fireEvent("beforegetscene"); + _$jscoverage['plugins/undo.js'][108]++; + var root = UE.htmlparser(me.body.innerHTML); + _$jscoverage['plugins/undo.js'][109]++; + me.options.autoClearEmptyNode = false; + _$jscoverage['plugins/undo.js'][110]++; + me.filterOutputRule(root); + _$jscoverage['plugins/undo.js'][111]++; + me.options.autoClearEmptyNode = orgState; + _$jscoverage['plugins/undo.js'][112]++; + var cont = root.toHtml(); + _$jscoverage['plugins/undo.js'][116]++; + me.fireEvent("aftergetscene"); + _$jscoverage['plugins/undo.js'][118]++; + return ({address: rngAddress, content: cont}); +}); + _$jscoverage['plugins/undo.js'][123]++; + this.save = (function (notCompareRange, notSetCursor) { + _$jscoverage['plugins/undo.js'][124]++; + clearTimeout(saveSceneTimer); + _$jscoverage['plugins/undo.js'][125]++; + var currentScene = this.getScene(notSetCursor), lastScene = this.list[this.index]; + _$jscoverage['plugins/undo.js'][128]++; + if ((lastScene && (lastScene.content == currentScene.content) && (notCompareRange? 1: compareRangeAddress(lastScene.address, currentScene.address)))) { + _$jscoverage['plugins/undo.js'][131]++; + return; + } + _$jscoverage['plugins/undo.js'][133]++; + this.list = this.list.slice(0, (this.index + 1)); + _$jscoverage['plugins/undo.js'][134]++; + this.list.push(currentScene); + _$jscoverage['plugins/undo.js'][136]++; + if ((this.list.length > maxUndoCount)) { + _$jscoverage['plugins/undo.js'][137]++; + this.list.shift(); + } + _$jscoverage['plugins/undo.js'][139]++; + this.index = (this.list.length - 1); + _$jscoverage['plugins/undo.js'][140]++; + this.clearKey(); + _$jscoverage['plugins/undo.js'][142]++; + this.update(); +}); + _$jscoverage['plugins/undo.js'][145]++; + this.update = (function () { + _$jscoverage['plugins/undo.js'][146]++; + this.hasRedo = (! (! this.list[(this.index + 1)])); + _$jscoverage['plugins/undo.js'][147]++; + this.hasUndo = (! (! this.list[(this.index - 1)])); +}); + _$jscoverage['plugins/undo.js'][149]++; + this.reset = (function () { + _$jscoverage['plugins/undo.js'][150]++; + this.list = []; + _$jscoverage['plugins/undo.js'][151]++; + this.index = 0; + _$jscoverage['plugins/undo.js'][152]++; + this.hasUndo = false; + _$jscoverage['plugins/undo.js'][153]++; + this.hasRedo = false; + _$jscoverage['plugins/undo.js'][154]++; + this.clearKey(); +}); + _$jscoverage['plugins/undo.js'][156]++; + this.clearKey = (function () { + _$jscoverage['plugins/undo.js'][157]++; + keycont = 0; + _$jscoverage['plugins/undo.js'][158]++; + lastKeyCode = null; +}); +} + _$jscoverage['plugins/undo.js'][162]++; + me.undoManger = new UndoManager(); + _$jscoverage['plugins/undo.js'][163]++; + me.undoManger.editor = me; + _$jscoverage['plugins/undo.js'][164]++; + function saveScene() { + _$jscoverage['plugins/undo.js'][165]++; + this.undoManger.save(); +} + _$jscoverage['plugins/undo.js'][168]++; + me.addListener("saveScene", (function () { + _$jscoverage['plugins/undo.js'][169]++; + var args = Array.prototype.splice.call(arguments, 1); + _$jscoverage['plugins/undo.js'][170]++; + this.undoManger.save.apply(this.undoManger, args); +})); + _$jscoverage['plugins/undo.js'][173]++; + me.addListener("beforeexeccommand", saveScene); + _$jscoverage['plugins/undo.js'][174]++; + me.addListener("afterexeccommand", saveScene); + _$jscoverage['plugins/undo.js'][176]++; + me.addListener("reset", (function (type, exclude) { + _$jscoverage['plugins/undo.js'][177]++; + if ((! exclude)) { + _$jscoverage['plugins/undo.js'][178]++; + this.undoManger.reset(); + } +})); + _$jscoverage['plugins/undo.js'][181]++; + me.commands.redo = (me.commands.undo = {execCommand: (function (cmdName) { + _$jscoverage['plugins/undo.js'][183]++; + (this.undoManger[cmdName])(); +}), queryCommandState: (function (cmdName) { + _$jscoverage['plugins/undo.js'][186]++; + return (this.undoManger[("has" + ((cmdName.toLowerCase() == "undo")? "Undo": "Redo"))]? 0: -1); +}), notNeedUndo: 1}); + _$jscoverage['plugins/undo.js'][191]++; + var keys = {16: 1, 17: 1, 18: 1, 37: 1, 38: 1, 39: 1, 40: 1}, keycont = 0, lastKeyCode; + _$jscoverage['plugins/undo.js'][200]++; + var inputType = false; + _$jscoverage['plugins/undo.js'][201]++; + me.addListener("ready", (function () { + _$jscoverage['plugins/undo.js'][202]++; + domUtils.on(this.body, "compositionstart", (function () { + _$jscoverage['plugins/undo.js'][203]++; + inputType = true; +})); + _$jscoverage['plugins/undo.js'][205]++; + domUtils.on(this.body, "compositionend", (function () { + _$jscoverage['plugins/undo.js'][206]++; + inputType = false; +})); +})); + _$jscoverage['plugins/undo.js'][210]++; + me.addshortcutkey({"Undo": "ctrl+90", "Redo": "ctrl+89"}); + _$jscoverage['plugins/undo.js'][215]++; + var isCollapsed = true; + _$jscoverage['plugins/undo.js'][216]++; + me.addListener("keydown", (function (type, evt) { + _$jscoverage['plugins/undo.js'][218]++; + var me = this; + _$jscoverage['plugins/undo.js'][219]++; + var keyCode = (evt.keyCode || evt.which); + _$jscoverage['plugins/undo.js'][220]++; + if (((! keys[keyCode]) && (! evt.ctrlKey) && (! evt.metaKey) && (! evt.shiftKey) && (! evt.altKey))) { + _$jscoverage['plugins/undo.js'][221]++; + if (inputType) { + _$jscoverage['plugins/undo.js'][222]++; + return; + } + _$jscoverage['plugins/undo.js'][224]++; + if ((! me.selection.getRange().collapsed)) { + _$jscoverage['plugins/undo.js'][225]++; + me.undoManger.save(false, true); + _$jscoverage['plugins/undo.js'][226]++; + isCollapsed = false; + _$jscoverage['plugins/undo.js'][227]++; + return; + } + _$jscoverage['plugins/undo.js'][229]++; + if ((me.undoManger.list.length == 0)) { + _$jscoverage['plugins/undo.js'][230]++; + me.undoManger.save(true); + } + _$jscoverage['plugins/undo.js'][232]++; + clearTimeout(saveSceneTimer); + _$jscoverage['plugins/undo.js'][233]++; + function save(cont) { + _$jscoverage['plugins/undo.js'][235]++; + if (cont.selection.getRange().collapsed) { + _$jscoverage['plugins/undo.js'][236]++; + cont.fireEvent("contentchange"); + } + _$jscoverage['plugins/undo.js'][237]++; + cont.undoManger.save(false, true); + _$jscoverage['plugins/undo.js'][238]++; + cont.fireEvent("selectionchange"); +} + _$jscoverage['plugins/undo.js'][240]++; + saveSceneTimer = setTimeout((function () { + _$jscoverage['plugins/undo.js'][241]++; + if (inputType) { + _$jscoverage['plugins/undo.js'][242]++; + var interalTimer = setInterval((function () { + _$jscoverage['plugins/undo.js'][243]++; + if ((! inputType)) { + _$jscoverage['plugins/undo.js'][244]++; + save(me); + _$jscoverage['plugins/undo.js'][245]++; + clearInterval(interalTimer); + } +}), 300); + _$jscoverage['plugins/undo.js'][248]++; + return; + } + _$jscoverage['plugins/undo.js'][250]++; + save(me); +}), 200); + _$jscoverage['plugins/undo.js'][253]++; + lastKeyCode = keyCode; + _$jscoverage['plugins/undo.js'][254]++; + (keycont++); + _$jscoverage['plugins/undo.js'][255]++; + if ((keycont >= maxInputCount)) { + _$jscoverage['plugins/undo.js'][256]++; + save(me); + } + } +})); + _$jscoverage['plugins/undo.js'][260]++; + me.addListener("keyup", (function (type, evt) { + _$jscoverage['plugins/undo.js'][261]++; + var keyCode = (evt.keyCode || evt.which); + _$jscoverage['plugins/undo.js'][262]++; + if (((! keys[keyCode]) && (! evt.ctrlKey) && (! evt.metaKey) && (! evt.shiftKey) && (! evt.altKey))) { + _$jscoverage['plugins/undo.js'][263]++; + if (inputType) { + _$jscoverage['plugins/undo.js'][264]++; + return; + } + _$jscoverage['plugins/undo.js'][265]++; + if ((! isCollapsed)) { + _$jscoverage['plugins/undo.js'][266]++; + this.undoManger.save(false, true); + _$jscoverage['plugins/undo.js'][267]++; + isCollapsed = true; + } + } +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/video.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/video.js new file mode 100644 index 000000000..95e37bd9d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/video.js @@ -0,0 +1,138 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/video.js']) { + _$jscoverage['plugins/video.js'] = []; + _$jscoverage['plugins/video.js'][7] = 0; + _$jscoverage['plugins/video.js'][9] = 0; + _$jscoverage['plugins/video.js'][21] = 0; + _$jscoverage['plugins/video.js'][22] = 0; + _$jscoverage['plugins/video.js'][33] = 0; + _$jscoverage['plugins/video.js'][34] = 0; + _$jscoverage['plugins/video.js'][35] = 0; + _$jscoverage['plugins/video.js'][37] = 0; + _$jscoverage['plugins/video.js'][38] = 0; + _$jscoverage['plugins/video.js'][43] = 0; + _$jscoverage['plugins/video.js'][44] = 0; + _$jscoverage['plugins/video.js'][46] = 0; + _$jscoverage['plugins/video.js'][47] = 0; + _$jscoverage['plugins/video.js'][93] = 0; + _$jscoverage['plugins/video.js'][95] = 0; + _$jscoverage['plugins/video.js'][96] = 0; + _$jscoverage['plugins/video.js'][97] = 0; + _$jscoverage['plugins/video.js'][98] = 0; + _$jscoverage['plugins/video.js'][99] = 0; + _$jscoverage['plugins/video.js'][101] = 0; + _$jscoverage['plugins/video.js'][102] = 0; + _$jscoverage['plugins/video.js'][103] = 0; + _$jscoverage['plugins/video.js'][104] = 0; + _$jscoverage['plugins/video.js'][105] = 0; + _$jscoverage['plugins/video.js'][106] = 0; + _$jscoverage['plugins/video.js'][107] = 0; + _$jscoverage['plugins/video.js'][111] = 0; + _$jscoverage['plugins/video.js'][113] = 0; +} +_$jscoverage['plugins/video.js'].source = ["/**"," * video插件, 为UEditor提供视频插入支持"," * @file"," * @since 1.2.6.1"," */","","UE.plugins['video'] = function (){",""," var me =this,"," div;",""," /*"," * 创建插入视频字符窜"," * @param url 视频地址"," * @param width 视频宽度"," * @param height 视频高度"," * @param align 视频对齐"," * @param toEmbed 是否以flash代替显示"," * @param addParagraph 是否需要添加P 标签"," */"," function creatInsertStr(url,width,height,id,align,toEmbed){"," return !toEmbed ?",""," '<img ' + (id ? 'id=\"' + id+'\"' : '') + ' width=\"'+ width +'\" height=\"' + height + '\" _url=\"'+url+'\" class=\"edui-faked-video\"' +"," ' src=\"' + me.options.UEDITOR_HOME_URL+'themes/default/images/spacer.gif\" style=\"background:url('+me.options.UEDITOR_HOME_URL+'themes/default/images/videologo.gif) no-repeat center center; border:1px solid gray;'+(align ? 'float:' + align + ';': '')+'\" />'",""," :"," '<embed type=\"application/x-shockwave-flash\" class=\"edui-faked-video\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\"' +"," ' src=\"' + url + '\" width=\"' + width + '\" height=\"' + height + '\"' + (align ? ' style=\"float:' + align + '\"': '') +"," ' wmode=\"transparent\" play=\"true\" loop=\"false\" menu=\"false\" allowscriptaccess=\"never\" allowfullscreen=\"true\" >';"," }",""," function switchImgAndEmbed(root,img2embed){"," utils.each(root.getNodesByTagName(img2embed ? 'img' : 'embed'),function(node){"," if(node.getAttr('class') == 'edui-faked-video'){",""," var html = creatInsertStr( img2embed ? node.getAttr('_url') : node.getAttr('src'),node.getAttr('width'),node.getAttr('height'),null,node.getStyle('float') || '',img2embed);"," node.parentNode.replaceChild(UE.uNode.createElement(html),node)"," }"," })"," }",""," me.addOutputRule(function(root){"," switchImgAndEmbed(root,true)"," });"," me.addInputRule(function(root){"," switchImgAndEmbed(root)"," });",""," /**"," * 插入视频"," * @command insertvideo"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param { KeyValueMap } videoObj 键值对对象, 描述一个视频的所有属性"," * @example"," * ```javascript"," *"," * //editor 是编辑器实例"," * editor.execCommand( 'insertvideo', {"," *"," * } );"," * ```"," */",""," /**"," * 插入视频"," * @command insertvideo"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @param { Array } videoArr 需要插入的视频的数组, 其中的每一个元素都是一个键值对对象, 描述了一个视频的所有属性"," * @example"," * ```javascript"," *"," * //editor 是编辑器实例"," * editor.execCommand( 'insertvideo', [ ] );"," * ```"," */",""," /**"," * 查询当前光标所在处是否是一个视频"," * @command insertvideo"," * @method queryCommandState"," * @param { String } cmd 需要查询的命令字符串"," * @return { int } 如果当前光标所在处的元素是一个视频对象, 则返回1,否则返回0"," * @example"," * ```javascript"," *"," * //editor 是编辑器实例"," * editor.queryCommandState( 'insertvideo' );"," * ```"," */"," me.commands[\"insertvideo\"] = {"," execCommand: function (cmd, videoObjs){"," videoObjs = utils.isArray(videoObjs)?videoObjs:[videoObjs];"," var html = [],id = 'tmpVedio';"," for(var i=0,vi,len = videoObjs.length;i<len;i++){"," vi = videoObjs[i];"," html.push(creatInsertStr( vi.url, vi.width || 420, vi.height || 280, id + i,null,false));"," }"," me.execCommand(\"inserthtml\",html.join(\"\"),true);"," var rng = this.selection.getRange();"," for(var i= 0,len=videoObjs.length;i<len;i++){"," var img = this.document.getElementById('tmpVedio'+i);"," domUtils.removeAttributes(img,'id');"," rng.selectNode(img).select();"," me.execCommand('imagefloat',videoObjs[i].align)"," }"," },"," queryCommandState : function(){"," var img = me.selection.getRange().getClosedNode(),"," flag = img && (img.className == \"edui-faked-video\");"," return flag ? 1 : 0;"," }"," };","};"]; +_$jscoverage['plugins/video.js'][7]++; +UE.plugins.video = (function () { + _$jscoverage['plugins/video.js'][9]++; + var me = this, div; + _$jscoverage['plugins/video.js'][21]++; + function creatInsertStr(url, width, height, id, align, toEmbed) { + _$jscoverage['plugins/video.js'][22]++; + return ((! toEmbed)? (""): ("")); +} + _$jscoverage['plugins/video.js'][33]++; + function switchImgAndEmbed(root, img2embed) { + _$jscoverage['plugins/video.js'][34]++; + utils.each(root.getNodesByTagName((img2embed? "img": "embed")), (function (node) { + _$jscoverage['plugins/video.js'][35]++; + if ((node.getAttr("class") == "edui-faked-video")) { + _$jscoverage['plugins/video.js'][37]++; + var html = creatInsertStr((img2embed? node.getAttr("_url"): node.getAttr("src")), node.getAttr("width"), node.getAttr("height"), null, (node.getStyle("float") || ""), img2embed); + _$jscoverage['plugins/video.js'][38]++; + node.parentNode.replaceChild(UE.uNode.createElement(html), node); + } +})); +} + _$jscoverage['plugins/video.js'][43]++; + me.addOutputRule((function (root) { + _$jscoverage['plugins/video.js'][44]++; + switchImgAndEmbed(root, true); +})); + _$jscoverage['plugins/video.js'][46]++; + me.addInputRule((function (root) { + _$jscoverage['plugins/video.js'][47]++; + switchImgAndEmbed(root); +})); + _$jscoverage['plugins/video.js'][93]++; + me.commands.insertvideo = {execCommand: (function (cmd, videoObjs) { + _$jscoverage['plugins/video.js'][95]++; + videoObjs = (utils.isArray(videoObjs)? videoObjs: [videoObjs]); + _$jscoverage['plugins/video.js'][96]++; + var html = [], id = "tmpVedio"; + _$jscoverage['plugins/video.js'][97]++; + for (var i = 0, vi, len = videoObjs.length; (i < len); (i++)) { + _$jscoverage['plugins/video.js'][98]++; + vi = videoObjs[i]; + _$jscoverage['plugins/video.js'][99]++; + html.push(creatInsertStr(vi.url, (vi.width || 420), (vi.height || 280), (id + i), null, false)); +} + _$jscoverage['plugins/video.js'][101]++; + me.execCommand("inserthtml", html.join(""), true); + _$jscoverage['plugins/video.js'][102]++; + var rng = this.selection.getRange(); + _$jscoverage['plugins/video.js'][103]++; + for (var i = 0, len = videoObjs.length; (i < len); (i++)) { + _$jscoverage['plugins/video.js'][104]++; + var img = this.document.getElementById(("tmpVedio" + i)); + _$jscoverage['plugins/video.js'][105]++; + domUtils.removeAttributes(img, "id"); + _$jscoverage['plugins/video.js'][106]++; + rng.selectNode(img).select(); + _$jscoverage['plugins/video.js'][107]++; + me.execCommand("imagefloat", videoObjs[i].align); +} +}), queryCommandState: (function () { + _$jscoverage['plugins/video.js'][111]++; + var img = me.selection.getRange().getClosedNode(), flag = (img && (img.className == "edui-faked-video")); + _$jscoverage['plugins/video.js'][113]++; + return (flag? 1: 0); +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/webapp.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/webapp.js new file mode 100644 index 000000000..75660c5ce --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/webapp.js @@ -0,0 +1,119 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/webapp.js']) { + _$jscoverage['plugins/webapp.js'] = []; + _$jscoverage['plugins/webapp.js'][28] = 0; + _$jscoverage['plugins/webapp.js'][29] = 0; + _$jscoverage['plugins/webapp.js'][30] = 0; + _$jscoverage['plugins/webapp.js'][31] = 0; + _$jscoverage['plugins/webapp.js'][39] = 0; + _$jscoverage['plugins/webapp.js'][40] = 0; + _$jscoverage['plugins/webapp.js'][42] = 0; + _$jscoverage['plugins/webapp.js'][43] = 0; + _$jscoverage['plugins/webapp.js'][44] = 0; + _$jscoverage['plugins/webapp.js'][46] = 0; + _$jscoverage['plugins/webapp.js'][47] = 0; + _$jscoverage['plugins/webapp.js'][48] = 0; + _$jscoverage['plugins/webapp.js'][52] = 0; + _$jscoverage['plugins/webapp.js'][53] = 0; + _$jscoverage['plugins/webapp.js'][55] = 0; + _$jscoverage['plugins/webapp.js'][56] = 0; + _$jscoverage['plugins/webapp.js'][58] = 0; + _$jscoverage['plugins/webapp.js'][59] = 0; + _$jscoverage['plugins/webapp.js'][60] = 0; + _$jscoverage['plugins/webapp.js'][62] = 0; + _$jscoverage['plugins/webapp.js'][65] = 0; + _$jscoverage['plugins/webapp.js'][67] = 0; +} +_$jscoverage['plugins/webapp.js'].source = ["/**"," * 百度应用"," * @file"," * @since 1.2.6.1"," */","","","/**"," * 在当前光标处插入一个百度应用, 需要百度APPKey"," * @command webapp"," * @method execCommand"," * @param { KeyValueMap } appOptions 应用所需的参数项, 支持的key有: title=>应用标题, width=>应用容器宽度,"," * height=>应用容器高度,logo=>应用logo,url=>应用地址"," * @example"," * ```javascript"," * //editor是编辑器实例"," * //在编辑器里插入一个“植物大战僵尸”的APP"," * editor.execCommand( 'webapp' , {"," * title: '植物大战僵尸',"," * width: 560,"," * height: 465,"," * logo: '应用展示的图片',"," * url: '百度应用的地址'"," * } );"," * ```"," */","","UE.plugins['webapp'] = function () {"," var me = this;"," function createInsertStr( obj, toIframe, addParagraph ) {"," return !toIframe ?"," (addParagraph ? '<p>' : '') + '<img title=\"'+obj.title+'\" width=\"' + obj.width + '\" height=\"' + obj.height + '\"' +"," ' src=\"' + me.options.UEDITOR_HOME_URL + 'themes/default/images/spacer.gif\" style=\"background:url(' + obj.logo+') no-repeat center center; border:1px solid gray;\" class=\"edui-faked-webapp\" _url=\"' + obj.url + '\" />' +"," (addParagraph ? '</p>' : '')"," :"," '<iframe class=\"edui-faked-webapp\" title=\"'+obj.title+'\" width=\"' + obj.width + '\" height=\"' + obj.height + '\" scrolling=\"no\" frameborder=\"0\" src=\"' + obj.url + '\" logo_url = '+obj.logo+'></iframe>';"," }",""," function switchImgAndIframe( img2frame ) {"," var tmpdiv,"," nodes = domUtils.getElementsByTagName( me.document, !img2frame ? \"iframe\" : \"img\" );"," for ( var i = 0, node; node = nodes[i++]; ) {"," if ( node.className != \"edui-faked-webapp\" ){"," continue;"," }"," tmpdiv = me.document.createElement( \"div\" );"," tmpdiv.innerHTML = createInsertStr( img2frame ? {url:node.getAttribute( \"_url\" ), width:node.width, height:node.height,title:node.title,logo:node.style.backgroundImage.replace(\"url(\",\"\").replace(\")\",\"\")} : {url:node.getAttribute( \"src\", 2 ),title:node.title, width:node.width, height:node.height,logo:node.getAttribute(\"logo_url\")}, img2frame ? true : false,false );"," node.parentNode.replaceChild( tmpdiv.firstChild, node );"," }"," }",""," me.addListener( \"beforegetcontent\", function () {"," switchImgAndIframe( true );"," } );"," me.addListener( 'aftersetcontent', function () {"," switchImgAndIframe( false );"," } );"," me.addListener( 'aftergetcontent', function ( cmdName ) {"," if ( cmdName == 'aftergetcontent' && me.queryCommandState( 'source' ) ){"," return;"," }"," switchImgAndIframe( false );"," } );",""," me.commands['webapp'] = {"," execCommand:function ( cmd, obj ) {"," me.execCommand( \"inserthtml\", createInsertStr( obj, false,true ) );"," }"," };","};"]; +_$jscoverage['plugins/webapp.js'][28]++; +UE.plugins.webapp = (function () { + _$jscoverage['plugins/webapp.js'][29]++; + var me = this; + _$jscoverage['plugins/webapp.js'][30]++; + function createInsertStr(obj, toIframe, addParagraph) { + _$jscoverage['plugins/webapp.js'][31]++; + return ((! toIframe)? ((addParagraph? "

    ": "") + "" + (addParagraph? "

    ": "")): ("")); +} + _$jscoverage['plugins/webapp.js'][39]++; + function switchImgAndIframe(img2frame) { + _$jscoverage['plugins/webapp.js'][40]++; + var tmpdiv, nodes = domUtils.getElementsByTagName(me.document, ((! img2frame)? "iframe": "img")); + _$jscoverage['plugins/webapp.js'][42]++; + for (var i = 0, node; (node = nodes[(i++)]);) { + _$jscoverage['plugins/webapp.js'][43]++; + if ((node.className != "edui-faked-webapp")) { + _$jscoverage['plugins/webapp.js'][44]++; + continue; + } + _$jscoverage['plugins/webapp.js'][46]++; + tmpdiv = me.document.createElement("div"); + _$jscoverage['plugins/webapp.js'][47]++; + tmpdiv.innerHTML = createInsertStr((img2frame? {url: node.getAttribute("_url"), width: node.width, height: node.height, title: node.title, logo: node.style.backgroundImage.replace("url(", "").replace(")", "")}: {url: node.getAttribute("src", 2), title: node.title, width: node.width, height: node.height, logo: node.getAttribute("logo_url")}), (img2frame? true: false), false); + _$jscoverage['plugins/webapp.js'][48]++; + node.parentNode.replaceChild(tmpdiv.firstChild, node); +} +} + _$jscoverage['plugins/webapp.js'][52]++; + me.addListener("beforegetcontent", (function () { + _$jscoverage['plugins/webapp.js'][53]++; + switchImgAndIframe(true); +})); + _$jscoverage['plugins/webapp.js'][55]++; + me.addListener("aftersetcontent", (function () { + _$jscoverage['plugins/webapp.js'][56]++; + switchImgAndIframe(false); +})); + _$jscoverage['plugins/webapp.js'][58]++; + me.addListener("aftergetcontent", (function (cmdName) { + _$jscoverage['plugins/webapp.js'][59]++; + if (((cmdName == "aftergetcontent") && me.queryCommandState("source"))) { + _$jscoverage['plugins/webapp.js'][60]++; + return; + } + _$jscoverage['plugins/webapp.js'][62]++; + switchImgAndIframe(false); +})); + _$jscoverage['plugins/webapp.js'][65]++; + me.commands.webapp = {execCommand: (function (cmd, obj) { + _$jscoverage['plugins/webapp.js'][67]++; + me.execCommand("inserthtml", createInsertStr(obj, false, true)); +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/wordcount.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/wordcount.js new file mode 100644 index 000000000..08a67d399 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/wordcount.js @@ -0,0 +1,90 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/wordcount.js']) { + _$jscoverage['plugins/wordcount.js'] = []; + _$jscoverage['plugins/wordcount.js'][13] = 0; + _$jscoverage['plugins/wordcount.js'][14] = 0; + _$jscoverage['plugins/wordcount.js'][15] = 0; + _$jscoverage['plugins/wordcount.js'][16] = 0; + _$jscoverage['plugins/wordcount.js'][18] = 0; + _$jscoverage['plugins/wordcount.js'][19] = 0; + _$jscoverage['plugins/wordcount.js'][20] = 0; + _$jscoverage['plugins/wordcount.js'][21] = 0; + _$jscoverage['plugins/wordcount.js'][22] = 0; + _$jscoverage['plugins/wordcount.js'][25] = 0; + _$jscoverage['plugins/wordcount.js'][26] = 0; + _$jscoverage['plugins/wordcount.js'][27] = 0; + _$jscoverage['plugins/wordcount.js'][28] = 0; +} +_$jscoverage['plugins/wordcount.js'].source = ["///import core","///commands 字数统计","///commandsName WordCount,wordCount","///commandsTitle 字数统计","/*"," * Created by JetBrains WebStorm."," * User: taoqili"," * Date: 11-9-7"," * Time: 下午8:18"," * To change this template use File | Settings | File Templates."," */","","UE.plugins['wordcount'] = function(){"," var me = this;"," me.addListener('contentchange',function(){"," me.fireEvent('wordcount');"," });"," var timer;"," me.addListener('ready',function(){"," var me = this;"," domUtils.on(me.body,\"keyup\",function(evt){"," var code = evt.keyCode||evt.which,"," //忽略的按键,ctr,alt,shift,方向键"," ignores = {\"16\":1,\"18\":1,\"20\":1,\"37\":1,\"38\":1,\"39\":1,\"40\":1};"," if(code in ignores) return;"," clearTimeout(timer);"," timer = setTimeout(function(){"," me.fireEvent('wordcount');"," },200)"," })"," });","};"]; +_$jscoverage['plugins/wordcount.js'][13]++; +UE.plugins.wordcount = (function () { + _$jscoverage['plugins/wordcount.js'][14]++; + var me = this; + _$jscoverage['plugins/wordcount.js'][15]++; + me.addListener("contentchange", (function () { + _$jscoverage['plugins/wordcount.js'][16]++; + me.fireEvent("wordcount"); +})); + _$jscoverage['plugins/wordcount.js'][18]++; + var timer; + _$jscoverage['plugins/wordcount.js'][19]++; + me.addListener("ready", (function () { + _$jscoverage['plugins/wordcount.js'][20]++; + var me = this; + _$jscoverage['plugins/wordcount.js'][21]++; + domUtils.on(me.body, "keyup", (function (evt) { + _$jscoverage['plugins/wordcount.js'][22]++; + var code = (evt.keyCode || evt.which), ignores = {"16": 1, "18": 1, "20": 1, "37": 1, "38": 1, "39": 1, "40": 1}; + _$jscoverage['plugins/wordcount.js'][25]++; + if ((code in ignores)) { + _$jscoverage['plugins/wordcount.js'][25]++; + return; + } + _$jscoverage['plugins/wordcount.js'][26]++; + clearTimeout(timer); + _$jscoverage['plugins/wordcount.js'][27]++; + timer = setTimeout((function () { + _$jscoverage['plugins/wordcount.js'][28]++; + me.fireEvent("wordcount"); +}), 200); +})); +})); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/wordimage.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/wordimage.js new file mode 100644 index 000000000..04237c9b1 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/plugins/wordimage.js @@ -0,0 +1,113 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['plugins/wordimage.js']) { + _$jscoverage['plugins/wordimage.js'] = []; + _$jscoverage['plugins/wordimage.js'][7] = 0; + _$jscoverage['plugins/wordimage.js'][8] = 0; + _$jscoverage['plugins/wordimage.js'][10] = 0; + _$jscoverage['plugins/wordimage.js'][11] = 0; + _$jscoverage['plugins/wordimage.js'][12] = 0; + _$jscoverage['plugins/wordimage.js'][16] = 0; + _$jscoverage['plugins/wordimage.js'][17] = 0; + _$jscoverage['plugins/wordimage.js'][53] = 0; + _$jscoverage['plugins/wordimage.js'][55] = 0; + _$jscoverage['plugins/wordimage.js'][56] = 0; + _$jscoverage['plugins/wordimage.js'][57] = 0; + _$jscoverage['plugins/wordimage.js'][58] = 0; + _$jscoverage['plugins/wordimage.js'][59] = 0; + _$jscoverage['plugins/wordimage.js'][61] = 0; + _$jscoverage['plugins/wordimage.js'][62] = 0; + _$jscoverage['plugins/wordimage.js'][66] = 0; + _$jscoverage['plugins/wordimage.js'][67] = 0; + _$jscoverage['plugins/wordimage.js'][68] = 0; + _$jscoverage['plugins/wordimage.js'][69] = 0; + _$jscoverage['plugins/wordimage.js'][72] = 0; +} +_$jscoverage['plugins/wordimage.js'].source = ["/**"," * 本地图片引导上传插件"," * @file"," * @since 1.2.6.1"," */","","UE.plugins[\"wordimage\"] = function () {"," var me = this,"," images;"," me.addInputRule(function (root) {"," utils.each(root.getNodesByTagName('img'), function (img) {"," var attrs = img.attrs,"," flag = parseInt(attrs.width) < 128 || parseInt(attrs.height) < 43,"," opt = me.options,"," src = opt.UEDITOR_HOME_URL + 'themes/default/images/spacer.gif';"," if (attrs['_src'] && attrs['_src'].indexOf(\"file:///\")!==-1) {"," img.setAttr({"," width:attrs.width,"," height:attrs.height,"," alt:attrs.alt,"," word_img:attrs._src,"," src:src,"," _src:src,"," 'style':'background:url(' + ( flag ? opt.themePath + opt.theme + '/images/word.gif' : opt.langPath + opt.lang + '/images/localimage.png') + ') no-repeat center center;border:1px solid #ddd'"," })"," }"," })"," });",""," /**"," * 粘贴word文档的内容时,运行该命令,会把编辑区域里的word图片地址,赋值到editor.word_img的数组里面"," * @command wordimage"," * @method execCommand"," * @param { String } cmd 命令字符串"," * @example"," * ```javascript"," * editor.execCommand( 'wordimage');"," * ```"," */",""," /**"," * 查询当前是否有word文档粘贴进来的图片"," * @command wordimage"," * @method queryCommandState"," * @param { String } cmd 命令字符串"," * @return { int } 如果当前编辑区域有word文档的粘贴进来的图片,则返回1,否则返回-1"," * @example"," * ```javascript"," * editor.queryCommandState( 'wordimage' );"," * ```"," */",""," me.commands['wordimage'] = {"," execCommand:function () {"," images = domUtils.getElementsByTagName(me.document.body, \"img\");"," var urlList = [];"," for (var i = 0, ci; ci = images[i++];) {"," var url = ci.getAttribute(\"word_img\");"," url && urlList.push(url);"," }"," if (images.length) {"," this[\"word_img\"] = urlList;"," }"," },"," queryCommandState:function () {"," images = domUtils.getElementsByTagName(me.document.body, \"img\");"," for (var i = 0, ci; ci = images[i++];) {"," if (ci.getAttribute(\"word_img\")) {"," return 1;"," }"," }"," return -1;"," }"," };","","};"]; +_$jscoverage['plugins/wordimage.js'][7]++; +UE.plugins.wordimage = (function () { + _$jscoverage['plugins/wordimage.js'][8]++; + var me = this, images; + _$jscoverage['plugins/wordimage.js'][10]++; + me.addInputRule((function (root) { + _$jscoverage['plugins/wordimage.js'][11]++; + utils.each(root.getNodesByTagName("img"), (function (img) { + _$jscoverage['plugins/wordimage.js'][12]++; + var attrs = img.attrs, flag = ((parseInt(attrs.width) < 128) || (parseInt(attrs.height) < 43)), opt = me.options, src = (opt.UEDITOR_HOME_URL + "themes/default/images/spacer.gif"); + _$jscoverage['plugins/wordimage.js'][16]++; + if ((attrs._src && (attrs._src.indexOf("file:///") !== -1))) { + _$jscoverage['plugins/wordimage.js'][17]++; + img.setAttr({width: attrs.width, height: attrs.height, alt: attrs.alt, word_img: attrs._src, src: src, _src: src, "style": ("background:url(" + (flag? (opt.themePath + opt.theme + "/images/word.gif"): (opt.langPath + opt.lang + "/images/localimage.png")) + ") no-repeat center center;border:1px solid #ddd")}); + } +})); +})); + _$jscoverage['plugins/wordimage.js'][53]++; + me.commands.wordimage = {execCommand: (function () { + _$jscoverage['plugins/wordimage.js'][55]++; + images = domUtils.getElementsByTagName(me.document.body, "img"); + _$jscoverage['plugins/wordimage.js'][56]++; + var urlList = []; + _$jscoverage['plugins/wordimage.js'][57]++; + for (var i = 0, ci; (ci = images[(i++)]);) { + _$jscoverage['plugins/wordimage.js'][58]++; + var url = ci.getAttribute("word_img"); + _$jscoverage['plugins/wordimage.js'][59]++; + (url && urlList.push(url)); +} + _$jscoverage['plugins/wordimage.js'][61]++; + if (images.length) { + _$jscoverage['plugins/wordimage.js'][62]++; + this.word_img = urlList; + } +}), queryCommandState: (function () { + _$jscoverage['plugins/wordimage.js'][66]++; + images = domUtils.getElementsByTagName(me.document.body, "img"); + _$jscoverage['plugins/wordimage.js'][67]++; + for (var i = 0, ci; (ci = images[(i++)]);) { + _$jscoverage['plugins/wordimage.js'][68]++; + if (ci.getAttribute("word_img")) { + _$jscoverage['plugins/wordimage.js'][69]++; + return 1; + } +} + _$jscoverage['plugins/wordimage.js'][72]++; + return -1; +})}; +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/autotypesetbutton.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/autotypesetbutton.js new file mode 100644 index 000000000..3cf697733 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/autotypesetbutton.js @@ -0,0 +1,207 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/autotypesetbutton.js']) { + _$jscoverage['ui/autotypesetbutton.js'] = []; + _$jscoverage['ui/autotypesetbutton.js'][6] = 0; + _$jscoverage['ui/autotypesetbutton.js'][7] = 0; + _$jscoverage['ui/autotypesetbutton.js'][12] = 0; + _$jscoverage['ui/autotypesetbutton.js'][13] = 0; + _$jscoverage['ui/autotypesetbutton.js'][15] = 0; + _$jscoverage['ui/autotypesetbutton.js'][16] = 0; + _$jscoverage['ui/autotypesetbutton.js'][22] = 0; + _$jscoverage['ui/autotypesetbutton.js'][24] = 0; + _$jscoverage['ui/autotypesetbutton.js'][26] = 0; + _$jscoverage['ui/autotypesetbutton.js'][27] = 0; + _$jscoverage['ui/autotypesetbutton.js'][28] = 0; + _$jscoverage['ui/autotypesetbutton.js'][29] = 0; + _$jscoverage['ui/autotypesetbutton.js'][30] = 0; + _$jscoverage['ui/autotypesetbutton.js'][31] = 0; + _$jscoverage['ui/autotypesetbutton.js'][32] = 0; + _$jscoverage['ui/autotypesetbutton.js'][33] = 0; + _$jscoverage['ui/autotypesetbutton.js'][35] = 0; + _$jscoverage['ui/autotypesetbutton.js'][36] = 0; + _$jscoverage['ui/autotypesetbutton.js'][37] = 0; + _$jscoverage['ui/autotypesetbutton.js'][38] = 0; + _$jscoverage['ui/autotypesetbutton.js'][39] = 0; + _$jscoverage['ui/autotypesetbutton.js'][44] = 0; + _$jscoverage['ui/autotypesetbutton.js'][49] = 0; + _$jscoverage['ui/autotypesetbutton.js'][50] = 0; + _$jscoverage['ui/autotypesetbutton.js'][51] = 0; + _$jscoverage['ui/autotypesetbutton.js'][52] = 0; + _$jscoverage['ui/autotypesetbutton.js'][55] = 0; + _$jscoverage['ui/autotypesetbutton.js'][57] = 0; + _$jscoverage['ui/autotypesetbutton.js'][59] = 0; + _$jscoverage['ui/autotypesetbutton.js'][60] = 0; + _$jscoverage['ui/autotypesetbutton.js'][66] = 0; + _$jscoverage['ui/autotypesetbutton.js'][67] = 0; + _$jscoverage['ui/autotypesetbutton.js'][68] = 0; + _$jscoverage['ui/autotypesetbutton.js'][69] = 0; + _$jscoverage['ui/autotypesetbutton.js'][70] = 0; + _$jscoverage['ui/autotypesetbutton.js'][74] = 0; + _$jscoverage['ui/autotypesetbutton.js'][75] = 0; + _$jscoverage['ui/autotypesetbutton.js'][76] = 0; + _$jscoverage['ui/autotypesetbutton.js'][77] = 0; + _$jscoverage['ui/autotypesetbutton.js'][78] = 0; + _$jscoverage['ui/autotypesetbutton.js'][81] = 0; + _$jscoverage['ui/autotypesetbutton.js'][82] = 0; + _$jscoverage['ui/autotypesetbutton.js'][83] = 0; + _$jscoverage['ui/autotypesetbutton.js'][84] = 0; + _$jscoverage['ui/autotypesetbutton.js'][86] = 0; + _$jscoverage['ui/autotypesetbutton.js'][88] = 0; + _$jscoverage['ui/autotypesetbutton.js'][91] = 0; +} +_$jscoverage['ui/autotypesetbutton.js'].source = ["///import core","///import uicore","///import ui/popup.js","///import ui/autotypesetpicker.js","///import ui/splitbutton.js","(function (){"," var utils = baidu.editor.utils,"," Popup = baidu.editor.ui.Popup,"," AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker,"," SplitButton = baidu.editor.ui.SplitButton,"," AutoTypeSetButton = baidu.editor.ui.AutoTypeSetButton = function (options){"," this.initOptions(options);"," this.initAutoTypeSetButton();"," };"," function getPara(me){"," var opt = me.editor.options.autotypeset,"," cont = me.getDom(),"," editorId = me.editor.uid,"," inputType = null,"," attrName = null,"," ipts = domUtils.getElementsByTagName(cont,\"input\");"," for(var i=ipts.length-1,ipt;ipt=ipts[i--];){",""," inputType = ipt.getAttribute(\"type\");",""," if(inputType==\"checkbox\"){"," attrName = ipt.getAttribute(\"name\");"," opt[attrName] && delete opt[attrName];"," if(ipt.checked){"," var attrValue = document.getElementById( attrName+\"Value\" + editorId );"," if(attrValue){"," if(/input/ig.test(attrValue.tagName)){"," opt[attrName] = attrValue.value;"," }else{"," var iptChilds = attrValue.getElementsByTagName(\"input\");"," for(var j=iptChilds.length-1,iptchild;iptchild=iptChilds[j--];){"," if(iptchild.checked){"," opt[attrName] = iptchild.value;"," break;"," }"," }"," }"," }else{"," opt[attrName] = true;"," }"," }"," }"," }"," var selects = domUtils.getElementsByTagName(cont,\"select\");"," for(var i=0,si;si=selects[i++];){"," var attr = si.getAttribute('name');"," opt[attr] = opt[attr] ? si.value : '';"," }",""," me.editor.options.autotypeset = opt;"," }"," AutoTypeSetButton.prototype = {"," initAutoTypeSetButton: function (){"," var me = this;"," this.popup = new Popup({"," //传入配置参数"," content: new AutoTypeSetPicker({editor:me.editor}),"," 'editor':me.editor,"," hide : function(){",""," if (!this._hidden && this.getDom()) {"," getPara(this);"," this.getDom().style.display = 'none';"," this._hidden = true;"," this.fireEvent('hide');"," }"," }"," });"," var flag = 0;"," this.popup.addListener('postRenderAfter',function(){"," var popupUI = this;"," if(flag)return;"," var cont = this.getDom(),"," btn = cont.getElementsByTagName('button')[0];",""," btn.onclick = function(){"," getPara(popupUI);"," me.editor.execCommand('autotypeset');"," popupUI.hide()"," };"," flag = 1;"," });"," this.initSplitButton();"," }"," };"," utils.inherits(AutoTypeSetButton, SplitButton);","","})();"]; +_$jscoverage['ui/autotypesetbutton.js'][6]++; +(function () { + _$jscoverage['ui/autotypesetbutton.js'][7]++; + var utils = baidu.editor.utils, Popup = baidu.editor.ui.Popup, AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker, SplitButton = baidu.editor.ui.SplitButton, AutoTypeSetButton = (baidu.editor.ui.AutoTypeSetButton = (function (options) { + _$jscoverage['ui/autotypesetbutton.js'][12]++; + this.initOptions(options); + _$jscoverage['ui/autotypesetbutton.js'][13]++; + this.initAutoTypeSetButton(); +})); + _$jscoverage['ui/autotypesetbutton.js'][15]++; + function getPara(me) { + _$jscoverage['ui/autotypesetbutton.js'][16]++; + var opt = me.editor.options.autotypeset, cont = me.getDom(), editorId = me.editor.uid, inputType = null, attrName = null, ipts = domUtils.getElementsByTagName(cont, "input"); + _$jscoverage['ui/autotypesetbutton.js'][22]++; + for (var i = (ipts.length - 1), ipt; (ipt = ipts[(i--)]);) { + _$jscoverage['ui/autotypesetbutton.js'][24]++; + inputType = ipt.getAttribute("type"); + _$jscoverage['ui/autotypesetbutton.js'][26]++; + if ((inputType == "checkbox")) { + _$jscoverage['ui/autotypesetbutton.js'][27]++; + attrName = ipt.getAttribute("name"); + _$jscoverage['ui/autotypesetbutton.js'][28]++; + (opt[attrName] && (delete opt[attrName])); + _$jscoverage['ui/autotypesetbutton.js'][29]++; + if (ipt.checked) { + _$jscoverage['ui/autotypesetbutton.js'][30]++; + var attrValue = document.getElementById((attrName + "Value" + editorId)); + _$jscoverage['ui/autotypesetbutton.js'][31]++; + if (attrValue) { + _$jscoverage['ui/autotypesetbutton.js'][32]++; + if (/input/gi.test(attrValue.tagName)) { + _$jscoverage['ui/autotypesetbutton.js'][33]++; + opt[attrName] = attrValue.value; + } + else { + _$jscoverage['ui/autotypesetbutton.js'][35]++; + var iptChilds = attrValue.getElementsByTagName("input"); + _$jscoverage['ui/autotypesetbutton.js'][36]++; + for (var j = (iptChilds.length - 1), iptchild; (iptchild = iptChilds[(j--)]);) { + _$jscoverage['ui/autotypesetbutton.js'][37]++; + if (iptchild.checked) { + _$jscoverage['ui/autotypesetbutton.js'][38]++; + opt[attrName] = iptchild.value; + _$jscoverage['ui/autotypesetbutton.js'][39]++; + break; + } +} + } + } + else { + _$jscoverage['ui/autotypesetbutton.js'][44]++; + opt[attrName] = true; + } + } + } +} + _$jscoverage['ui/autotypesetbutton.js'][49]++; + var selects = domUtils.getElementsByTagName(cont, "select"); + _$jscoverage['ui/autotypesetbutton.js'][50]++; + for (var i = 0, si; (si = selects[(i++)]);) { + _$jscoverage['ui/autotypesetbutton.js'][51]++; + var attr = si.getAttribute("name"); + _$jscoverage['ui/autotypesetbutton.js'][52]++; + opt[attr] = (opt[attr]? si.value: ""); +} + _$jscoverage['ui/autotypesetbutton.js'][55]++; + me.editor.options.autotypeset = opt; +} + _$jscoverage['ui/autotypesetbutton.js'][57]++; + AutoTypeSetButton.prototype = {initAutoTypeSetButton: (function () { + _$jscoverage['ui/autotypesetbutton.js'][59]++; + var me = this; + _$jscoverage['ui/autotypesetbutton.js'][60]++; + this.popup = new Popup({content: new AutoTypeSetPicker({editor: me.editor}), "editor": me.editor, hide: (function () { + _$jscoverage['ui/autotypesetbutton.js'][66]++; + if (((! this._hidden) && this.getDom())) { + _$jscoverage['ui/autotypesetbutton.js'][67]++; + getPara(this); + _$jscoverage['ui/autotypesetbutton.js'][68]++; + this.getDom().style.display = "none"; + _$jscoverage['ui/autotypesetbutton.js'][69]++; + this._hidden = true; + _$jscoverage['ui/autotypesetbutton.js'][70]++; + this.fireEvent("hide"); + } +})}); + _$jscoverage['ui/autotypesetbutton.js'][74]++; + var flag = 0; + _$jscoverage['ui/autotypesetbutton.js'][75]++; + this.popup.addListener("postRenderAfter", (function () { + _$jscoverage['ui/autotypesetbutton.js'][76]++; + var popupUI = this; + _$jscoverage['ui/autotypesetbutton.js'][77]++; + if (flag) { + _$jscoverage['ui/autotypesetbutton.js'][77]++; + return; + } + _$jscoverage['ui/autotypesetbutton.js'][78]++; + var cont = this.getDom(), btn = cont.getElementsByTagName("button")[0]; + _$jscoverage['ui/autotypesetbutton.js'][81]++; + btn.onclick = (function () { + _$jscoverage['ui/autotypesetbutton.js'][82]++; + getPara(popupUI); + _$jscoverage['ui/autotypesetbutton.js'][83]++; + me.editor.execCommand("autotypeset"); + _$jscoverage['ui/autotypesetbutton.js'][84]++; + popupUI.hide(); +}); + _$jscoverage['ui/autotypesetbutton.js'][86]++; + flag = 1; +})); + _$jscoverage['ui/autotypesetbutton.js'][88]++; + this.initSplitButton(); +})}; + _$jscoverage['ui/autotypesetbutton.js'][91]++; + utils.inherits(AutoTypeSetButton, SplitButton); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/autotypesetpicker.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/autotypesetpicker.js new file mode 100644 index 000000000..e499278aa --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/autotypesetpicker.js @@ -0,0 +1,80 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/autotypesetpicker.js']) { + _$jscoverage['ui/autotypesetpicker.js'] = []; + _$jscoverage['ui/autotypesetpicker.js'][3] = 0; + _$jscoverage['ui/autotypesetpicker.js'][4] = 0; + _$jscoverage['ui/autotypesetpicker.js'][7] = 0; + _$jscoverage['ui/autotypesetpicker.js'][8] = 0; + _$jscoverage['ui/autotypesetpicker.js'][9] = 0; + _$jscoverage['ui/autotypesetpicker.js'][11] = 0; + _$jscoverage['ui/autotypesetpicker.js'][13] = 0; + _$jscoverage['ui/autotypesetpicker.js'][16] = 0; + _$jscoverage['ui/autotypesetpicker.js'][20] = 0; + _$jscoverage['ui/autotypesetpicker.js'][23] = 0; + _$jscoverage['ui/autotypesetpicker.js'][48] = 0; +} +_$jscoverage['ui/autotypesetpicker.js'].source = ["///import core","///import uicore","(function () {"," var utils = baidu.editor.utils,"," UIBase = baidu.editor.ui.UIBase;",""," var AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker = function (options) {"," this.initOptions(options);"," this.initAutoTypeSetPicker();"," };"," AutoTypeSetPicker.prototype = {"," initAutoTypeSetPicker:function () {"," this.initUIBase();"," },"," getHtmlTpl:function () {"," var me = this.editor,"," opt = me.options.autotypeset,"," lang = me.getLang(\"autoTypeSet\");",""," var textAlignInputName = 'textAlignValue' + me.uid,"," imageBlockInputName = 'imageBlockLineValue' + me.uid;",""," return '<div id=\"##\" class=\"edui-autotypesetpicker %%\">' +"," '<div class=\"edui-autotypesetpicker-body\">' +"," '<table >' +"," '<tr><td nowrap colspan=\"2\"><input type=\"checkbox\" name=\"mergeEmptyline\" ' + (opt[\"mergeEmptyline\"] ? \"checked\" : \"\" ) + '>' + lang.mergeLine + '</td><td colspan=\"2\"><input type=\"checkbox\" name=\"removeEmptyline\" ' + (opt[\"removeEmptyline\"] ? \"checked\" : \"\" ) + '>' + lang.delLine + '</td></tr>' +"," '<tr><td nowrap colspan=\"2\"><input type=\"checkbox\" name=\"removeClass\" ' + (opt[\"removeClass\"] ? \"checked\" : \"\" ) + '>' + lang.removeFormat + '</td><td colspan=\"2\"><input type=\"checkbox\" name=\"indent\" ' + (opt[\"indent\"] ? \"checked\" : \"\" ) + '>' + lang.indent + '</td></tr>' +"," '<tr><td nowrap colspan=\"2\"><input type=\"checkbox\" name=\"textAlign\" ' + (opt[\"textAlign\"] ? \"checked\" : \"\" ) + '>' + lang.alignment + '</td><td colspan=\"2\" id=\"' + textAlignInputName + '\"><input type=\"radio\" name=\"'+ textAlignInputName +'\" value=\"left\" ' + ((opt[\"textAlign\"] && opt[\"textAlign\"] == \"left\") ? \"checked\" : \"\") + '>' + me.getLang(\"justifyleft\") + '<input type=\"radio\" name=\"'+ textAlignInputName +'\" value=\"center\" ' + ((opt[\"textAlign\"] && opt[\"textAlign\"] == \"center\") ? \"checked\" : \"\") + '>' + me.getLang(\"justifycenter\") + '<input type=\"radio\" name=\"'+ textAlignInputName +'\" value=\"right\" ' + ((opt[\"textAlign\"] && opt[\"textAlign\"] == \"right\") ? \"checked\" : \"\") + '>' + me.getLang(\"justifyright\") + ' </tr>' +"," '<tr><td nowrap colspan=\"2\"><input type=\"checkbox\" name=\"imageBlockLine\" ' + (opt[\"imageBlockLine\"] ? \"checked\" : \"\" ) + '>' + lang.imageFloat + '</td>' +"," '<td nowrap colspan=\"2\" id=\"'+ imageBlockInputName +'\">' +"," '<input type=\"radio\" name=\"'+ imageBlockInputName +'\" value=\"none\" ' + ((opt[\"imageBlockLine\"] && opt[\"imageBlockLine\"] == \"none\") ? \"checked\" : \"\") + '>' + me.getLang(\"default\") +"," '<input type=\"radio\" name=\"'+ imageBlockInputName +'\" value=\"left\" ' + ((opt[\"imageBlockLine\"] && opt[\"imageBlockLine\"] == \"left\") ? \"checked\" : \"\") + '>' + me.getLang(\"justifyleft\") +"," '<input type=\"radio\" name=\"'+ imageBlockInputName +'\" value=\"center\" ' + ((opt[\"imageBlockLine\"] && opt[\"imageBlockLine\"] == \"center\") ? \"checked\" : \"\") + '>' + me.getLang(\"justifycenter\") +"," '<input type=\"radio\" name=\"'+ imageBlockInputName +'\" value=\"right\" ' + ((opt[\"imageBlockLine\"] && opt[\"imageBlockLine\"] == \"right\") ? \"checked\" : \"\") + '>' + me.getLang(\"justifyright\") + '</tr>' +",""," '<tr><td nowrap colspan=\"2\"><input type=\"checkbox\" name=\"clearFontSize\" ' + (opt[\"clearFontSize\"] ? \"checked\" : \"\" ) + '>' + lang.removeFontsize + '</td><td colspan=\"2\"><input type=\"checkbox\" name=\"clearFontFamily\" ' + (opt[\"clearFontFamily\"] ? \"checked\" : \"\" ) + '>' + lang.removeFontFamily + '</td></tr>' +"," '<tr><td nowrap colspan=\"4\"><input type=\"checkbox\" name=\"removeEmptyNode\" ' + (opt[\"removeEmptyNode\"] ? \"checked\" : \"\" ) + '>' + lang.removeHtml + '</td></tr>' +"," '<tr><td nowrap colspan=\"4\"><input type=\"checkbox\" name=\"pasteFilter\" ' + (opt[\"pasteFilter\"] ? \"checked\" : \"\" ) + '>' + lang.pasteFilter + '</td></tr>' +"," '<tr><td nowrap colspan=\"4\" align=\"right\"><button >' + lang.run + '</button></td></tr>' +"," '</table>' +"," '</div>' +"," '</div>';","",""," },"," _UIBase_render:UIBase.prototype.render"," };"," utils.inherits(AutoTypeSetPicker, UIBase);","})();"]; +_$jscoverage['ui/autotypesetpicker.js'][3]++; +(function () { + _$jscoverage['ui/autotypesetpicker.js'][4]++; + var utils = baidu.editor.utils, UIBase = baidu.editor.ui.UIBase; + _$jscoverage['ui/autotypesetpicker.js'][7]++; + var AutoTypeSetPicker = (baidu.editor.ui.AutoTypeSetPicker = (function (options) { + _$jscoverage['ui/autotypesetpicker.js'][8]++; + this.initOptions(options); + _$jscoverage['ui/autotypesetpicker.js'][9]++; + this.initAutoTypeSetPicker(); +})); + _$jscoverage['ui/autotypesetpicker.js'][11]++; + AutoTypeSetPicker.prototype = {initAutoTypeSetPicker: (function () { + _$jscoverage['ui/autotypesetpicker.js'][13]++; + this.initUIBase(); +}), getHtmlTpl: (function () { + _$jscoverage['ui/autotypesetpicker.js'][16]++; + var me = this.editor, opt = me.options.autotypeset, lang = me.getLang("autoTypeSet"); + _$jscoverage['ui/autotypesetpicker.js'][20]++; + var textAlignInputName = ("textAlignValue" + me.uid), imageBlockInputName = ("imageBlockLineValue" + me.uid); + _$jscoverage['ui/autotypesetpicker.js'][23]++; + return ("
    " + "
    " + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "
    " + lang.mergeLine + "" + lang.delLine + "
    " + lang.removeFormat + "" + lang.indent + "
    " + lang.alignment + "" + me.getLang("justifyleft") + "" + me.getLang("justifycenter") + "" + me.getLang("justifyright") + "
    " + lang.imageFloat + "" + "" + me.getLang("default") + "" + me.getLang("justifyleft") + "" + me.getLang("justifycenter") + "" + me.getLang("justifyright") + "
    " + lang.removeFontsize + "" + lang.removeFontFamily + "
    " + lang.removeHtml + "
    " + lang.pasteFilter + "
    " + "
    " + "
    "); +}), _UIBase_render: UIBase.prototype.render}; + _$jscoverage['ui/autotypesetpicker.js'][48]++; + utils.inherits(AutoTypeSetPicker, UIBase); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/breakline.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/breakline.js new file mode 100644 index 000000000..35d6745eb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/breakline.js @@ -0,0 +1,71 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/breakline.js']) { + _$jscoverage['ui/breakline.js'] = []; + _$jscoverage['ui/breakline.js'][1] = 0; + _$jscoverage['ui/breakline.js'][2] = 0; + _$jscoverage['ui/breakline.js'][5] = 0; + _$jscoverage['ui/breakline.js'][6] = 0; + _$jscoverage['ui/breakline.js'][8] = 0; + _$jscoverage['ui/breakline.js'][11] = 0; + _$jscoverage['ui/breakline.js'][14] = 0; + _$jscoverage['ui/breakline.js'][17] = 0; +} +_$jscoverage['ui/breakline.js'].source = ["(function (){"," var utils = baidu.editor.utils,"," UIBase = baidu.editor.ui.UIBase,"," Breakline = baidu.editor.ui.Breakline = function (options){"," this.initOptions(options);"," this.initSeparator();"," };"," Breakline.prototype = {"," uiName: 'Breakline',"," initSeparator: function (){"," this.initUIBase();"," },"," getHtmlTpl: function (){"," return '<br/>';"," }"," };"," utils.inherits(Breakline, UIBase);","","})();"]; +_$jscoverage['ui/breakline.js'][1]++; +(function () { + _$jscoverage['ui/breakline.js'][2]++; + var utils = baidu.editor.utils, UIBase = baidu.editor.ui.UIBase, Breakline = (baidu.editor.ui.Breakline = (function (options) { + _$jscoverage['ui/breakline.js'][5]++; + this.initOptions(options); + _$jscoverage['ui/breakline.js'][6]++; + this.initSeparator(); +})); + _$jscoverage['ui/breakline.js'][8]++; + Breakline.prototype = {uiName: "Breakline", initSeparator: (function () { + _$jscoverage['ui/breakline.js'][11]++; + this.initUIBase(); +}), getHtmlTpl: (function () { + _$jscoverage['ui/breakline.js'][14]++; + return "
    "; +})}; + _$jscoverage['ui/breakline.js'][17]++; + utils.inherits(Breakline, UIBase); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/button.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/button.js new file mode 100644 index 000000000..5346f333f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/button.js @@ -0,0 +1,92 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/button.js']) { + _$jscoverage['ui/button.js'] = []; + _$jscoverage['ui/button.js'][4] = 0; + _$jscoverage['ui/button.js'][5] = 0; + _$jscoverage['ui/button.js'][9] = 0; + _$jscoverage['ui/button.js'][10] = 0; + _$jscoverage['ui/button.js'][12] = 0; + _$jscoverage['ui/button.js'][19] = 0; + _$jscoverage['ui/button.js'][20] = 0; + _$jscoverage['ui/button.js'][23] = 0; + _$jscoverage['ui/button.js'][34] = 0; + _$jscoverage['ui/button.js'][35] = 0; + _$jscoverage['ui/button.js'][38] = 0; + _$jscoverage['ui/button.js'][39] = 0; + _$jscoverage['ui/button.js'][43] = 0; + _$jscoverage['ui/button.js'][44] = 0; +} +_$jscoverage['ui/button.js'].source = ["///import core","///import uicore","///import ui/stateful.js","(function (){"," var utils = baidu.editor.utils,"," UIBase = baidu.editor.ui.UIBase,"," Stateful = baidu.editor.ui.Stateful,"," Button = baidu.editor.ui.Button = function (options){"," this.initOptions(options);"," this.initButton();"," };"," Button.prototype = {"," uiName: 'button',"," label: '',"," title: '',"," showIcon: true,"," showText: true,"," initButton: function (){"," this.initUIBase();"," this.Stateful_init();"," },"," getHtmlTpl: function (){"," return '<div id=\"##\" class=\"edui-box %%\">' +"," '<div id=\"##_state\" stateful>' +"," '<div class=\"%%-wrap\"><div id=\"##_body\" unselectable=\"on\" ' + (this.title ? 'title=\"' + this.title + '\"' : '') +"," ' class=\"%%-body\" onmousedown=\"return false;\" onclick=\"return $$._onClick();\">' +"," (this.showIcon ? '<div class=\"edui-box edui-icon\"></div>' : '') +"," (this.showText ? '<div class=\"edui-box edui-label\">' + this.label + '</div>' : '') +"," '</div>' +"," '</div>' +"," '</div></div>';"," },"," postRender: function (){"," this.Stateful_postRender();"," this.setDisabled(this.disabled)"," },"," _onClick: function (){"," if (!this.isDisabled()) {"," this.fireEvent('click');"," }"," }"," };"," utils.inherits(Button, UIBase);"," utils.extend(Button.prototype, Stateful);","","})();"]; +_$jscoverage['ui/button.js'][4]++; +(function () { + _$jscoverage['ui/button.js'][5]++; + var utils = baidu.editor.utils, UIBase = baidu.editor.ui.UIBase, Stateful = baidu.editor.ui.Stateful, Button = (baidu.editor.ui.Button = (function (options) { + _$jscoverage['ui/button.js'][9]++; + this.initOptions(options); + _$jscoverage['ui/button.js'][10]++; + this.initButton(); +})); + _$jscoverage['ui/button.js'][12]++; + Button.prototype = {uiName: "button", label: "", title: "", showIcon: true, showText: true, initButton: (function () { + _$jscoverage['ui/button.js'][19]++; + this.initUIBase(); + _$jscoverage['ui/button.js'][20]++; + this.Stateful_init(); +}), getHtmlTpl: (function () { + _$jscoverage['ui/button.js'][23]++; + return ("
    " + "
    " + "
    " + (this.showIcon? "
    ": "") + (this.showText? ("
    " + this.label + "
    "): "") + "
    " + "
    " + "
    "); +}), postRender: (function () { + _$jscoverage['ui/button.js'][34]++; + this.Stateful_postRender(); + _$jscoverage['ui/button.js'][35]++; + this.setDisabled(this.disabled); +}), _onClick: (function () { + _$jscoverage['ui/button.js'][38]++; + if ((! this.isDisabled())) { + _$jscoverage['ui/button.js'][39]++; + this.fireEvent("click"); + } +})}; + _$jscoverage['ui/button.js'][43]++; + utils.inherits(Button, UIBase); + _$jscoverage['ui/button.js'][44]++; + utils.extend(Button.prototype, Stateful); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/cellalignpicker.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/cellalignpicker.js new file mode 100644 index 000000000..5634b1c3c --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/cellalignpicker.js @@ -0,0 +1,134 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/cellalignpicker.js']) { + _$jscoverage['ui/cellalignpicker.js'] = []; + _$jscoverage['ui/cellalignpicker.js'][3] = 0; + _$jscoverage['ui/cellalignpicker.js'][4] = 0; + _$jscoverage['ui/cellalignpicker.js'][14] = 0; + _$jscoverage['ui/cellalignpicker.js'][15] = 0; + _$jscoverage['ui/cellalignpicker.js'][16] = 0; + _$jscoverage['ui/cellalignpicker.js'][17] = 0; + _$jscoverage['ui/cellalignpicker.js'][19] = 0; + _$jscoverage['ui/cellalignpicker.js'][23] = 0; + _$jscoverage['ui/cellalignpicker.js'][40] = 0; + _$jscoverage['ui/cellalignpicker.js'][41] = 0; + _$jscoverage['ui/cellalignpicker.js'][46] = 0; + _$jscoverage['ui/cellalignpicker.js'][47] = 0; + _$jscoverage['ui/cellalignpicker.js'][51] = 0; + _$jscoverage['ui/cellalignpicker.js'][58] = 0; + _$jscoverage['ui/cellalignpicker.js'][60] = 0; + _$jscoverage['ui/cellalignpicker.js'][61] = 0; + _$jscoverage['ui/cellalignpicker.js'][63] = 0; + _$jscoverage['ui/cellalignpicker.js'][65] = 0; + _$jscoverage['ui/cellalignpicker.js'][67] = 0; + _$jscoverage['ui/cellalignpicker.js'][71] = 0; + _$jscoverage['ui/cellalignpicker.js'][80] = 0; + _$jscoverage['ui/cellalignpicker.js'][83] = 0; + _$jscoverage['ui/cellalignpicker.js'][84] = 0; + _$jscoverage['ui/cellalignpicker.js'][85] = 0; + _$jscoverage['ui/cellalignpicker.js'][86] = 0; + _$jscoverage['ui/cellalignpicker.js'][91] = 0; + _$jscoverage['ui/cellalignpicker.js'][92] = 0; +} +_$jscoverage['ui/cellalignpicker.js'].source = ["///import core","///import uicore","(function () {"," var utils = baidu.editor.utils,"," Popup = baidu.editor.ui.Popup,"," Stateful = baidu.editor.ui.Stateful,"," UIBase = baidu.editor.ui.UIBase;",""," /**"," * 该参数将新增一个参数: selected, 参数类型为一个Object, 形如{ 'align': 'center', 'valign': 'top' }, 表示单元格的初始"," * 对齐状态为: 竖直居上,水平居中; 其中 align的取值为:'center', 'left', 'right'; valign的取值为: 'top', 'middle', 'bottom'"," * @update 2013/4/2 hancong03@baidu.com"," */"," var CellAlignPicker = baidu.editor.ui.CellAlignPicker = function (options) {"," this.initOptions(options);"," this.initSelected();"," this.initCellAlignPicker();"," };"," CellAlignPicker.prototype = {"," //初始化选中状态, 该方法将根据传递进来的参数获取到应该选中的对齐方式图标的索引"," initSelected: function(){",""," var status = {",""," valign: {"," top: 0,"," middle: 1,"," bottom: 2"," },"," align: {"," left: 0,"," center: 1,"," right: 2"," },"," count: 3",""," },"," result = -1;",""," if( this.selected ) {"," this.selectedIndex = status.valign[ this.selected.valign ] * status.count + status.align[ this.selected.align ];"," }",""," },"," initCellAlignPicker:function () {"," this.initUIBase();"," this.Stateful_init();"," },"," getHtmlTpl:function () {",""," var alignType = [ 'left', 'center', 'right' ],"," COUNT = 9,"," tempClassName = null,"," tempIndex = -1,"," tmpl = [];","",""," for( var i= 0; i<COUNT; i++ ) {",""," tempClassName = this.selectedIndex === i ? ' class=\"edui-cellalign-selected\" ' : '';"," tempIndex = i % 3;",""," tempIndex === 0 && tmpl.push('<tr>');",""," tmpl.push( '<td index=\"'+ i +'\" ' + tempClassName + ' stateful><div class=\"edui-icon edui-'+ alignType[ tempIndex ] +'\"></div></td>' );",""," tempIndex === 2 && tmpl.push('</tr>');",""," }",""," return '<div id=\"##\" class=\"edui-cellalignpicker %%\">' +"," '<div class=\"edui-cellalignpicker-body\">' +"," '<table onclick=\"$$._onClick(event);\">' +"," tmpl.join('') +"," '</table>' +"," '</div>' +"," '</div>';"," },"," getStateDom: function (){"," return this.target;"," },"," _onClick: function (evt){"," var target= evt.target || evt.srcElement;"," if(/icon/.test(target.className)){"," this.items[target.parentNode.getAttribute(\"index\")].onclick();"," Popup.postHide(evt);"," }"," },"," _UIBase_render:UIBase.prototype.render"," };"," utils.inherits(CellAlignPicker, UIBase);"," utils.extend(CellAlignPicker.prototype, Stateful,true);","})();","","",""]; +_$jscoverage['ui/cellalignpicker.js'][3]++; +(function () { + _$jscoverage['ui/cellalignpicker.js'][4]++; + var utils = baidu.editor.utils, Popup = baidu.editor.ui.Popup, Stateful = baidu.editor.ui.Stateful, UIBase = baidu.editor.ui.UIBase; + _$jscoverage['ui/cellalignpicker.js'][14]++; + var CellAlignPicker = (baidu.editor.ui.CellAlignPicker = (function (options) { + _$jscoverage['ui/cellalignpicker.js'][15]++; + this.initOptions(options); + _$jscoverage['ui/cellalignpicker.js'][16]++; + this.initSelected(); + _$jscoverage['ui/cellalignpicker.js'][17]++; + this.initCellAlignPicker(); +})); + _$jscoverage['ui/cellalignpicker.js'][19]++; + CellAlignPicker.prototype = {initSelected: (function () { + _$jscoverage['ui/cellalignpicker.js'][23]++; + var status = {valign: {top: 0, middle: 1, bottom: 2}, align: {left: 0, center: 1, right: 2}, count: 3}, result = -1; + _$jscoverage['ui/cellalignpicker.js'][40]++; + if (this.selected) { + _$jscoverage['ui/cellalignpicker.js'][41]++; + this.selectedIndex = ((status.valign[this.selected.valign] * status.count) + status.align[this.selected.align]); + } +}), initCellAlignPicker: (function () { + _$jscoverage['ui/cellalignpicker.js'][46]++; + this.initUIBase(); + _$jscoverage['ui/cellalignpicker.js'][47]++; + this.Stateful_init(); +}), getHtmlTpl: (function () { + _$jscoverage['ui/cellalignpicker.js'][51]++; + var alignType = ["left", "center", "right"], COUNT = 9, tempClassName = null, tempIndex = -1, tmpl = []; + _$jscoverage['ui/cellalignpicker.js'][58]++; + for (var i = 0; (i < COUNT); (i++)) { + _$jscoverage['ui/cellalignpicker.js'][60]++; + tempClassName = ((this.selectedIndex === i)? " class=\"edui-cellalign-selected\" ": ""); + _$jscoverage['ui/cellalignpicker.js'][61]++; + tempIndex = (i % 3); + _$jscoverage['ui/cellalignpicker.js'][63]++; + ((tempIndex === 0) && tmpl.push("")); + _$jscoverage['ui/cellalignpicker.js'][65]++; + tmpl.push(("
    ")); + _$jscoverage['ui/cellalignpicker.js'][67]++; + ((tempIndex === 2) && tmpl.push("")); +} + _$jscoverage['ui/cellalignpicker.js'][71]++; + return ("
    " + "
    " + "" + tmpl.join("") + "
    " + "
    " + "
    "); +}), getStateDom: (function () { + _$jscoverage['ui/cellalignpicker.js'][80]++; + return this.target; +}), _onClick: (function (evt) { + _$jscoverage['ui/cellalignpicker.js'][83]++; + var target = (evt.target || evt.srcElement); + _$jscoverage['ui/cellalignpicker.js'][84]++; + if (/icon/.test(target.className)) { + _$jscoverage['ui/cellalignpicker.js'][85]++; + this.items[target.parentNode.getAttribute("index")].onclick(); + _$jscoverage['ui/cellalignpicker.js'][86]++; + Popup.postHide(evt); + } +}), _UIBase_render: UIBase.prototype.render}; + _$jscoverage['ui/cellalignpicker.js'][91]++; + utils.inherits(CellAlignPicker, UIBase); + _$jscoverage['ui/cellalignpicker.js'][92]++; + utils.extend(CellAlignPicker.prototype, Stateful, true); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/colorbutton.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/colorbutton.js new file mode 100644 index 000000000..00b61978b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/colorbutton.js @@ -0,0 +1,117 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/colorbutton.js']) { + _$jscoverage['ui/colorbutton.js'] = []; + _$jscoverage['ui/colorbutton.js'][6] = 0; + _$jscoverage['ui/colorbutton.js'][7] = 0; + _$jscoverage['ui/colorbutton.js'][13] = 0; + _$jscoverage['ui/colorbutton.js'][14] = 0; + _$jscoverage['ui/colorbutton.js'][16] = 0; + _$jscoverage['ui/colorbutton.js'][18] = 0; + _$jscoverage['ui/colorbutton.js'][19] = 0; + _$jscoverage['ui/colorbutton.js'][24] = 0; + _$jscoverage['ui/colorbutton.js'][27] = 0; + _$jscoverage['ui/colorbutton.js'][32] = 0; + _$jscoverage['ui/colorbutton.js'][36] = 0; + _$jscoverage['ui/colorbutton.js'][37] = 0; + _$jscoverage['ui/colorbutton.js'][40] = 0; + _$jscoverage['ui/colorbutton.js'][43] = 0; + _$jscoverage['ui/colorbutton.js'][44] = 0; + _$jscoverage['ui/colorbutton.js'][47] = 0; + _$jscoverage['ui/colorbutton.js'][48] = 0; + _$jscoverage['ui/colorbutton.js'][49] = 0; + _$jscoverage['ui/colorbutton.js'][53] = 0; + _$jscoverage['ui/colorbutton.js'][54] = 0; + _$jscoverage['ui/colorbutton.js'][58] = 0; +} +_$jscoverage['ui/colorbutton.js'].source = ["///import core","///import uicore","///import ui/colorpicker.js","///import ui/popup.js","///import ui/splitbutton.js","(function (){"," var utils = baidu.editor.utils,"," uiUtils = baidu.editor.ui.uiUtils,"," ColorPicker = baidu.editor.ui.ColorPicker,"," Popup = baidu.editor.ui.Popup,"," SplitButton = baidu.editor.ui.SplitButton,"," ColorButton = baidu.editor.ui.ColorButton = function (options){"," this.initOptions(options);"," this.initColorButton();"," };"," ColorButton.prototype = {"," initColorButton: function (){"," var me = this;"," this.popup = new Popup({"," content: new ColorPicker({"," noColorText: me.editor.getLang(\"clearColor\"),"," editor:me.editor,"," onpickcolor: function (t, color){"," me._onPickColor(color);"," },"," onpicknocolor: function (t, color){"," me._onPickNoColor(color);"," }"," }),"," editor:me.editor"," });"," this.initSplitButton();"," },"," _SplitButton_postRender: SplitButton.prototype.postRender,"," postRender: function (){"," this._SplitButton_postRender();"," this.getDom('button_body').appendChild("," uiUtils.createElementByHtml('<div id=\"' + this.id + '_colorlump\" class=\"edui-colorlump\"></div>')"," );"," this.getDom().className += ' edui-colorbutton';"," },"," setColor: function (color){"," this.getDom('colorlump').style.backgroundColor = color;"," this.color = color;"," },"," _onPickColor: function (color){"," if (this.fireEvent('pickcolor', color) !== false) {"," this.setColor(color);"," this.popup.hide();"," }"," },"," _onPickNoColor: function (color){"," if (this.fireEvent('picknocolor') !== false) {"," this.popup.hide();"," }"," }"," };"," utils.inherits(ColorButton, SplitButton);","","})();"]; +_$jscoverage['ui/colorbutton.js'][6]++; +(function () { + _$jscoverage['ui/colorbutton.js'][7]++; + var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, ColorPicker = baidu.editor.ui.ColorPicker, Popup = baidu.editor.ui.Popup, SplitButton = baidu.editor.ui.SplitButton, ColorButton = (baidu.editor.ui.ColorButton = (function (options) { + _$jscoverage['ui/colorbutton.js'][13]++; + this.initOptions(options); + _$jscoverage['ui/colorbutton.js'][14]++; + this.initColorButton(); +})); + _$jscoverage['ui/colorbutton.js'][16]++; + ColorButton.prototype = {initColorButton: (function () { + _$jscoverage['ui/colorbutton.js'][18]++; + var me = this; + _$jscoverage['ui/colorbutton.js'][19]++; + this.popup = new Popup({content: new ColorPicker({noColorText: me.editor.getLang("clearColor"), editor: me.editor, onpickcolor: (function (t, color) { + _$jscoverage['ui/colorbutton.js'][24]++; + me._onPickColor(color); +}), onpicknocolor: (function (t, color) { + _$jscoverage['ui/colorbutton.js'][27]++; + me._onPickNoColor(color); +})}), editor: me.editor}); + _$jscoverage['ui/colorbutton.js'][32]++; + this.initSplitButton(); +}), _SplitButton_postRender: SplitButton.prototype.postRender, postRender: (function () { + _$jscoverage['ui/colorbutton.js'][36]++; + this._SplitButton_postRender(); + _$jscoverage['ui/colorbutton.js'][37]++; + this.getDom("button_body").appendChild(uiUtils.createElementByHtml(("
    "))); + _$jscoverage['ui/colorbutton.js'][40]++; + this.getDom().className += " edui-colorbutton"; +}), setColor: (function (color) { + _$jscoverage['ui/colorbutton.js'][43]++; + this.getDom("colorlump").style.backgroundColor = color; + _$jscoverage['ui/colorbutton.js'][44]++; + this.color = color; +}), _onPickColor: (function (color) { + _$jscoverage['ui/colorbutton.js'][47]++; + if ((this.fireEvent("pickcolor", color) !== false)) { + _$jscoverage['ui/colorbutton.js'][48]++; + this.setColor(color); + _$jscoverage['ui/colorbutton.js'][49]++; + this.popup.hide(); + } +}), _onPickNoColor: (function (color) { + _$jscoverage['ui/colorbutton.js'][53]++; + if ((this.fireEvent("picknocolor") !== false)) { + _$jscoverage['ui/colorbutton.js'][54]++; + this.popup.hide(); + } +})}; + _$jscoverage['ui/colorbutton.js'][58]++; + utils.inherits(ColorButton, SplitButton); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/colorpicker.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/colorpicker.js new file mode 100644 index 000000000..959014f93 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/colorpicker.js @@ -0,0 +1,136 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/colorpicker.js']) { + _$jscoverage['ui/colorpicker.js'] = []; + _$jscoverage['ui/colorpicker.js'][3] = 0; + _$jscoverage['ui/colorpicker.js'][4] = 0; + _$jscoverage['ui/colorpicker.js'][7] = 0; + _$jscoverage['ui/colorpicker.js'][8] = 0; + _$jscoverage['ui/colorpicker.js'][9] = 0; + _$jscoverage['ui/colorpicker.js'][12] = 0; + _$jscoverage['ui/colorpicker.js'][14] = 0; + _$jscoverage['ui/colorpicker.js'][17] = 0; + _$jscoverage['ui/colorpicker.js'][18] = 0; + _$jscoverage['ui/colorpicker.js'][19] = 0; + _$jscoverage['ui/colorpicker.js'][20] = 0; + _$jscoverage['ui/colorpicker.js'][24] = 0; + _$jscoverage['ui/colorpicker.js'][25] = 0; + _$jscoverage['ui/colorpicker.js'][26] = 0; + _$jscoverage['ui/colorpicker.js'][27] = 0; + _$jscoverage['ui/colorpicker.js'][31] = 0; + _$jscoverage['ui/colorpicker.js'][34] = 0; + _$jscoverage['ui/colorpicker.js'][37] = 0; + _$jscoverage['ui/colorpicker.js'][39] = 0; + _$jscoverage['ui/colorpicker.js'][48] = 0; + _$jscoverage['ui/colorpicker.js'][49] = 0; + _$jscoverage['ui/colorpicker.js'][57] = 0; + _$jscoverage['ui/colorpicker.js'][58] = 0; + _$jscoverage['ui/colorpicker.js'][59] = 0; + _$jscoverage['ui/colorpicker.js'][61] = 0; + _$jscoverage['ui/colorpicker.js'][71] = 0; + _$jscoverage['ui/colorpicker.js'][72] = 0; +} +_$jscoverage['ui/colorpicker.js'].source = ["///import core","///import uicore","(function (){"," var utils = baidu.editor.utils,"," UIBase = baidu.editor.ui.UIBase,"," ColorPicker = baidu.editor.ui.ColorPicker = function (options){"," this.initOptions(options);"," this.noColorText = this.noColorText || this.editor.getLang(\"clearColor\");"," this.initUIBase();"," };",""," ColorPicker.prototype = {"," getHtmlTpl: function (){"," return genColorPicker(this.noColorText,this.editor);"," },"," _onTableClick: function (evt){"," var tgt = evt.target || evt.srcElement;"," var color = tgt.getAttribute('data-color');"," if (color) {"," this.fireEvent('pickcolor', color);"," }"," },"," _onTableOver: function (evt){"," var tgt = evt.target || evt.srcElement;"," var color = tgt.getAttribute('data-color');"," if (color) {"," this.getDom('preview').style.backgroundColor = color;"," }"," },"," _onTableOut: function (){"," this.getDom('preview').style.backgroundColor = '';"," },"," _onPickNoColor: function (){"," this.fireEvent('picknocolor');"," }"," };"," utils.inherits(ColorPicker, UIBase);",""," var COLORS = ("," 'ffffff,000000,eeece1,1f497d,4f81bd,c0504d,9bbb59,8064a2,4bacc6,f79646,' +"," 'f2f2f2,7f7f7f,ddd9c3,c6d9f0,dbe5f1,f2dcdb,ebf1dd,e5e0ec,dbeef3,fdeada,' +"," 'd8d8d8,595959,c4bd97,8db3e2,b8cce4,e5b9b7,d7e3bc,ccc1d9,b7dde8,fbd5b5,' +"," 'bfbfbf,3f3f3f,938953,548dd4,95b3d7,d99694,c3d69b,b2a2c7,92cddc,fac08f,' +"," 'a5a5a5,262626,494429,17365d,366092,953734,76923c,5f497a,31859b,e36c09,' +"," '7f7f7f,0c0c0c,1d1b10,0f243e,244061,632423,4f6128,3f3151,205867,974806,' +"," 'c00000,ff0000,ffc000,ffff00,92d050,00b050,00b0f0,0070c0,002060,7030a0,').split(',');",""," function genColorPicker(noColorText,editor){"," var html = '<div id=\"##\" class=\"edui-colorpicker %%\">' +"," '<div class=\"edui-colorpicker-topbar edui-clearfix\">' +"," '<div unselectable=\"on\" id=\"##_preview\" class=\"edui-colorpicker-preview\"></div>' +"," '<div unselectable=\"on\" class=\"edui-colorpicker-nocolor\" onclick=\"$$._onPickNoColor(event, this);\">'+ noColorText +'</div>' +"," '</div>' +"," '<table class=\"edui-box\" style=\"border-collapse: collapse;\" onmouseover=\"$$._onTableOver(event, this);\" onmouseout=\"$$._onTableOut(event, this);\" onclick=\"return $$._onTableClick(event, this);\" cellspacing=\"0\" cellpadding=\"0\">' +"," '<tr style=\"border-bottom: 1px solid #ddd;font-size: 13px;line-height: 25px;color:#39C;padding-top: 2px\"><td colspan=\"10\">'+editor.getLang(\"themeColor\")+'</td> </tr>'+"," '<tr class=\"edui-colorpicker-tablefirstrow\" >';"," for (var i=0; i<COLORS.length; i++) {"," if (i && i%10 === 0) {"," html += '</tr>'+(i==60?'<tr style=\"border-bottom: 1px solid #ddd;font-size: 13px;line-height: 25px;color:#39C;\"><td colspan=\"10\">'+editor.getLang(\"standardColor\")+'</td></tr>':'')+'<tr'+(i==60?' class=\"edui-colorpicker-tablefirstrow\"':'')+'>';"," }"," html += i<70 ? '<td style=\"padding: 0 2px;\"><a hidefocus title=\"'+COLORS[i]+'\" onclick=\"return false;\" href=\"javascript:\" unselectable=\"on\" class=\"edui-box edui-colorpicker-colorcell\"' +"," ' data-color=\"#'+ COLORS[i] +'\"'+"," ' style=\"background-color:#'+ COLORS[i] +';border:solid #ccc;'+"," (i<10 || i>=60?'border-width:1px;':"," i>=10&&i<20?'border-width:1px 1px 0 1px;':",""," 'border-width:0 1px 0 1px;')+"," '\"' +"," '></a></td>':'';"," }"," html += '</tr></table></div>';"," return html;"," }","})();"]; +_$jscoverage['ui/colorpicker.js'][3]++; +(function () { + _$jscoverage['ui/colorpicker.js'][4]++; + var utils = baidu.editor.utils, UIBase = baidu.editor.ui.UIBase, ColorPicker = (baidu.editor.ui.ColorPicker = (function (options) { + _$jscoverage['ui/colorpicker.js'][7]++; + this.initOptions(options); + _$jscoverage['ui/colorpicker.js'][8]++; + this.noColorText = (this.noColorText || this.editor.getLang("clearColor")); + _$jscoverage['ui/colorpicker.js'][9]++; + this.initUIBase(); +})); + _$jscoverage['ui/colorpicker.js'][12]++; + ColorPicker.prototype = {getHtmlTpl: (function () { + _$jscoverage['ui/colorpicker.js'][14]++; + return genColorPicker(this.noColorText, this.editor); +}), _onTableClick: (function (evt) { + _$jscoverage['ui/colorpicker.js'][17]++; + var tgt = (evt.target || evt.srcElement); + _$jscoverage['ui/colorpicker.js'][18]++; + var color = tgt.getAttribute("data-color"); + _$jscoverage['ui/colorpicker.js'][19]++; + if (color) { + _$jscoverage['ui/colorpicker.js'][20]++; + this.fireEvent("pickcolor", color); + } +}), _onTableOver: (function (evt) { + _$jscoverage['ui/colorpicker.js'][24]++; + var tgt = (evt.target || evt.srcElement); + _$jscoverage['ui/colorpicker.js'][25]++; + var color = tgt.getAttribute("data-color"); + _$jscoverage['ui/colorpicker.js'][26]++; + if (color) { + _$jscoverage['ui/colorpicker.js'][27]++; + this.getDom("preview").style.backgroundColor = color; + } +}), _onTableOut: (function () { + _$jscoverage['ui/colorpicker.js'][31]++; + this.getDom("preview").style.backgroundColor = ""; +}), _onPickNoColor: (function () { + _$jscoverage['ui/colorpicker.js'][34]++; + this.fireEvent("picknocolor"); +})}; + _$jscoverage['ui/colorpicker.js'][37]++; + utils.inherits(ColorPicker, UIBase); + _$jscoverage['ui/colorpicker.js'][39]++; + var COLORS = "ffffff,000000,eeece1,1f497d,4f81bd,c0504d,9bbb59,8064a2,4bacc6,f79646,f2f2f2,7f7f7f,ddd9c3,c6d9f0,dbe5f1,f2dcdb,ebf1dd,e5e0ec,dbeef3,fdeada,d8d8d8,595959,c4bd97,8db3e2,b8cce4,e5b9b7,d7e3bc,ccc1d9,b7dde8,fbd5b5,bfbfbf,3f3f3f,938953,548dd4,95b3d7,d99694,c3d69b,b2a2c7,92cddc,fac08f,a5a5a5,262626,494429,17365d,366092,953734,76923c,5f497a,31859b,e36c09,7f7f7f,0c0c0c,1d1b10,0f243e,244061,632423,4f6128,3f3151,205867,974806,c00000,ff0000,ffc000,ffff00,92d050,00b050,00b0f0,0070c0,002060,7030a0,".split(","); + _$jscoverage['ui/colorpicker.js'][48]++; + function genColorPicker(noColorText, editor) { + _$jscoverage['ui/colorpicker.js'][49]++; + var html = ("
    " + "
    " + "
    " + "
    " + noColorText + "
    " + "
    " + "" + "" + ""); + _$jscoverage['ui/colorpicker.js'][57]++; + for (var i = 0; (i < COLORS.length); (i++)) { + _$jscoverage['ui/colorpicker.js'][58]++; + if ((i && ((i % 10) === 0))) { + _$jscoverage['ui/colorpicker.js'][59]++; + html += ("" + ((i == 60)? (""): "") + ""); + } + _$jscoverage['ui/colorpicker.js'][61]++; + html += ((i < 70)? (""): ""); +} + _$jscoverage['ui/colorpicker.js'][71]++; + html += "
    " + editor.getLang("themeColor") + "
    " + editor.getLang("standardColor") + "
    = 60))? "border-width:1px;": (((i >= 10) && (i < 20))? "border-width:1px 1px 0 1px;": "border-width:0 1px 0 1px;")) + "\"" + ">
    "; + _$jscoverage['ui/colorpicker.js'][72]++; + return html; +} +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/combox.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/combox.js new file mode 100644 index 000000000..dfb61613d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/combox.js @@ -0,0 +1,198 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/combox.js']) { + _$jscoverage['ui/combox.js'] = []; + _$jscoverage['ui/combox.js'][5] = 0; + _$jscoverage['ui/combox.js'][7] = 0; + _$jscoverage['ui/combox.js'][12] = 0; + _$jscoverage['ui/combox.js'][13] = 0; + _$jscoverage['ui/combox.js'][15] = 0; + _$jscoverage['ui/combox.js'][18] = 0; + _$jscoverage['ui/combox.js'][19] = 0; + _$jscoverage['ui/combox.js'][20] = 0; + _$jscoverage['ui/combox.js'][21] = 0; + _$jscoverage['ui/combox.js'][22] = 0; + _$jscoverage['ui/combox.js'][23] = 0; + _$jscoverage['ui/combox.js'][24] = 0; + _$jscoverage['ui/combox.js'][25] = 0; + _$jscoverage['ui/combox.js'][28] = 0; + _$jscoverage['ui/combox.js'][36] = 0; + _$jscoverage['ui/combox.js'][40] = 0; + _$jscoverage['ui/combox.js'][41] = 0; + _$jscoverage['ui/combox.js'][42] = 0; + _$jscoverage['ui/combox.js'][45] = 0; + _$jscoverage['ui/combox.js'][46] = 0; + _$jscoverage['ui/combox.js'][47] = 0; + _$jscoverage['ui/combox.js'][48] = 0; + _$jscoverage['ui/combox.js'][49] = 0; + _$jscoverage['ui/combox.js'][52] = 0; + _$jscoverage['ui/combox.js'][55] = 0; + _$jscoverage['ui/combox.js'][56] = 0; + _$jscoverage['ui/combox.js'][57] = 0; + _$jscoverage['ui/combox.js'][58] = 0; + _$jscoverage['ui/combox.js'][59] = 0; + _$jscoverage['ui/combox.js'][61] = 0; + _$jscoverage['ui/combox.js'][62] = 0; + _$jscoverage['ui/combox.js'][63] = 0; + _$jscoverage['ui/combox.js'][67] = 0; + _$jscoverage['ui/combox.js'][68] = 0; + _$jscoverage['ui/combox.js'][71] = 0; + _$jscoverage['ui/combox.js'][74] = 0; + _$jscoverage['ui/combox.js'][75] = 0; + _$jscoverage['ui/combox.js'][76] = 0; + _$jscoverage['ui/combox.js'][79] = 0; + _$jscoverage['ui/combox.js'][82] = 0; + _$jscoverage['ui/combox.js'][85] = 0; + _$jscoverage['ui/combox.js'][86] = 0; + _$jscoverage['ui/combox.js'][87] = 0; + _$jscoverage['ui/combox.js'][88] = 0; + _$jscoverage['ui/combox.js'][92] = 0; +} +_$jscoverage['ui/combox.js'].source = ["///import core","///import uicore","///import ui/menu.js","///import ui/splitbutton.js","(function (){"," // todo: menu和item提成通用list"," var utils = baidu.editor.utils,"," uiUtils = baidu.editor.ui.uiUtils,"," Menu = baidu.editor.ui.Menu,"," SplitButton = baidu.editor.ui.SplitButton,"," Combox = baidu.editor.ui.Combox = function (options){"," this.initOptions(options);"," this.initCombox();"," };"," Combox.prototype = {"," uiName: 'combox',"," initCombox: function (){"," var me = this;"," this.items = this.items || [];"," for (var i=0; i<this.items.length; i++) {"," var item = this.items[i];"," item.uiName = 'listitem';"," item.index = i;"," item.onclick = function (){"," me.selectByIndex(this.index);"," };"," }"," this.popup = new Menu({"," items: this.items,"," uiName: 'list',"," editor:this.editor,"," captureWheel: true,"," combox: this"," });",""," this.initSplitButton();"," },"," _SplitButton_postRender: SplitButton.prototype.postRender,"," postRender: function (){"," this._SplitButton_postRender();"," this.setLabel(this.label || '');"," this.setValue(this.initValue || '');"," },"," showPopup: function (){"," var rect = uiUtils.getClientRect(this.getDom());"," rect.top += 1;"," rect.bottom -= 1;"," rect.height -= 2;"," this.popup.showAnchorRect(rect);"," },"," getValue: function (){"," return this.value;"," },"," setValue: function (value){"," var index = this.indexByValue(value);"," if (index != -1) {"," this.selectedIndex = index;"," this.setLabel(this.items[index].label);"," this.value = this.items[index].value;"," } else {"," this.selectedIndex = -1;"," this.setLabel(this.getLabelForUnknowValue(value));"," this.value = value;"," }"," },"," setLabel: function (label){"," this.getDom('button_body').innerHTML = label;"," this.label = label;"," },"," getLabelForUnknowValue: function (value){"," return value;"," },"," indexByValue: function (value){"," for (var i=0; i<this.items.length; i++) {"," if (value == this.items[i].value) {"," return i;"," }"," }"," return -1;"," },"," getItem: function (index){"," return this.items[index];"," },"," selectByIndex: function (index){"," if (index < this.items.length && this.fireEvent('select', index) !== false) {"," this.selectedIndex = index;"," this.value = this.items[index].value;"," this.setLabel(this.items[index].label);"," }"," }"," };"," utils.inherits(Combox, SplitButton);","})();"]; +_$jscoverage['ui/combox.js'][5]++; +(function () { + _$jscoverage['ui/combox.js'][7]++; + var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, Menu = baidu.editor.ui.Menu, SplitButton = baidu.editor.ui.SplitButton, Combox = (baidu.editor.ui.Combox = (function (options) { + _$jscoverage['ui/combox.js'][12]++; + this.initOptions(options); + _$jscoverage['ui/combox.js'][13]++; + this.initCombox(); +})); + _$jscoverage['ui/combox.js'][15]++; + Combox.prototype = {uiName: "combox", initCombox: (function () { + _$jscoverage['ui/combox.js'][18]++; + var me = this; + _$jscoverage['ui/combox.js'][19]++; + this.items = (this.items || []); + _$jscoverage['ui/combox.js'][20]++; + for (var i = 0; (i < this.items.length); (i++)) { + _$jscoverage['ui/combox.js'][21]++; + var item = this.items[i]; + _$jscoverage['ui/combox.js'][22]++; + item.uiName = "listitem"; + _$jscoverage['ui/combox.js'][23]++; + item.index = i; + _$jscoverage['ui/combox.js'][24]++; + item.onclick = (function () { + _$jscoverage['ui/combox.js'][25]++; + me.selectByIndex(this.index); +}); +} + _$jscoverage['ui/combox.js'][28]++; + this.popup = new Menu({items: this.items, uiName: "list", editor: this.editor, captureWheel: true, combox: this}); + _$jscoverage['ui/combox.js'][36]++; + this.initSplitButton(); +}), _SplitButton_postRender: SplitButton.prototype.postRender, postRender: (function () { + _$jscoverage['ui/combox.js'][40]++; + this._SplitButton_postRender(); + _$jscoverage['ui/combox.js'][41]++; + this.setLabel((this.label || "")); + _$jscoverage['ui/combox.js'][42]++; + this.setValue((this.initValue || "")); +}), showPopup: (function () { + _$jscoverage['ui/combox.js'][45]++; + var rect = uiUtils.getClientRect(this.getDom()); + _$jscoverage['ui/combox.js'][46]++; + rect.top += 1; + _$jscoverage['ui/combox.js'][47]++; + rect.bottom -= 1; + _$jscoverage['ui/combox.js'][48]++; + rect.height -= 2; + _$jscoverage['ui/combox.js'][49]++; + this.popup.showAnchorRect(rect); +}), getValue: (function () { + _$jscoverage['ui/combox.js'][52]++; + return this.value; +}), setValue: (function (value) { + _$jscoverage['ui/combox.js'][55]++; + var index = this.indexByValue(value); + _$jscoverage['ui/combox.js'][56]++; + if ((index != -1)) { + _$jscoverage['ui/combox.js'][57]++; + this.selectedIndex = index; + _$jscoverage['ui/combox.js'][58]++; + this.setLabel(this.items[index].label); + _$jscoverage['ui/combox.js'][59]++; + this.value = this.items[index].value; + } + else { + _$jscoverage['ui/combox.js'][61]++; + this.selectedIndex = -1; + _$jscoverage['ui/combox.js'][62]++; + this.setLabel(this.getLabelForUnknowValue(value)); + _$jscoverage['ui/combox.js'][63]++; + this.value = value; + } +}), setLabel: (function (label) { + _$jscoverage['ui/combox.js'][67]++; + this.getDom("button_body").innerHTML = label; + _$jscoverage['ui/combox.js'][68]++; + this.label = label; +}), getLabelForUnknowValue: (function (value) { + _$jscoverage['ui/combox.js'][71]++; + return value; +}), indexByValue: (function (value) { + _$jscoverage['ui/combox.js'][74]++; + for (var i = 0; (i < this.items.length); (i++)) { + _$jscoverage['ui/combox.js'][75]++; + if ((value == this.items[i].value)) { + _$jscoverage['ui/combox.js'][76]++; + return i; + } +} + _$jscoverage['ui/combox.js'][79]++; + return -1; +}), getItem: (function (index) { + _$jscoverage['ui/combox.js'][82]++; + return this.items[index]; +}), selectByIndex: (function (index) { + _$jscoverage['ui/combox.js'][85]++; + if (((index < this.items.length) && (this.fireEvent("select", index) !== false))) { + _$jscoverage['ui/combox.js'][86]++; + this.selectedIndex = index; + _$jscoverage['ui/combox.js'][87]++; + this.value = this.items[index].value; + _$jscoverage['ui/combox.js'][88]++; + this.setLabel(this.items[index].label); + } +})}; + _$jscoverage['ui/combox.js'][92]++; + utils.inherits(Combox, SplitButton); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/dialog.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/dialog.js new file mode 100644 index 000000000..798216438 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/dialog.js @@ -0,0 +1,535 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/dialog.js']) { + _$jscoverage['ui/dialog.js'] = []; + _$jscoverage['ui/dialog.js'][5] = 0; + _$jscoverage['ui/dialog.js'][6] = 0; + _$jscoverage['ui/dialog.js'][13] = 0; + _$jscoverage['ui/dialog.js'][19] = 0; + _$jscoverage['ui/dialog.js'][24] = 0; + _$jscoverage['ui/dialog.js'][26] = 0; + _$jscoverage['ui/dialog.js'][27] = 0; + _$jscoverage['ui/dialog.js'][28] = 0; + _$jscoverage['ui/dialog.js'][32] = 0; + _$jscoverage['ui/dialog.js'][34] = 0; + _$jscoverage['ui/dialog.js'][35] = 0; + _$jscoverage['ui/dialog.js'][39] = 0; + _$jscoverage['ui/dialog.js'][43] = 0; + _$jscoverage['ui/dialog.js'][48] = 0; + _$jscoverage['ui/dialog.js'][51] = 0; + _$jscoverage['ui/dialog.js'][52] = 0; + _$jscoverage['ui/dialog.js'][53] = 0; + _$jscoverage['ui/dialog.js'][54] = 0; + _$jscoverage['ui/dialog.js'][60] = 0; + _$jscoverage['ui/dialog.js'][65] = 0; + _$jscoverage['ui/dialog.js'][66] = 0; + _$jscoverage['ui/dialog.js'][67] = 0; + _$jscoverage['ui/dialog.js'][68] = 0; + _$jscoverage['ui/dialog.js'][71] = 0; + _$jscoverage['ui/dialog.js'][72] = 0; + _$jscoverage['ui/dialog.js'][73] = 0; + _$jscoverage['ui/dialog.js'][74] = 0; + _$jscoverage['ui/dialog.js'][75] = 0; + _$jscoverage['ui/dialog.js'][76] = 0; + _$jscoverage['ui/dialog.js'][77] = 0; + _$jscoverage['ui/dialog.js'][79] = 0; + _$jscoverage['ui/dialog.js'][80] = 0; + _$jscoverage['ui/dialog.js'][81] = 0; + _$jscoverage['ui/dialog.js'][83] = 0; + _$jscoverage['ui/dialog.js'][84] = 0; + _$jscoverage['ui/dialog.js'][87] = 0; + _$jscoverage['ui/dialog.js'][88] = 0; + _$jscoverage['ui/dialog.js'][89] = 0; + _$jscoverage['ui/dialog.js'][90] = 0; + _$jscoverage['ui/dialog.js'][91] = 0; + _$jscoverage['ui/dialog.js'][92] = 0; + _$jscoverage['ui/dialog.js'][93] = 0; + _$jscoverage['ui/dialog.js'][94] = 0; + _$jscoverage['ui/dialog.js'][98] = 0; + _$jscoverage['ui/dialog.js'][99] = 0; + _$jscoverage['ui/dialog.js'][101] = 0; + _$jscoverage['ui/dialog.js'][104] = 0; + _$jscoverage['ui/dialog.js'][105] = 0; + _$jscoverage['ui/dialog.js'][106] = 0; + _$jscoverage['ui/dialog.js'][107] = 0; + _$jscoverage['ui/dialog.js'][108] = 0; + _$jscoverage['ui/dialog.js'][111] = 0; + _$jscoverage['ui/dialog.js'][114] = 0; + _$jscoverage['ui/dialog.js'][116] = 0; + _$jscoverage['ui/dialog.js'][117] = 0; + _$jscoverage['ui/dialog.js'][118] = 0; + _$jscoverage['ui/dialog.js'][119] = 0; + _$jscoverage['ui/dialog.js'][121] = 0; + _$jscoverage['ui/dialog.js'][126] = 0; + _$jscoverage['ui/dialog.js'][140] = 0; + _$jscoverage['ui/dialog.js'][141] = 0; + _$jscoverage['ui/dialog.js'][142] = 0; + _$jscoverage['ui/dialog.js'][144] = 0; + _$jscoverage['ui/dialog.js'][145] = 0; + _$jscoverage['ui/dialog.js'][146] = 0; + _$jscoverage['ui/dialog.js'][148] = 0; + _$jscoverage['ui/dialog.js'][149] = 0; + _$jscoverage['ui/dialog.js'][150] = 0; + _$jscoverage['ui/dialog.js'][152] = 0; + _$jscoverage['ui/dialog.js'][153] = 0; + _$jscoverage['ui/dialog.js'][155] = 0; + _$jscoverage['ui/dialog.js'][156] = 0; + _$jscoverage['ui/dialog.js'][157] = 0; + _$jscoverage['ui/dialog.js'][160] = 0; + _$jscoverage['ui/dialog.js'][161] = 0; + _$jscoverage['ui/dialog.js'][162] = 0; + _$jscoverage['ui/dialog.js'][163] = 0; + _$jscoverage['ui/dialog.js'][169] = 0; + _$jscoverage['ui/dialog.js'][171] = 0; + _$jscoverage['ui/dialog.js'][172] = 0; + _$jscoverage['ui/dialog.js'][173] = 0; + _$jscoverage['ui/dialog.js'][176] = 0; + _$jscoverage['ui/dialog.js'][177] = 0; + _$jscoverage['ui/dialog.js'][178] = 0; + _$jscoverage['ui/dialog.js'][180] = 0; + _$jscoverage['ui/dialog.js'][182] = 0; + _$jscoverage['ui/dialog.js'][184] = 0; + _$jscoverage['ui/dialog.js'][185] = 0; + _$jscoverage['ui/dialog.js'][186] = 0; + _$jscoverage['ui/dialog.js'][187] = 0; + _$jscoverage['ui/dialog.js'][188] = 0; + _$jscoverage['ui/dialog.js'][195] = 0; + _$jscoverage['ui/dialog.js'][196] = 0; + _$jscoverage['ui/dialog.js'][205] = 0; + _$jscoverage['ui/dialog.js'][208] = 0; + _$jscoverage['ui/dialog.js'][209] = 0; + _$jscoverage['ui/dialog.js'][210] = 0; + _$jscoverage['ui/dialog.js'][211] = 0; + _$jscoverage['ui/dialog.js'][212] = 0; + _$jscoverage['ui/dialog.js'][215] = 0; + _$jscoverage['ui/dialog.js'][216] = 0; + _$jscoverage['ui/dialog.js'][217] = 0; + _$jscoverage['ui/dialog.js'][218] = 0; + _$jscoverage['ui/dialog.js'][219] = 0; + _$jscoverage['ui/dialog.js'][221] = 0; + _$jscoverage['ui/dialog.js'][222] = 0; + _$jscoverage['ui/dialog.js'][223] = 0; + _$jscoverage['ui/dialog.js'][226] = 0; + _$jscoverage['ui/dialog.js'][227] = 0; + _$jscoverage['ui/dialog.js'][228] = 0; + _$jscoverage['ui/dialog.js'][234] = 0; + _$jscoverage['ui/dialog.js'][235] = 0; + _$jscoverage['ui/dialog.js'][236] = 0; + _$jscoverage['ui/dialog.js'][242] = 0; + _$jscoverage['ui/dialog.js'][243] = 0; + _$jscoverage['ui/dialog.js'][246] = 0; + _$jscoverage['ui/dialog.js'][247] = 0; + _$jscoverage['ui/dialog.js'][250] = 0; + _$jscoverage['ui/dialog.js'][251] = 0; + _$jscoverage['ui/dialog.js'][252] = 0; + _$jscoverage['ui/dialog.js'][253] = 0; + _$jscoverage['ui/dialog.js'][257] = 0; + _$jscoverage['ui/dialog.js'][260] = 0; + _$jscoverage['ui/dialog.js'][261] = 0; + _$jscoverage['ui/dialog.js'][262] = 0; + _$jscoverage['ui/dialog.js'][263] = 0; + _$jscoverage['ui/dialog.js'][264] = 0; + _$jscoverage['ui/dialog.js'][268] = 0; + _$jscoverage['ui/dialog.js'][270] = 0; + _$jscoverage['ui/dialog.js'][271] = 0; + _$jscoverage['ui/dialog.js'][273] = 0; + _$jscoverage['ui/dialog.js'][274] = 0; + _$jscoverage['ui/dialog.js'][277] = 0; + _$jscoverage['ui/dialog.js'][278] = 0; + _$jscoverage['ui/dialog.js'][279] = 0; + _$jscoverage['ui/dialog.js'][280] = 0; + _$jscoverage['ui/dialog.js'][285] = 0; + _$jscoverage['ui/dialog.js'][288] = 0; + _$jscoverage['ui/dialog.js'][289] = 0; + _$jscoverage['ui/dialog.js'][293] = 0; +} +_$jscoverage['ui/dialog.js'].source = ["///import core","///import uicore","///import ui/mask.js","///import ui/button.js","(function (){"," var utils = baidu.editor.utils,"," domUtils = baidu.editor.dom.domUtils,"," uiUtils = baidu.editor.ui.uiUtils,"," Mask = baidu.editor.ui.Mask,"," UIBase = baidu.editor.ui.UIBase,"," Button = baidu.editor.ui.Button,"," Dialog = baidu.editor.ui.Dialog = function (options){"," this.initOptions(utils.extend({"," autoReset: true,"," draggable: true,"," onok: function (){},"," oncancel: function (){},"," onclose: function (t, ok){"," return ok ? this.onok() : this.oncancel();"," },"," //是否控制dialog中的scroll事件, 默认为不阻止"," holdScroll: false"," },options));"," this.initDialog();"," };"," var modalMask;"," var dragMask;"," Dialog.prototype = {"," draggable: false,"," uiName: 'dialog',"," initDialog: function (){"," var me = this,"," theme=this.editor.options.theme;"," this.initUIBase();"," this.modalMask = (modalMask || (modalMask = new Mask({"," className: 'edui-dialog-modalmask',"," theme:theme"," })));"," this.dragMask = (dragMask || (dragMask = new Mask({"," className: 'edui-dialog-dragmask',"," theme:theme"," })));"," this.closeButton = new Button({"," className: 'edui-dialog-closebutton',"," title: me.closeDialog,"," theme:theme,"," onclick: function (){"," me.close(false);"," }"," });"," if (this.buttons) {"," for (var i=0; i<this.buttons.length; i++) {"," if (!(this.buttons[i] instanceof Button)) {"," this.buttons[i] = new Button(this.buttons[i]);"," }"," }"," }"," },"," fitSize: function (){"," var popBodyEl = this.getDom('body');","// if (!(baidu.editor.browser.ie && baidu.editor.browser.version == 7)) {","// uiUtils.removeStyle(popBodyEl, 'width');","// uiUtils.removeStyle(popBodyEl, 'height');","// }"," var size = this.mesureSize();"," popBodyEl.style.width = size.width + 'px';"," popBodyEl.style.height = size.height + 'px';"," return size;"," },"," safeSetOffset: function (offset){"," var me = this;"," var el = me.getDom();"," var vpRect = uiUtils.getViewportRect();"," var rect = uiUtils.getClientRect(el);"," var left = offset.left;"," if (left + rect.width > vpRect.right) {"," left = vpRect.right - rect.width;"," }"," var top = offset.top;"," if (top + rect.height > vpRect.bottom) {"," top = vpRect.bottom - rect.height;"," }"," el.style.left = Math.max(left, 0) + 'px';"," el.style.top = Math.max(top, 0) + 'px';"," },"," showAtCenter: function (){"," this.getDom().style.display = '';"," var vpRect = uiUtils.getViewportRect();"," var popSize = this.fitSize();"," var titleHeight = this.getDom('titlebar').offsetHeight | 0;"," var left = vpRect.width / 2 - popSize.width / 2;"," var top = vpRect.height / 2 - (popSize.height - titleHeight) / 2 - titleHeight;"," var popEl = this.getDom();"," this.safeSetOffset({"," left: Math.max(left | 0, 0),"," top: Math.max(top | 0, 0)"," });"," if (!domUtils.hasClass(popEl, 'edui-state-centered')) {"," popEl.className += ' edui-state-centered';"," }"," this._show();"," },"," getContentHtml: function (){"," var contentHtml = '';"," if (typeof this.content == 'string') {"," contentHtml = this.content;"," } else if (this.iframeUrl) {"," contentHtml = '<span id=\"'+ this.id +'_contmask\" class=\"dialogcontmask\"></span><iframe id=\"'+ this.id +"," '_iframe\" class=\"%%-iframe\" height=\"100%\" width=\"100%\" frameborder=\"0\" src=\"'+ this.iframeUrl +'\"></iframe>';"," }"," return contentHtml;"," },"," getHtmlTpl: function (){"," var footHtml = '';",""," if (this.buttons) {"," var buff = [];"," for (var i=0; i<this.buttons.length; i++) {"," buff[i] = this.buttons[i].renderHtml();"," }"," footHtml = '<div class=\"%%-foot\">' +"," '<div id=\"##_buttons\" class=\"%%-buttons\">' + buff.join('') + '</div>' +"," '</div>';"," }",""," return '<div id=\"##\" class=\"%%\"><div class=\"%%-wrap\"><div id=\"##_body\" class=\"%%-body\">' +"," '<div class=\"%%-shadow\"></div>' +"," '<div id=\"##_titlebar\" class=\"%%-titlebar\">' +"," '<div class=\"%%-draghandle\" onmousedown=\"$$._onTitlebarMouseDown(event, this);\">' +"," '<span class=\"%%-caption\">' + (this.title || '') + '</span>' +"," '</div>' +"," this.closeButton.renderHtml() +"," '</div>' +"," '<div id=\"##_content\" class=\"%%-content\">'+ ( this.autoReset ? '' : this.getContentHtml()) +'</div>' +"," footHtml +"," '</div></div></div>';"," },"," postRender: function (){"," // todo: 保持居中/记住上次关闭位置选项"," if (!this.modalMask.getDom()) {"," this.modalMask.render();"," this.modalMask.hide();"," }"," if (!this.dragMask.getDom()) {"," this.dragMask.render();"," this.dragMask.hide();"," }"," var me = this;"," this.addListener('show', function (){"," me.modalMask.show(this.getDom().style.zIndex - 2);"," });"," this.addListener('hide', function (){"," me.modalMask.hide();"," });"," if (this.buttons) {"," for (var i=0; i<this.buttons.length; i++) {"," this.buttons[i].postRender();"," }"," }"," domUtils.on(window, 'resize', function (){"," setTimeout(function (){"," if (!me.isHidden()) {"," me.safeSetOffset(uiUtils.getClientRect(me.getDom()));"," }"," });"," });",""," //hold住scroll事件,防止dialog的滚动影响页面"," if( this.holdScroll ) {",""," if( !me.iframeUrl ) {"," domUtils.on( document.getElementById( me.id + \"_iframe\"), !browser.gecko ? \"mousewheel\" : \"DOMMouseScroll\", function(e){"," domUtils.preventDefault(e);"," } );"," } else {"," me.addListener('dialogafterreset', function(){"," window.setTimeout(function(){"," var iframeWindow = document.getElementById( me.id + \"_iframe\").contentWindow;",""," if( browser.ie ) {",""," var timer = window.setInterval(function(){",""," if( iframeWindow.document && iframeWindow.document.body ) {"," window.clearInterval( timer );"," timer = null;"," domUtils.on( iframeWindow.document.body, !browser.gecko ? \"mousewheel\" : \"DOMMouseScroll\", function(e){"," domUtils.preventDefault(e);"," } );"," }",""," }, 100);",""," } else {"," domUtils.on( iframeWindow, !browser.gecko ? \"mousewheel\" : \"DOMMouseScroll\", function(e){"," domUtils.preventDefault(e);"," } );"," }",""," }, 1);"," });"," }",""," }"," this._hide();"," },"," mesureSize: function (){"," var body = this.getDom('body');"," var width = uiUtils.getClientRect(this.getDom('content')).width;"," var dialogBodyStyle = body.style;"," dialogBodyStyle.width = width;"," return uiUtils.getClientRect(body);"," },"," _onTitlebarMouseDown: function (evt, el){"," if (this.draggable) {"," var rect;"," var vpRect = uiUtils.getViewportRect();"," var me = this;"," uiUtils.startDrag(evt, {"," ondragstart: function (){"," rect = uiUtils.getClientRect(me.getDom());"," me.getDom('contmask').style.visibility = 'visible';"," me.dragMask.show(me.getDom().style.zIndex - 1);"," },"," ondragmove: function (x, y){"," var left = rect.left + x;"," var top = rect.top + y;"," me.safeSetOffset({"," left: left,"," top: top"," });"," },"," ondragstop: function (){"," me.getDom('contmask').style.visibility = 'hidden';"," domUtils.removeClasses(me.getDom(), ['edui-state-centered']);"," me.dragMask.hide();"," }"," });"," }"," },"," reset: function (){"," this.getDom('content').innerHTML = this.getContentHtml();"," this.fireEvent('dialogafterreset');"," },"," _show: function (){"," if (this._hidden) {"," this.getDom().style.display = '';",""," //要高过编辑器的zindxe"," this.editor.container.style.zIndex && (this.getDom().style.zIndex = this.editor.container.style.zIndex * 1 + 10);"," this._hidden = false;"," this.fireEvent('show');"," baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = this.getDom().style.zIndex - 4;"," }"," },"," isHidden: function (){"," return this._hidden;"," },"," _hide: function (){"," if (!this._hidden) {"," this.getDom().style.display = 'none';"," this.getDom().style.zIndex = '';"," this._hidden = true;"," this.fireEvent('hide');"," }"," },"," open: function (){"," if (this.autoReset) {"," //有可能还没有渲染"," try{"," this.reset();"," }catch(e){"," this.render();"," this.open()"," }"," }"," this.showAtCenter();"," if (this.iframeUrl) {"," try {"," this.getDom('iframe').focus();"," } catch(ex){}"," }"," },"," _onCloseButtonClick: function (evt, el){"," this.close(false);"," },"," close: function (ok){"," if (this.fireEvent('close', ok) !== false) {"," this._hide();"," }"," }"," };"," utils.inherits(Dialog, UIBase);","})();"]; +_$jscoverage['ui/dialog.js'][5]++; +(function () { + _$jscoverage['ui/dialog.js'][6]++; + var utils = baidu.editor.utils, domUtils = baidu.editor.dom.domUtils, uiUtils = baidu.editor.ui.uiUtils, Mask = baidu.editor.ui.Mask, UIBase = baidu.editor.ui.UIBase, Button = baidu.editor.ui.Button, Dialog = (baidu.editor.ui.Dialog = (function (options) { + _$jscoverage['ui/dialog.js'][13]++; + this.initOptions(utils.extend({autoReset: true, draggable: true, onok: (function () { +}), oncancel: (function () { +}), onclose: (function (t, ok) { + _$jscoverage['ui/dialog.js'][19]++; + return (ok? this.onok(): this.oncancel()); +}), holdScroll: false}, options)); + _$jscoverage['ui/dialog.js'][24]++; + this.initDialog(); +})); + _$jscoverage['ui/dialog.js'][26]++; + var modalMask; + _$jscoverage['ui/dialog.js'][27]++; + var dragMask; + _$jscoverage['ui/dialog.js'][28]++; + Dialog.prototype = {draggable: false, uiName: "dialog", initDialog: (function () { + _$jscoverage['ui/dialog.js'][32]++; + var me = this, theme = this.editor.options.theme; + _$jscoverage['ui/dialog.js'][34]++; + this.initUIBase(); + _$jscoverage['ui/dialog.js'][35]++; + this.modalMask = (modalMask || (modalMask = new Mask({className: "edui-dialog-modalmask", theme: theme}))); + _$jscoverage['ui/dialog.js'][39]++; + this.dragMask = (dragMask || (dragMask = new Mask({className: "edui-dialog-dragmask", theme: theme}))); + _$jscoverage['ui/dialog.js'][43]++; + this.closeButton = new Button({className: "edui-dialog-closebutton", title: me.closeDialog, theme: theme, onclick: (function () { + _$jscoverage['ui/dialog.js'][48]++; + me.close(false); +})}); + _$jscoverage['ui/dialog.js'][51]++; + if (this.buttons) { + _$jscoverage['ui/dialog.js'][52]++; + for (var i = 0; (i < this.buttons.length); (i++)) { + _$jscoverage['ui/dialog.js'][53]++; + if ((! (this.buttons[i] instanceof Button))) { + _$jscoverage['ui/dialog.js'][54]++; + this.buttons[i] = new Button(this.buttons[i]); + } +} + } +}), fitSize: (function () { + _$jscoverage['ui/dialog.js'][60]++; + var popBodyEl = this.getDom("body"); + _$jscoverage['ui/dialog.js'][65]++; + var size = this.mesureSize(); + _$jscoverage['ui/dialog.js'][66]++; + popBodyEl.style.width = (size.width + "px"); + _$jscoverage['ui/dialog.js'][67]++; + popBodyEl.style.height = (size.height + "px"); + _$jscoverage['ui/dialog.js'][68]++; + return size; +}), safeSetOffset: (function (offset) { + _$jscoverage['ui/dialog.js'][71]++; + var me = this; + _$jscoverage['ui/dialog.js'][72]++; + var el = me.getDom(); + _$jscoverage['ui/dialog.js'][73]++; + var vpRect = uiUtils.getViewportRect(); + _$jscoverage['ui/dialog.js'][74]++; + var rect = uiUtils.getClientRect(el); + _$jscoverage['ui/dialog.js'][75]++; + var left = offset.left; + _$jscoverage['ui/dialog.js'][76]++; + if (((left + rect.width) > vpRect.right)) { + _$jscoverage['ui/dialog.js'][77]++; + left = (vpRect.right - rect.width); + } + _$jscoverage['ui/dialog.js'][79]++; + var top = offset.top; + _$jscoverage['ui/dialog.js'][80]++; + if (((top + rect.height) > vpRect.bottom)) { + _$jscoverage['ui/dialog.js'][81]++; + top = (vpRect.bottom - rect.height); + } + _$jscoverage['ui/dialog.js'][83]++; + el.style.left = (Math.max(left, 0) + "px"); + _$jscoverage['ui/dialog.js'][84]++; + el.style.top = (Math.max(top, 0) + "px"); +}), showAtCenter: (function () { + _$jscoverage['ui/dialog.js'][87]++; + this.getDom().style.display = ""; + _$jscoverage['ui/dialog.js'][88]++; + var vpRect = uiUtils.getViewportRect(); + _$jscoverage['ui/dialog.js'][89]++; + var popSize = this.fitSize(); + _$jscoverage['ui/dialog.js'][90]++; + var titleHeight = (this.getDom("titlebar").offsetHeight | 0); + _$jscoverage['ui/dialog.js'][91]++; + var left = ((vpRect.width / 2) - (popSize.width / 2)); + _$jscoverage['ui/dialog.js'][92]++; + var top = ((vpRect.height / 2) - ((popSize.height - titleHeight) / 2) - titleHeight); + _$jscoverage['ui/dialog.js'][93]++; + var popEl = this.getDom(); + _$jscoverage['ui/dialog.js'][94]++; + this.safeSetOffset({left: Math.max((left | 0), 0), top: Math.max((top | 0), 0)}); + _$jscoverage['ui/dialog.js'][98]++; + if ((! domUtils.hasClass(popEl, "edui-state-centered"))) { + _$jscoverage['ui/dialog.js'][99]++; + popEl.className += " edui-state-centered"; + } + _$jscoverage['ui/dialog.js'][101]++; + this._show(); +}), getContentHtml: (function () { + _$jscoverage['ui/dialog.js'][104]++; + var contentHtml = ""; + _$jscoverage['ui/dialog.js'][105]++; + if (((typeof this.content) == "string")) { + _$jscoverage['ui/dialog.js'][106]++; + contentHtml = this.content; + } + else { + _$jscoverage['ui/dialog.js'][107]++; + if (this.iframeUrl) { + _$jscoverage['ui/dialog.js'][108]++; + contentHtml = (""); + } + } + _$jscoverage['ui/dialog.js'][111]++; + return contentHtml; +}), getHtmlTpl: (function () { + _$jscoverage['ui/dialog.js'][114]++; + var footHtml = ""; + _$jscoverage['ui/dialog.js'][116]++; + if (this.buttons) { + _$jscoverage['ui/dialog.js'][117]++; + var buff = []; + _$jscoverage['ui/dialog.js'][118]++; + for (var i = 0; (i < this.buttons.length); (i++)) { + _$jscoverage['ui/dialog.js'][119]++; + buff[i] = this.buttons[i].renderHtml(); +} + _$jscoverage['ui/dialog.js'][121]++; + footHtml = ("
    " + "
    " + buff.join("") + "
    " + "
    "); + } + _$jscoverage['ui/dialog.js'][126]++; + return ("
    " + "
    " + "
    " + "
    " + "" + (this.title || "") + "" + "
    " + this.closeButton.renderHtml() + "
    " + "
    " + (this.autoReset? "": this.getContentHtml()) + "
    " + footHtml + "
    "); +}), postRender: (function () { + _$jscoverage['ui/dialog.js'][140]++; + if ((! this.modalMask.getDom())) { + _$jscoverage['ui/dialog.js'][141]++; + this.modalMask.render(); + _$jscoverage['ui/dialog.js'][142]++; + this.modalMask.hide(); + } + _$jscoverage['ui/dialog.js'][144]++; + if ((! this.dragMask.getDom())) { + _$jscoverage['ui/dialog.js'][145]++; + this.dragMask.render(); + _$jscoverage['ui/dialog.js'][146]++; + this.dragMask.hide(); + } + _$jscoverage['ui/dialog.js'][148]++; + var me = this; + _$jscoverage['ui/dialog.js'][149]++; + this.addListener("show", (function () { + _$jscoverage['ui/dialog.js'][150]++; + me.modalMask.show((this.getDom().style.zIndex - 2)); +})); + _$jscoverage['ui/dialog.js'][152]++; + this.addListener("hide", (function () { + _$jscoverage['ui/dialog.js'][153]++; + me.modalMask.hide(); +})); + _$jscoverage['ui/dialog.js'][155]++; + if (this.buttons) { + _$jscoverage['ui/dialog.js'][156]++; + for (var i = 0; (i < this.buttons.length); (i++)) { + _$jscoverage['ui/dialog.js'][157]++; + this.buttons[i].postRender(); +} + } + _$jscoverage['ui/dialog.js'][160]++; + domUtils.on(window, "resize", (function () { + _$jscoverage['ui/dialog.js'][161]++; + setTimeout((function () { + _$jscoverage['ui/dialog.js'][162]++; + if ((! me.isHidden())) { + _$jscoverage['ui/dialog.js'][163]++; + me.safeSetOffset(uiUtils.getClientRect(me.getDom())); + } +})); +})); + _$jscoverage['ui/dialog.js'][169]++; + if (this.holdScroll) { + _$jscoverage['ui/dialog.js'][171]++; + if ((! me.iframeUrl)) { + _$jscoverage['ui/dialog.js'][172]++; + domUtils.on(document.getElementById((me.id + "_iframe")), ((! browser.gecko)? "mousewheel": "DOMMouseScroll"), (function (e) { + _$jscoverage['ui/dialog.js'][173]++; + domUtils.preventDefault(e); +})); + } + else { + _$jscoverage['ui/dialog.js'][176]++; + me.addListener("dialogafterreset", (function () { + _$jscoverage['ui/dialog.js'][177]++; + window.setTimeout((function () { + _$jscoverage['ui/dialog.js'][178]++; + var iframeWindow = document.getElementById((me.id + "_iframe")).contentWindow; + _$jscoverage['ui/dialog.js'][180]++; + if (browser.ie) { + _$jscoverage['ui/dialog.js'][182]++; + var timer = window.setInterval((function () { + _$jscoverage['ui/dialog.js'][184]++; + if ((iframeWindow.document && iframeWindow.document.body)) { + _$jscoverage['ui/dialog.js'][185]++; + window.clearInterval(timer); + _$jscoverage['ui/dialog.js'][186]++; + timer = null; + _$jscoverage['ui/dialog.js'][187]++; + domUtils.on(iframeWindow.document.body, ((! browser.gecko)? "mousewheel": "DOMMouseScroll"), (function (e) { + _$jscoverage['ui/dialog.js'][188]++; + domUtils.preventDefault(e); +})); + } +}), 100); + } + else { + _$jscoverage['ui/dialog.js'][195]++; + domUtils.on(iframeWindow, ((! browser.gecko)? "mousewheel": "DOMMouseScroll"), (function (e) { + _$jscoverage['ui/dialog.js'][196]++; + domUtils.preventDefault(e); +})); + } +}), 1); +})); + } + } + _$jscoverage['ui/dialog.js'][205]++; + this._hide(); +}), mesureSize: (function () { + _$jscoverage['ui/dialog.js'][208]++; + var body = this.getDom("body"); + _$jscoverage['ui/dialog.js'][209]++; + var width = uiUtils.getClientRect(this.getDom("content")).width; + _$jscoverage['ui/dialog.js'][210]++; + var dialogBodyStyle = body.style; + _$jscoverage['ui/dialog.js'][211]++; + dialogBodyStyle.width = width; + _$jscoverage['ui/dialog.js'][212]++; + return uiUtils.getClientRect(body); +}), _onTitlebarMouseDown: (function (evt, el) { + _$jscoverage['ui/dialog.js'][215]++; + if (this.draggable) { + _$jscoverage['ui/dialog.js'][216]++; + var rect; + _$jscoverage['ui/dialog.js'][217]++; + var vpRect = uiUtils.getViewportRect(); + _$jscoverage['ui/dialog.js'][218]++; + var me = this; + _$jscoverage['ui/dialog.js'][219]++; + uiUtils.startDrag(evt, {ondragstart: (function () { + _$jscoverage['ui/dialog.js'][221]++; + rect = uiUtils.getClientRect(me.getDom()); + _$jscoverage['ui/dialog.js'][222]++; + me.getDom("contmask").style.visibility = "visible"; + _$jscoverage['ui/dialog.js'][223]++; + me.dragMask.show((me.getDom().style.zIndex - 1)); +}), ondragmove: (function (x, y) { + _$jscoverage['ui/dialog.js'][226]++; + var left = (rect.left + x); + _$jscoverage['ui/dialog.js'][227]++; + var top = (rect.top + y); + _$jscoverage['ui/dialog.js'][228]++; + me.safeSetOffset({left: left, top: top}); +}), ondragstop: (function () { + _$jscoverage['ui/dialog.js'][234]++; + me.getDom("contmask").style.visibility = "hidden"; + _$jscoverage['ui/dialog.js'][235]++; + domUtils.removeClasses(me.getDom(), ["edui-state-centered"]); + _$jscoverage['ui/dialog.js'][236]++; + me.dragMask.hide(); +})}); + } +}), reset: (function () { + _$jscoverage['ui/dialog.js'][242]++; + this.getDom("content").innerHTML = this.getContentHtml(); + _$jscoverage['ui/dialog.js'][243]++; + this.fireEvent("dialogafterreset"); +}), _show: (function () { + _$jscoverage['ui/dialog.js'][246]++; + if (this._hidden) { + _$jscoverage['ui/dialog.js'][247]++; + this.getDom().style.display = ""; + _$jscoverage['ui/dialog.js'][250]++; + (this.editor.container.style.zIndex && (this.getDom().style.zIndex = ((this.editor.container.style.zIndex * 1) + 10))); + _$jscoverage['ui/dialog.js'][251]++; + this._hidden = false; + _$jscoverage['ui/dialog.js'][252]++; + this.fireEvent("show"); + _$jscoverage['ui/dialog.js'][253]++; + baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = (this.getDom().style.zIndex - 4); + } +}), isHidden: (function () { + _$jscoverage['ui/dialog.js'][257]++; + return this._hidden; +}), _hide: (function () { + _$jscoverage['ui/dialog.js'][260]++; + if ((! this._hidden)) { + _$jscoverage['ui/dialog.js'][261]++; + this.getDom().style.display = "none"; + _$jscoverage['ui/dialog.js'][262]++; + this.getDom().style.zIndex = ""; + _$jscoverage['ui/dialog.js'][263]++; + this._hidden = true; + _$jscoverage['ui/dialog.js'][264]++; + this.fireEvent("hide"); + } +}), open: (function () { + _$jscoverage['ui/dialog.js'][268]++; + if (this.autoReset) { + _$jscoverage['ui/dialog.js'][270]++; + try { + _$jscoverage['ui/dialog.js'][271]++; + this.reset(); + } + catch (e) { + _$jscoverage['ui/dialog.js'][273]++; + this.render(); + _$jscoverage['ui/dialog.js'][274]++; + this.open(); + } + } + _$jscoverage['ui/dialog.js'][277]++; + this.showAtCenter(); + _$jscoverage['ui/dialog.js'][278]++; + if (this.iframeUrl) { + _$jscoverage['ui/dialog.js'][279]++; + try { + _$jscoverage['ui/dialog.js'][280]++; + this.getDom("iframe").focus(); + } + catch (ex) { + } + } +}), _onCloseButtonClick: (function (evt, el) { + _$jscoverage['ui/dialog.js'][285]++; + this.close(false); +}), close: (function (ok) { + _$jscoverage['ui/dialog.js'][288]++; + if ((this.fireEvent("close", ok) !== false)) { + _$jscoverage['ui/dialog.js'][289]++; + this._hide(); + } +})}; + _$jscoverage['ui/dialog.js'][293]++; + utils.inherits(Dialog, UIBase); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/editor.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/editor.js new file mode 100644 index 000000000..254ce39da --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/editor.js @@ -0,0 +1,1531 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/editor.js']) { + _$jscoverage['ui/editor.js'] = []; + _$jscoverage['ui/editor.js'][5] = 0; + _$jscoverage['ui/editor.js'][6] = 0; + _$jscoverage['ui/editor.js'][10] = 0; + _$jscoverage['ui/editor.js'][12] = 0; + _$jscoverage['ui/editor.js'][13] = 0; + _$jscoverage['ui/editor.js'][14] = 0; + _$jscoverage['ui/editor.js'][17] = 0; + _$jscoverage['ui/editor.js'][20] = 0; + _$jscoverage['ui/editor.js'][21] = 0; + _$jscoverage['ui/editor.js'][22] = 0; + _$jscoverage['ui/editor.js'][23] = 0; + _$jscoverage['ui/editor.js'][24] = 0; + _$jscoverage['ui/editor.js'][27] = 0; + _$jscoverage['ui/editor.js'][29] = 0; + _$jscoverage['ui/editor.js'][30] = 0; + _$jscoverage['ui/editor.js'][32] = 0; + _$jscoverage['ui/editor.js'][33] = 0; + _$jscoverage['ui/editor.js'][36] = 0; + _$jscoverage['ui/editor.js'][39] = 0; + _$jscoverage['ui/editor.js'][40] = 0; + _$jscoverage['ui/editor.js'][42] = 0; + _$jscoverage['ui/editor.js'][43] = 0; + _$jscoverage['ui/editor.js'][44] = 0; + _$jscoverage['ui/editor.js'][45] = 0; + _$jscoverage['ui/editor.js'][47] = 0; + _$jscoverage['ui/editor.js'][48] = 0; + _$jscoverage['ui/editor.js'][50] = 0; + _$jscoverage['ui/editor.js'][51] = 0; + _$jscoverage['ui/editor.js'][52] = 0; + _$jscoverage['ui/editor.js'][53] = 0; + _$jscoverage['ui/editor.js'][55] = 0; + _$jscoverage['ui/editor.js'][57] = 0; + _$jscoverage['ui/editor.js'][59] = 0; + _$jscoverage['ui/editor.js'][60] = 0; + _$jscoverage['ui/editor.js'][61] = 0; + _$jscoverage['ui/editor.js'][62] = 0; + _$jscoverage['ui/editor.js'][65] = 0; + _$jscoverage['ui/editor.js'][66] = 0; + _$jscoverage['ui/editor.js'][71] = 0; + _$jscoverage['ui/editor.js'][72] = 0; + _$jscoverage['ui/editor.js'][73] = 0; + _$jscoverage['ui/editor.js'][74] = 0; + _$jscoverage['ui/editor.js'][77] = 0; + _$jscoverage['ui/editor.js'][78] = 0; + _$jscoverage['ui/editor.js'][79] = 0; + _$jscoverage['ui/editor.js'][81] = 0; + _$jscoverage['ui/editor.js'][84] = 0; + _$jscoverage['ui/editor.js'][85] = 0; + _$jscoverage['ui/editor.js'][86] = 0; + _$jscoverage['ui/editor.js'][87] = 0; + _$jscoverage['ui/editor.js'][88] = 0; + _$jscoverage['ui/editor.js'][89] = 0; + _$jscoverage['ui/editor.js'][94] = 0; + _$jscoverage['ui/editor.js'][96] = 0; + _$jscoverage['ui/editor.js'][99] = 0; + _$jscoverage['ui/editor.js'][100] = 0; + _$jscoverage['ui/editor.js'][101] = 0; + _$jscoverage['ui/editor.js'][102] = 0; + _$jscoverage['ui/editor.js'][103] = 0; + _$jscoverage['ui/editor.js'][104] = 0; + _$jscoverage['ui/editor.js'][109] = 0; + _$jscoverage['ui/editor.js'][110] = 0; + _$jscoverage['ui/editor.js'][111] = 0; + _$jscoverage['ui/editor.js'][112] = 0; + _$jscoverage['ui/editor.js'][115] = 0; + _$jscoverage['ui/editor.js'][117] = 0; + _$jscoverage['ui/editor.js'][118] = 0; + _$jscoverage['ui/editor.js'][122] = 0; + _$jscoverage['ui/editor.js'][123] = 0; + _$jscoverage['ui/editor.js'][125] = 0; + _$jscoverage['ui/editor.js'][126] = 0; + _$jscoverage['ui/editor.js'][127] = 0; + _$jscoverage['ui/editor.js'][128] = 0; + _$jscoverage['ui/editor.js'][129] = 0; + _$jscoverage['ui/editor.js'][132] = 0; + _$jscoverage['ui/editor.js'][133] = 0; + _$jscoverage['ui/editor.js'][135] = 0; + _$jscoverage['ui/editor.js'][136] = 0; + _$jscoverage['ui/editor.js'][142] = 0; + _$jscoverage['ui/editor.js'][147] = 0; + _$jscoverage['ui/editor.js'][148] = 0; + _$jscoverage['ui/editor.js'][150] = 0; + _$jscoverage['ui/editor.js'][151] = 0; + _$jscoverage['ui/editor.js'][152] = 0; + _$jscoverage['ui/editor.js'][153] = 0; + _$jscoverage['ui/editor.js'][155] = 0; + _$jscoverage['ui/editor.js'][159] = 0; + _$jscoverage['ui/editor.js'][160] = 0; + _$jscoverage['ui/editor.js'][161] = 0; + _$jscoverage['ui/editor.js'][163] = 0; + _$jscoverage['ui/editor.js'][164] = 0; + _$jscoverage['ui/editor.js'][168] = 0; + _$jscoverage['ui/editor.js'][173] = 0; + _$jscoverage['ui/editor.js'][174] = 0; + _$jscoverage['ui/editor.js'][177] = 0; + _$jscoverage['ui/editor.js'][178] = 0; + _$jscoverage['ui/editor.js'][182] = 0; + _$jscoverage['ui/editor.js'][183] = 0; + _$jscoverage['ui/editor.js'][187] = 0; + _$jscoverage['ui/editor.js'][188] = 0; + _$jscoverage['ui/editor.js'][189] = 0; + _$jscoverage['ui/editor.js'][191] = 0; + _$jscoverage['ui/editor.js'][192] = 0; + _$jscoverage['ui/editor.js'][194] = 0; + _$jscoverage['ui/editor.js'][195] = 0; + _$jscoverage['ui/editor.js'][197] = 0; + _$jscoverage['ui/editor.js'][198] = 0; + _$jscoverage['ui/editor.js'][200] = 0; + _$jscoverage['ui/editor.js'][201] = 0; + _$jscoverage['ui/editor.js'][202] = 0; + _$jscoverage['ui/editor.js'][203] = 0; + _$jscoverage['ui/editor.js'][206] = 0; + _$jscoverage['ui/editor.js'][207] = 0; + _$jscoverage['ui/editor.js'][208] = 0; + _$jscoverage['ui/editor.js'][211] = 0; + _$jscoverage['ui/editor.js'][212] = 0; + _$jscoverage['ui/editor.js'][215] = 0; + _$jscoverage['ui/editor.js'][216] = 0; + _$jscoverage['ui/editor.js'][217] = 0; + _$jscoverage['ui/editor.js'][220] = 0; + _$jscoverage['ui/editor.js'][223] = 0; + _$jscoverage['ui/editor.js'][224] = 0; + _$jscoverage['ui/editor.js'][225] = 0; + _$jscoverage['ui/editor.js'][226] = 0; + _$jscoverage['ui/editor.js'][227] = 0; + _$jscoverage['ui/editor.js'][228] = 0; + _$jscoverage['ui/editor.js'][229] = 0; + _$jscoverage['ui/editor.js'][232] = 0; + _$jscoverage['ui/editor.js'][233] = 0; + _$jscoverage['ui/editor.js'][234] = 0; + _$jscoverage['ui/editor.js'][235] = 0; + _$jscoverage['ui/editor.js'][237] = 0; + _$jscoverage['ui/editor.js'][241] = 0; + _$jscoverage['ui/editor.js'][242] = 0; + _$jscoverage['ui/editor.js'][243] = 0; + _$jscoverage['ui/editor.js'][246] = 0; + _$jscoverage['ui/editor.js'][247] = 0; + _$jscoverage['ui/editor.js'][248] = 0; + _$jscoverage['ui/editor.js'][249] = 0; + _$jscoverage['ui/editor.js'][251] = 0; + _$jscoverage['ui/editor.js'][252] = 0; + _$jscoverage['ui/editor.js'][254] = 0; + _$jscoverage['ui/editor.js'][255] = 0; + _$jscoverage['ui/editor.js'][257] = 0; + _$jscoverage['ui/editor.js'][258] = 0; + _$jscoverage['ui/editor.js'][260] = 0; + _$jscoverage['ui/editor.js'][261] = 0; + _$jscoverage['ui/editor.js'][263] = 0; + _$jscoverage['ui/editor.js'][264] = 0; + _$jscoverage['ui/editor.js'][265] = 0; + _$jscoverage['ui/editor.js'][269] = 0; + _$jscoverage['ui/editor.js'][271] = 0; + _$jscoverage['ui/editor.js'][272] = 0; + _$jscoverage['ui/editor.js'][274] = 0; + _$jscoverage['ui/editor.js'][275] = 0; + _$jscoverage['ui/editor.js'][277] = 0; + _$jscoverage['ui/editor.js'][284] = 0; + _$jscoverage['ui/editor.js'][287] = 0; + _$jscoverage['ui/editor.js'][288] = 0; + _$jscoverage['ui/editor.js'][289] = 0; + _$jscoverage['ui/editor.js'][290] = 0; + _$jscoverage['ui/editor.js'][291] = 0; + _$jscoverage['ui/editor.js'][292] = 0; + _$jscoverage['ui/editor.js'][293] = 0; + _$jscoverage['ui/editor.js'][295] = 0; + _$jscoverage['ui/editor.js'][296] = 0; + _$jscoverage['ui/editor.js'][298] = 0; + _$jscoverage['ui/editor.js'][302] = 0; + _$jscoverage['ui/editor.js'][306] = 0; + _$jscoverage['ui/editor.js'][307] = 0; + _$jscoverage['ui/editor.js'][308] = 0; + _$jscoverage['ui/editor.js'][309] = 0; + _$jscoverage['ui/editor.js'][311] = 0; + _$jscoverage['ui/editor.js'][318] = 0; + _$jscoverage['ui/editor.js'][319] = 0; + _$jscoverage['ui/editor.js'][320] = 0; + _$jscoverage['ui/editor.js'][321] = 0; + _$jscoverage['ui/editor.js'][322] = 0; + _$jscoverage['ui/editor.js'][323] = 0; + _$jscoverage['ui/editor.js'][324] = 0; + _$jscoverage['ui/editor.js'][325] = 0; + _$jscoverage['ui/editor.js'][326] = 0; + _$jscoverage['ui/editor.js'][327] = 0; + _$jscoverage['ui/editor.js'][328] = 0; + _$jscoverage['ui/editor.js'][329] = 0; + _$jscoverage['ui/editor.js'][330] = 0; + _$jscoverage['ui/editor.js'][332] = 0; + _$jscoverage['ui/editor.js'][333] = 0; + _$jscoverage['ui/editor.js'][335] = 0; + _$jscoverage['ui/editor.js'][336] = 0; + _$jscoverage['ui/editor.js'][340] = 0; + _$jscoverage['ui/editor.js'][341] = 0; + _$jscoverage['ui/editor.js'][342] = 0; + _$jscoverage['ui/editor.js'][344] = 0; + _$jscoverage['ui/editor.js'][347] = 0; + _$jscoverage['ui/editor.js'][352] = 0; + _$jscoverage['ui/editor.js'][354] = 0; + _$jscoverage['ui/editor.js'][356] = 0; + _$jscoverage['ui/editor.js'][359] = 0; + _$jscoverage['ui/editor.js'][361] = 0; + _$jscoverage['ui/editor.js'][364] = 0; + _$jscoverage['ui/editor.js'][388] = 0; + _$jscoverage['ui/editor.js'][389] = 0; + _$jscoverage['ui/editor.js'][392] = 0; + _$jscoverage['ui/editor.js'][393] = 0; + _$jscoverage['ui/editor.js'][394] = 0; + _$jscoverage['ui/editor.js'][396] = 0; + _$jscoverage['ui/editor.js'][400] = 0; + _$jscoverage['ui/editor.js'][402] = 0; + _$jscoverage['ui/editor.js'][403] = 0; + _$jscoverage['ui/editor.js'][404] = 0; + _$jscoverage['ui/editor.js'][405] = 0; + _$jscoverage['ui/editor.js'][406] = 0; + _$jscoverage['ui/editor.js'][408] = 0; + _$jscoverage['ui/editor.js'][409] = 0; + _$jscoverage['ui/editor.js'][410] = 0; + _$jscoverage['ui/editor.js'][411] = 0; + _$jscoverage['ui/editor.js'][412] = 0; + _$jscoverage['ui/editor.js'][413] = 0; + _$jscoverage['ui/editor.js'][415] = 0; + _$jscoverage['ui/editor.js'][416] = 0; + _$jscoverage['ui/editor.js'][417] = 0; + _$jscoverage['ui/editor.js'][418] = 0; + _$jscoverage['ui/editor.js'][420] = 0; + _$jscoverage['ui/editor.js'][421] = 0; + _$jscoverage['ui/editor.js'][423] = 0; + _$jscoverage['ui/editor.js'][424] = 0; + _$jscoverage['ui/editor.js'][427] = 0; + _$jscoverage['ui/editor.js'][428] = 0; + _$jscoverage['ui/editor.js'][429] = 0; + _$jscoverage['ui/editor.js'][430] = 0; + _$jscoverage['ui/editor.js'][431] = 0; + _$jscoverage['ui/editor.js'][432] = 0; + _$jscoverage['ui/editor.js'][434] = 0; + _$jscoverage['ui/editor.js'][435] = 0; + _$jscoverage['ui/editor.js'][436] = 0; + _$jscoverage['ui/editor.js'][438] = 0; + _$jscoverage['ui/editor.js'][439] = 0; + _$jscoverage['ui/editor.js'][440] = 0; + _$jscoverage['ui/editor.js'][441] = 0; + _$jscoverage['ui/editor.js'][442] = 0; + _$jscoverage['ui/editor.js'][445] = 0; + _$jscoverage['ui/editor.js'][446] = 0; + _$jscoverage['ui/editor.js'][447] = 0; + _$jscoverage['ui/editor.js'][448] = 0; + _$jscoverage['ui/editor.js'][450] = 0; + _$jscoverage['ui/editor.js'][451] = 0; + _$jscoverage['ui/editor.js'][452] = 0; + _$jscoverage['ui/editor.js'][453] = 0; + _$jscoverage['ui/editor.js'][454] = 0; + _$jscoverage['ui/editor.js'][455] = 0; + _$jscoverage['ui/editor.js'][456] = 0; + _$jscoverage['ui/editor.js'][457] = 0; + _$jscoverage['ui/editor.js'][458] = 0; + _$jscoverage['ui/editor.js'][459] = 0; + _$jscoverage['ui/editor.js'][460] = 0; + _$jscoverage['ui/editor.js'][461] = 0; + _$jscoverage['ui/editor.js'][466] = 0; + _$jscoverage['ui/editor.js'][467] = 0; + _$jscoverage['ui/editor.js'][468] = 0; + _$jscoverage['ui/editor.js'][474] = 0; + _$jscoverage['ui/editor.js'][475] = 0; + _$jscoverage['ui/editor.js'][476] = 0; + _$jscoverage['ui/editor.js'][477] = 0; + _$jscoverage['ui/editor.js'][478] = 0; + _$jscoverage['ui/editor.js'][480] = 0; + _$jscoverage['ui/editor.js'][481] = 0; + _$jscoverage['ui/editor.js'][482] = 0; + _$jscoverage['ui/editor.js'][491] = 0; + _$jscoverage['ui/editor.js'][492] = 0; + _$jscoverage['ui/editor.js'][494] = 0; + _$jscoverage['ui/editor.js'][495] = 0; + _$jscoverage['ui/editor.js'][496] = 0; + _$jscoverage['ui/editor.js'][498] = 0; + _$jscoverage['ui/editor.js'][501] = 0; + _$jscoverage['ui/editor.js'][505] = 0; + _$jscoverage['ui/editor.js'][506] = 0; + _$jscoverage['ui/editor.js'][507] = 0; + _$jscoverage['ui/editor.js'][508] = 0; + _$jscoverage['ui/editor.js'][512] = 0; + _$jscoverage['ui/editor.js'][513] = 0; + _$jscoverage['ui/editor.js'][514] = 0; + _$jscoverage['ui/editor.js'][515] = 0; + _$jscoverage['ui/editor.js'][518] = 0; + _$jscoverage['ui/editor.js'][527] = 0; + _$jscoverage['ui/editor.js'][536] = 0; + _$jscoverage['ui/editor.js'][537] = 0; + _$jscoverage['ui/editor.js'][539] = 0; + _$jscoverage['ui/editor.js'][540] = 0; + _$jscoverage['ui/editor.js'][543] = 0; + _$jscoverage['ui/editor.js'][546] = 0; + _$jscoverage['ui/editor.js'][547] = 0; + _$jscoverage['ui/editor.js'][548] = 0; + _$jscoverage['ui/editor.js'][551] = 0; + _$jscoverage['ui/editor.js'][553] = 0; + _$jscoverage['ui/editor.js'][554] = 0; + _$jscoverage['ui/editor.js'][555] = 0; + _$jscoverage['ui/editor.js'][558] = 0; + _$jscoverage['ui/editor.js'][559] = 0; + _$jscoverage['ui/editor.js'][560] = 0; + _$jscoverage['ui/editor.js'][561] = 0; + _$jscoverage['ui/editor.js'][562] = 0; + _$jscoverage['ui/editor.js'][563] = 0; + _$jscoverage['ui/editor.js'][567] = 0; + _$jscoverage['ui/editor.js'][568] = 0; + _$jscoverage['ui/editor.js'][569] = 0; + _$jscoverage['ui/editor.js'][570] = 0; + _$jscoverage['ui/editor.js'][571] = 0; + _$jscoverage['ui/editor.js'][572] = 0; + _$jscoverage['ui/editor.js'][573] = 0; + _$jscoverage['ui/editor.js'][575] = 0; + _$jscoverage['ui/editor.js'][576] = 0; + _$jscoverage['ui/editor.js'][577] = 0; + _$jscoverage['ui/editor.js'][579] = 0; + _$jscoverage['ui/editor.js'][580] = 0; + _$jscoverage['ui/editor.js'][581] = 0; + _$jscoverage['ui/editor.js'][585] = 0; + _$jscoverage['ui/editor.js'][586] = 0; + _$jscoverage['ui/editor.js'][587] = 0; + _$jscoverage['ui/editor.js'][588] = 0; + _$jscoverage['ui/editor.js'][589] = 0; + _$jscoverage['ui/editor.js'][591] = 0; + _$jscoverage['ui/editor.js'][593] = 0; + _$jscoverage['ui/editor.js'][594] = 0; + _$jscoverage['ui/editor.js'][596] = 0; + _$jscoverage['ui/editor.js'][597] = 0; + _$jscoverage['ui/editor.js'][598] = 0; + _$jscoverage['ui/editor.js'][599] = 0; + _$jscoverage['ui/editor.js'][602] = 0; + _$jscoverage['ui/editor.js'][603] = 0; + _$jscoverage['ui/editor.js'][604] = 0; + _$jscoverage['ui/editor.js'][606] = 0; + _$jscoverage['ui/editor.js'][609] = 0; + _$jscoverage['ui/editor.js'][611] = 0; + _$jscoverage['ui/editor.js'][612] = 0; + _$jscoverage['ui/editor.js'][613] = 0; + _$jscoverage['ui/editor.js'][614] = 0; + _$jscoverage['ui/editor.js'][616] = 0; + _$jscoverage['ui/editor.js'][617] = 0; + _$jscoverage['ui/editor.js'][618] = 0; + _$jscoverage['ui/editor.js'][619] = 0; + _$jscoverage['ui/editor.js'][623] = 0; + _$jscoverage['ui/editor.js'][626] = 0; + _$jscoverage['ui/editor.js'][627] = 0; + _$jscoverage['ui/editor.js'][628] = 0; + _$jscoverage['ui/editor.js'][630] = 0; + _$jscoverage['ui/editor.js'][631] = 0; + _$jscoverage['ui/editor.js'][634] = 0; + _$jscoverage['ui/editor.js'][635] = 0; + _$jscoverage['ui/editor.js'][636] = 0; + _$jscoverage['ui/editor.js'][639] = 0; + _$jscoverage['ui/editor.js'][641] = 0; + _$jscoverage['ui/editor.js'][642] = 0; + _$jscoverage['ui/editor.js'][643] = 0; + _$jscoverage['ui/editor.js'][647] = 0; + _$jscoverage['ui/editor.js'][648] = 0; + _$jscoverage['ui/editor.js'][650] = 0; + _$jscoverage['ui/editor.js'][651] = 0; + _$jscoverage['ui/editor.js'][652] = 0; + _$jscoverage['ui/editor.js'][656] = 0; + _$jscoverage['ui/editor.js'][659] = 0; + _$jscoverage['ui/editor.js'][662] = 0; + _$jscoverage['ui/editor.js'][663] = 0; + _$jscoverage['ui/editor.js'][664] = 0; + _$jscoverage['ui/editor.js'][666] = 0; + _$jscoverage['ui/editor.js'][670] = 0; + _$jscoverage['ui/editor.js'][673] = 0; + _$jscoverage['ui/editor.js'][676] = 0; + _$jscoverage['ui/editor.js'][677] = 0; + _$jscoverage['ui/editor.js'][678] = 0; + _$jscoverage['ui/editor.js'][679] = 0; + _$jscoverage['ui/editor.js'][686] = 0; + _$jscoverage['ui/editor.js'][687] = 0; + _$jscoverage['ui/editor.js'][688] = 0; + _$jscoverage['ui/editor.js'][689] = 0; + _$jscoverage['ui/editor.js'][690] = 0; + _$jscoverage['ui/editor.js'][692] = 0; + _$jscoverage['ui/editor.js'][693] = 0; + _$jscoverage['ui/editor.js'][694] = 0; + _$jscoverage['ui/editor.js'][695] = 0; + _$jscoverage['ui/editor.js'][698] = 0; + _$jscoverage['ui/editor.js'][699] = 0; + _$jscoverage['ui/editor.js'][700] = 0; + _$jscoverage['ui/editor.js'][701] = 0; + _$jscoverage['ui/editor.js'][703] = 0; + _$jscoverage['ui/editor.js'][704] = 0; + _$jscoverage['ui/editor.js'][705] = 0; + _$jscoverage['ui/editor.js'][706] = 0; + _$jscoverage['ui/editor.js'][707] = 0; + _$jscoverage['ui/editor.js'][708] = 0; + _$jscoverage['ui/editor.js'][712] = 0; + _$jscoverage['ui/editor.js'][713] = 0; + _$jscoverage['ui/editor.js'][714] = 0; + _$jscoverage['ui/editor.js'][715] = 0; + _$jscoverage['ui/editor.js'][716] = 0; + _$jscoverage['ui/editor.js'][719] = 0; + _$jscoverage['ui/editor.js'][720] = 0; + _$jscoverage['ui/editor.js'][722] = 0; + _$jscoverage['ui/editor.js'][723] = 0; + _$jscoverage['ui/editor.js'][727] = 0; + _$jscoverage['ui/editor.js'][728] = 0; + _$jscoverage['ui/editor.js'][729] = 0; + _$jscoverage['ui/editor.js'][731] = 0; + _$jscoverage['ui/editor.js'][732] = 0; + _$jscoverage['ui/editor.js'][733] = 0; + _$jscoverage['ui/editor.js'][734] = 0; + _$jscoverage['ui/editor.js'][735] = 0; + _$jscoverage['ui/editor.js'][736] = 0; + _$jscoverage['ui/editor.js'][738] = 0; + _$jscoverage['ui/editor.js'][739] = 0; + _$jscoverage['ui/editor.js'][741] = 0; + _$jscoverage['ui/editor.js'][743] = 0; + _$jscoverage['ui/editor.js'][744] = 0; + _$jscoverage['ui/editor.js'][746] = 0; + _$jscoverage['ui/editor.js'][748] = 0; + _$jscoverage['ui/editor.js'][749] = 0; + _$jscoverage['ui/editor.js'][753] = 0; + _$jscoverage['ui/editor.js'][754] = 0; + _$jscoverage['ui/editor.js'][756] = 0; + _$jscoverage['ui/editor.js'][757] = 0; + _$jscoverage['ui/editor.js'][758] = 0; + _$jscoverage['ui/editor.js'][763] = 0; + _$jscoverage['ui/editor.js'][788] = 0; + _$jscoverage['ui/editor.js'][789] = 0; + _$jscoverage['ui/editor.js'][790] = 0; + _$jscoverage['ui/editor.js'][791] = 0; + _$jscoverage['ui/editor.js'][792] = 0; + _$jscoverage['ui/editor.js'][794] = 0; + _$jscoverage['ui/editor.js'][798] = 0; + _$jscoverage['ui/editor.js'][799] = 0; + _$jscoverage['ui/editor.js'][800] = 0; + _$jscoverage['ui/editor.js'][801] = 0; + _$jscoverage['ui/editor.js'][802] = 0; +} +_$jscoverage['ui/editor.js'].source = ["///import core","///commands 全屏","///commandsName FullScreen","///commandsTitle 全屏","(function () {"," var utils = baidu.editor.utils,"," uiUtils = baidu.editor.ui.uiUtils,"," UIBase = baidu.editor.ui.UIBase,"," domUtils = baidu.editor.dom.domUtils;"," var nodeStack = [];",""," function EditorUI(options) {"," this.initOptions(options);"," this.initEditorUI();"," }",""," EditorUI.prototype = {"," uiName:'editor',"," initEditorUI:function () {"," this.editor.ui = this;"," this._dialogs = {};"," this.initUIBase();"," this._initToolbars();"," var editor = this.editor,"," me = this;",""," editor.addListener('ready', function () {"," //提供getDialog方法"," editor.getDialog = function (name) {"," return editor.ui._dialogs[name + \"Dialog\"];"," };"," domUtils.on(editor.window, 'scroll', function (evt) {"," baidu.editor.ui.Popup.postHide(evt);"," });"," //提供编辑器实时宽高(全屏时宽高不变化)"," editor.ui._actualFrameWidth = editor.options.initialFrameWidth;",""," //display bottom-bar label based on config"," if (editor.options.elementPathEnabled) {"," editor.ui.getDom('elementpath').innerHTML = '<div class=\"edui-editor-breadcrumb\">' + editor.getLang(\"elementPathTip\") + ':</div>';"," }"," if (editor.options.wordCount) {"," function countFn() {"," setCount(editor,me);"," domUtils.un(editor.document, \"click\", arguments.callee);"," }"," domUtils.on(editor.document, \"click\", countFn);"," editor.ui.getDom('wordcount').innerHTML = editor.getLang(\"wordCountTip\");"," }"," editor.ui._scale();"," if (editor.options.scaleEnabled) {"," if (editor.autoHeightEnabled) {"," editor.disableAutoHeight();"," }"," me.enableScale();"," } else {"," me.disableScale();"," }"," if (!editor.options.elementPathEnabled && !editor.options.wordCount && !editor.options.scaleEnabled) {"," editor.ui.getDom('elementpath').style.display = \"none\";"," editor.ui.getDom('wordcount').style.display = \"none\";"," editor.ui.getDom('scale').style.display = \"none\";"," }",""," if (!editor.selection.isFocus())return;"," editor.fireEvent('selectionchange', false, true);","",""," });",""," editor.addListener('mousedown', function (t, evt) {"," var el = evt.target || evt.srcElement;"," baidu.editor.ui.Popup.postHide(evt, el);"," baidu.editor.ui.ShortCutMenu.postHide(evt);",""," });"," editor.addListener(\"delcells\", function () {"," if (UE.ui['edittip']) {"," new UE.ui['edittip'](editor);"," }"," editor.getDialog('edittip').open();"," });",""," var pastePop, isPaste = false, timer;"," editor.addListener(\"afterpaste\", function () {"," if(editor.queryCommandState('pasteplain'))"," return;"," if(baidu.editor.ui.PastePicker){"," pastePop = new baidu.editor.ui.Popup({"," content:new baidu.editor.ui.PastePicker({editor:editor}),"," editor:editor,"," className:'edui-wordpastepop'"," });"," pastePop.render();"," }"," isPaste = true;"," });",""," editor.addListener(\"afterinserthtml\", function () {"," clearTimeout(timer);"," timer = setTimeout(function () {"," if (pastePop && (isPaste || editor.ui._isTransfer)) {"," if(pastePop.isHidden()){"," var span = domUtils.createElement(editor.document, 'span', {"," 'style':\"line-height:0px;\","," 'innerHTML':'\\ufeff'"," }),"," range = editor.selection.getRange();"," range.insertNode(span);"," var tmp= getDomNode(span, 'firstChild', 'previousSibling');"," pastePop.showAnchor(tmp.nodeType == 3 ? tmp.parentNode : tmp);"," domUtils.remove(span);",""," }else{"," pastePop.show();"," }"," delete editor.ui._isTransfer;"," isPaste = false;"," }"," }, 200)"," });"," editor.addListener('contextmenu', function (t, evt) {"," baidu.editor.ui.Popup.postHide(evt);"," });"," editor.addListener('keydown', function (t, evt) {"," if (pastePop) pastePop.dispose(evt);"," var keyCode = evt.keyCode || evt.which;"," if(evt.altKey&&keyCode==90){"," UE.ui.buttons['fullscreen'].onclick();"," }"," });"," editor.addListener('wordcount', function (type) {"," setCount(this,me);"," });"," function setCount(editor,ui) {"," editor.setOpt({"," wordCount:true,"," maximumWords:10000,"," wordCountMsg:editor.options.wordCountMsg || editor.getLang(\"wordCountMsg\"),"," wordOverFlowMsg:editor.options.wordOverFlowMsg || editor.getLang(\"wordOverFlowMsg\")"," });"," var opt = editor.options,"," max = opt.maximumWords,"," msg = opt.wordCountMsg ,"," errMsg = opt.wordOverFlowMsg,"," countDom = ui.getDom('wordcount');"," if (!opt.wordCount) {"," return;"," }"," var count = editor.getContentLength(true);"," if (count > max) {"," countDom.innerHTML = errMsg;"," editor.fireEvent(\"wordcountoverflow\");"," } else {"," countDom.innerHTML = msg.replace(\"{#leave}\", max - count).replace(\"{#count}\", count);"," }"," }",""," editor.addListener('selectionchange', function () {"," if (editor.options.elementPathEnabled) {"," me[(editor.queryCommandState('elementpath') == -1 ? 'dis' : 'en') + 'ableElementPath']()"," }"," if (editor.options.scaleEnabled) {"," me[(editor.queryCommandState('scale') == -1 ? 'dis' : 'en') + 'ableScale']();",""," }"," });"," var popup = new baidu.editor.ui.Popup({"," editor:editor,"," content:'',"," className:'edui-bubble',"," _onEditButtonClick:function () {"," this.hide();"," editor.ui._dialogs.linkDialog.open();"," },"," _onImgEditButtonClick:function (name) {"," this.hide();"," editor.ui._dialogs[name] && editor.ui._dialogs[name].open();",""," },"," _onImgSetFloat:function (value) {"," this.hide();"," editor.execCommand(\"imagefloat\", value);",""," },"," _setIframeAlign:function (value) {"," var frame = popup.anchorEl;"," var newFrame = frame.cloneNode(true);"," switch (value) {"," case -2:"," newFrame.setAttribute(\"align\", \"\");"," break;"," case -1:"," newFrame.setAttribute(\"align\", \"left\");"," break;"," case 1:"," newFrame.setAttribute(\"align\", \"right\");"," break;"," }"," frame.parentNode.insertBefore(newFrame, frame);"," domUtils.remove(frame);"," popup.anchorEl = newFrame;"," popup.showAnchor(popup.anchorEl);"," },"," _updateIframe:function () {"," editor._iframe = popup.anchorEl;"," editor.ui._dialogs.insertframeDialog.open();"," popup.hide();"," },"," _onRemoveButtonClick:function (cmdName) {"," editor.execCommand(cmdName);"," this.hide();"," },"," queryAutoHide:function (el) {"," if (el && el.ownerDocument == editor.document) {"," if (el.tagName.toLowerCase() == 'img' || domUtils.findParentByTagName(el, 'a', true)) {"," return el !== popup.anchorEl;"," }"," }"," return baidu.editor.ui.Popup.prototype.queryAutoHide.call(this, el);"," }"," });"," popup.render();"," if (editor.options.imagePopup) {"," editor.addListener('mouseover', function (t, evt) {"," evt = evt || window.event;"," var el = evt.target || evt.srcElement;"," if (editor.ui._dialogs.insertframeDialog && /iframe/ig.test(el.tagName)) {"," var html = popup.formatHtml("," '<nobr>' + editor.getLang(\"property\") + ': <span onclick=$$._setIframeAlign(-2) class=\"edui-clickable\">' + editor.getLang(\"default\") + '</span>&nbsp;&nbsp;<span onclick=$$._setIframeAlign(-1) class=\"edui-clickable\">' + editor.getLang(\"justifyleft\") + '</span>&nbsp;&nbsp;<span onclick=$$._setIframeAlign(1) class=\"edui-clickable\">' + editor.getLang(\"justifyright\") + '</span>&nbsp;&nbsp;' +"," ' <span onclick=\"$$._updateIframe( this);\" class=\"edui-clickable\">' + editor.getLang(\"modify\") + '</span></nobr>');"," if (html) {"," popup.getDom('content').innerHTML = html;"," popup.anchorEl = el;"," popup.showAnchor(popup.anchorEl);"," } else {"," popup.hide();"," }"," }"," });"," editor.addListener('selectionchange', function (t, causeByUi) {"," if (!causeByUi) return;"," var html = '', str = \"\","," img = editor.selection.getRange().getClosedNode(),"," dialogs = editor.ui._dialogs;"," if (img && img.tagName == 'IMG') {"," var dialogName = 'insertimageDialog';"," if (img.className.indexOf(\"edui-faked-video\") != -1) {"," dialogName = \"insertvideoDialog\""," }"," if (img.className.indexOf(\"edui-faked-webapp\") != -1) {"," dialogName = \"webappDialog\""," }"," if (img.src.indexOf(\"http://api.map.baidu.com\") != -1) {"," dialogName = \"mapDialog\""," }"," if (img.className.indexOf(\"edui-faked-music\") != -1) {"," dialogName = \"musicDialog\""," }"," if (img.src.indexOf(\"http://maps.google.com/maps/api/staticmap\") != -1) {"," dialogName = \"gmapDialog\""," }"," if (img.getAttribute(\"anchorname\")) {"," dialogName = \"anchorDialog\";"," html = popup.formatHtml("," '<nobr>' + editor.getLang(\"property\") + ': <span onclick=$$._onImgEditButtonClick(\"anchorDialog\") class=\"edui-clickable\">' + editor.getLang(\"modify\") + '</span>&nbsp;&nbsp;' +"," '<span onclick=$$._onRemoveButtonClick(\\'anchor\\') class=\"edui-clickable\">' + editor.getLang(\"delete\") + '</span></nobr>');"," }"," if (img.getAttribute(\"word_img\")) {"," //todo 放到dialog去做查询"," editor.word_img = [img.getAttribute(\"word_img\")];"," dialogName = \"wordimageDialog\""," }"," if (!dialogs[dialogName]) {"," return;"," }"," str = '<nobr>' + editor.getLang(\"property\") + ': '+"," '<span onclick=$$._onImgSetFloat(\"none\") class=\"edui-clickable\">' + editor.getLang(\"default\") + '</span>&nbsp;&nbsp;' +"," '<span onclick=$$._onImgSetFloat(\"left\") class=\"edui-clickable\">' + editor.getLang(\"justifyleft\") + '</span>&nbsp;&nbsp;' +"," '<span onclick=$$._onImgSetFloat(\"right\") class=\"edui-clickable\">' + editor.getLang(\"justifyright\") + '</span>&nbsp;&nbsp;' +"," '<span onclick=$$._onImgSetFloat(\"center\") class=\"edui-clickable\">' + editor.getLang(\"justifycenter\") + '</span>&nbsp;&nbsp;'+"," '<span onclick=\"$$._onImgEditButtonClick(\\'' + dialogName + '\\');\" class=\"edui-clickable\">' + editor.getLang(\"modify\") + '</span></nobr>';",""," !html && (html = popup.formatHtml(str))",""," }"," if (editor.ui._dialogs.linkDialog) {"," var link = editor.queryCommandValue('link');"," var url;"," if (link && (url = (link.getAttribute('_href') || link.getAttribute('href', 2)))) {"," var txt = url;"," if (url.length > 30) {"," txt = url.substring(0, 20) + \"...\";"," }"," if (html) {"," html += '<div style=\"height:5px;\"></div>'"," }"," html += popup.formatHtml("," '<nobr>' + editor.getLang(\"anthorMsg\") + ': <a target=\"_blank\" href=\"' + url + '\" title=\"' + url + '\" >' + txt + '</a>' +"," ' <span class=\"edui-clickable\" onclick=\"$$._onEditButtonClick();\">' + editor.getLang(\"modify\") + '</span>' +"," ' <span class=\"edui-clickable\" onclick=\"$$._onRemoveButtonClick(\\'unlink\\');\"> ' + editor.getLang(\"clear\") + '</span></nobr>');"," popup.showAnchor(link);"," }"," }",""," if (html) {"," popup.getDom('content').innerHTML = html;"," popup.anchorEl = img || link;"," popup.showAnchor(popup.anchorEl);"," } else {"," popup.hide();"," }"," });"," }",""," },"," _initToolbars:function () {"," var editor = this.editor;"," var toolbars = this.toolbars || [];"," var toolbarUis = [];"," for (var i = 0; i < toolbars.length; i++) {"," var toolbar = toolbars[i];"," var toolbarUi = new baidu.editor.ui.Toolbar({theme:editor.options.theme});"," for (var j = 0; j < toolbar.length; j++) {"," var toolbarItem = toolbar[j];"," var toolbarItemUi = null;"," if (typeof toolbarItem == 'string') {"," toolbarItem = toolbarItem.toLowerCase();"," if (toolbarItem == '|') {"," toolbarItem = 'Separator';"," }"," if(toolbarItem == '||'){"," toolbarItem = 'Breakline';"," }"," if (baidu.editor.ui[toolbarItem]) {"," toolbarItemUi = new baidu.editor.ui[toolbarItem](editor);"," }",""," //fullscreen这里单独处理一下,放到首行去"," if (toolbarItem == 'fullscreen') {"," if (toolbarUis && toolbarUis[0]) {"," toolbarUis[0].items.splice(0, 0, toolbarItemUi);"," } else {"," toolbarItemUi && toolbarUi.items.splice(0, 0, toolbarItemUi);"," }",""," continue;","",""," }"," } else {"," toolbarItemUi = toolbarItem;"," }"," if (toolbarItemUi && toolbarItemUi.id) {",""," toolbarUi.add(toolbarItemUi);"," }"," }"," toolbarUis[i] = toolbarUi;"," }"," this.toolbars = toolbarUis;"," },"," getHtmlTpl:function () {"," return '<div id=\"##\" class=\"%%\">' +"," '<div id=\"##_toolbarbox\" class=\"%%-toolbarbox\">' +"," (this.toolbars.length ?"," '<div id=\"##_toolbarboxouter\" class=\"%%-toolbarboxouter\"><div class=\"%%-toolbarboxinner\">' +"," this.renderToolbarBoxHtml() +"," '</div></div>' : '') +"," '<div id=\"##_toolbarmsg\" class=\"%%-toolbarmsg\" style=\"display:none;\">' +"," '<div id = \"##_upload_dialog\" class=\"%%-toolbarmsg-upload\" onclick=\"$$.showWordImageDialog();\">' + this.editor.getLang(\"clickToUpload\") + '</div>' +"," '<div class=\"%%-toolbarmsg-close\" onclick=\"$$.hideToolbarMsg();\">x</div>' +"," '<div id=\"##_toolbarmsg_label\" class=\"%%-toolbarmsg-label\"></div>' +"," '<div style=\"height:0;overflow:hidden;clear:both;\"></div>' +"," '</div>' +"," '</div>' +"," '<div id=\"##_iframeholder\" class=\"%%-iframeholder\"></div>' +"," //modify wdcount by matao"," '<div id=\"##_bottombar\" class=\"%%-bottomContainer\"><table><tr>' +"," '<td id=\"##_elementpath\" class=\"%%-bottombar\"></td>' +"," '<td id=\"##_wordcount\" class=\"%%-wordcount\"></td>' +"," '<td id=\"##_scale\" class=\"%%-scale\"><div class=\"%%-icon\"></div></td>' +"," '</tr></table></div>' +"," '<div id=\"##_scalelayer\"></div>' +"," '</div>';"," },"," showWordImageDialog:function () {"," this.editor.execCommand(\"wordimage\", \"word_img\");"," this._dialogs['wordimageDialog'].open();"," },"," renderToolbarBoxHtml:function () {"," var buff = [];"," for (var i = 0; i < this.toolbars.length; i++) {"," buff.push(this.toolbars[i].renderHtml());"," }"," return buff.join('');"," },"," setFullScreen:function (fullscreen) {",""," var editor = this.editor,"," container = editor.container.parentNode.parentNode;"," if (this._fullscreen != fullscreen) {"," this._fullscreen = fullscreen;"," this.editor.fireEvent('beforefullscreenchange', fullscreen);"," if (baidu.editor.browser.gecko) {"," var bk = editor.selection.getRange().createBookmark();"," }"," if (fullscreen) {"," while (container.tagName != \"BODY\") {"," var position = baidu.editor.dom.domUtils.getComputedStyle(container, \"position\");"," nodeStack.push(position);"," container.style.position = \"static\";"," container = container.parentNode;"," }"," this._bakHtmlOverflow = document.documentElement.style.overflow;"," this._bakBodyOverflow = document.body.style.overflow;"," this._bakAutoHeight = this.editor.autoHeightEnabled;"," this._bakScrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);",""," this._bakEditorContaninerWidth = editor.iframe.parentNode.offsetWidth;"," if (this._bakAutoHeight) {"," //当全屏时不能执行自动长高"," editor.autoHeightEnabled = false;"," this.editor.disableAutoHeight();"," }",""," document.documentElement.style.overflow = 'hidden';"," document.body.style.overflow = 'hidden';"," this._bakCssText = this.getDom().style.cssText;"," this._bakCssText1 = this.getDom('iframeholder').style.cssText;"," editor.iframe.parentNode.style.width = '';"," this._updateFullScreen();"," } else {"," while (container.tagName != \"BODY\") {"," container.style.position = nodeStack.shift();"," container = container.parentNode;"," }"," this.getDom().style.cssText = this._bakCssText;"," this.getDom('iframeholder').style.cssText = this._bakCssText1;"," if (this._bakAutoHeight) {"," editor.autoHeightEnabled = true;"," this.editor.enableAutoHeight();"," }",""," document.documentElement.style.overflow = this._bakHtmlOverflow;"," document.body.style.overflow = this._bakBodyOverflow;"," editor.iframe.parentNode.style.width = this._bakEditorContaninerWidth + 'px';"," window.scrollTo(0, this._bakScrollTop);"," }"," if (browser.gecko && editor.body.contentEditable === 'true') {"," var input = document.createElement('input');"," document.body.appendChild(input);"," editor.body.contentEditable = false;"," setTimeout(function () {"," input.focus();"," setTimeout(function () {"," editor.body.contentEditable = true;"," editor.fireEvent('fullscreenchanged', fullscreen);"," editor.selection.getRange().moveToBookmark(bk).select(true);"," baidu.editor.dom.domUtils.remove(input);"," fullscreen && window.scroll(0, 0);"," }, 0)"," }, 0)"," }",""," if(editor.body.contentEditable === 'true'){"," this.editor.fireEvent('fullscreenchanged', fullscreen);"," this.triggerLayout();"," }",""," }"," },"," _updateFullScreen:function () {"," if (this._fullscreen) {"," var vpRect = uiUtils.getViewportRect();"," this.getDom().style.cssText = 'border:0;position:absolute;left:0;top:' + (this.editor.options.topOffset || 0) + 'px;width:' + vpRect.width + 'px;height:' + vpRect.height + 'px;z-index:' + (this.getDom().style.zIndex * 1 + 100);"," uiUtils.setViewportOffset(this.getDom(), { left:0, top:this.editor.options.topOffset || 0 });"," this.editor.setHeight(vpRect.height - this.getDom('toolbarbox').offsetHeight - this.getDom('bottombar').offsetHeight - (this.editor.options.topOffset || 0));"," //不手动调一下,会导致全屏失效"," if(browser.gecko){"," try{"," window.onresize();"," }catch(e){",""," }",""," }"," }"," },"," _updateElementPath:function () {"," var bottom = this.getDom('elementpath'), list;"," if (this.elementPathEnabled && (list = this.editor.queryCommandValue('elementpath'))) {",""," var buff = [];"," for (var i = 0, ci; ci = list[i]; i++) {"," buff[i] = this.formatHtml('<span unselectable=\"on\" onclick=\"$$.editor.execCommand(&quot;elementpath&quot;, &quot;' + i + '&quot;);\">' + ci + '</span>');"," }"," bottom.innerHTML = '<div class=\"edui-editor-breadcrumb\" onmousedown=\"return false;\">' + this.editor.getLang(\"elementPathTip\") + ': ' + buff.join(' &gt; ') + '</div>';",""," } else {"," bottom.style.display = 'none'"," }"," },"," disableElementPath:function () {"," var bottom = this.getDom('elementpath');"," bottom.innerHTML = '';"," bottom.style.display = 'none';"," this.elementPathEnabled = false;",""," },"," enableElementPath:function () {"," var bottom = this.getDom('elementpath');"," bottom.style.display = '';"," this.elementPathEnabled = true;"," this._updateElementPath();"," },"," _scale:function () {"," var doc = document,"," editor = this.editor,"," editorHolder = editor.container,"," editorDocument = editor.document,"," toolbarBox = this.getDom(\"toolbarbox\"),"," bottombar = this.getDom(\"bottombar\"),"," scale = this.getDom(\"scale\"),"," scalelayer = this.getDom(\"scalelayer\");",""," var isMouseMove = false,"," position = null,"," minEditorHeight = 0,"," minEditorWidth = editor.options.minFrameWidth,"," pageX = 0,"," pageY = 0,"," scaleWidth = 0,"," scaleHeight = 0;",""," function down() {"," position = domUtils.getXY(editorHolder);",""," if (!minEditorHeight) {"," minEditorHeight = editor.options.minFrameHeight + toolbarBox.offsetHeight + bottombar.offsetHeight;"," }",""," scalelayer.style.cssText = \"position:absolute;left:0;display:;top:0;background-color:#41ABFF;opacity:0.4;filter: Alpha(opacity=40);width:\" + editorHolder.offsetWidth + \"px;height:\""," + editorHolder.offsetHeight + \"px;z-index:\" + (editor.options.zIndex + 1);",""," domUtils.on(doc, \"mousemove\", move);"," domUtils.on(editorDocument, \"mouseup\", up);"," domUtils.on(doc, \"mouseup\", up);"," }",""," var me = this;"," //by xuheng 全屏时关掉缩放"," this.editor.addListener('fullscreenchanged', function (e, fullScreen) {"," if (fullScreen) {"," me.disableScale();",""," } else {"," if (me.editor.options.scaleEnabled) {"," me.enableScale();"," var tmpNode = me.editor.document.createElement('span');"," me.editor.body.appendChild(tmpNode);"," me.editor.body.style.height = Math.max(domUtils.getXY(tmpNode).y, me.editor.iframe.offsetHeight - 20) + 'px';"," domUtils.remove(tmpNode)"," }"," }"," });"," function move(event) {"," clearSelection();"," var e = event || window.event;"," pageX = e.pageX || (doc.documentElement.scrollLeft + e.clientX);"," pageY = e.pageY || (doc.documentElement.scrollTop + e.clientY);"," scaleWidth = pageX - position.x;"," scaleHeight = pageY - position.y;",""," if (scaleWidth >= minEditorWidth) {"," isMouseMove = true;"," scalelayer.style.width = scaleWidth + 'px';"," }"," if (scaleHeight >= minEditorHeight) {"," isMouseMove = true;"," scalelayer.style.height = scaleHeight + \"px\";"," }"," }",""," function up() {"," if (isMouseMove) {"," isMouseMove = false;"," editor.ui._actualFrameWidth = scalelayer.offsetWidth - 2;"," editorHolder.style.width = editor.ui._actualFrameWidth + 'px';",""," editor.setHeight(scalelayer.offsetHeight - bottombar.offsetHeight - toolbarBox.offsetHeight - 2);"," }"," if (scalelayer) {"," scalelayer.style.display = \"none\";"," }"," clearSelection();"," domUtils.un(doc, \"mousemove\", move);"," domUtils.un(editorDocument, \"mouseup\", up);"," domUtils.un(doc, \"mouseup\", up);"," }",""," function clearSelection() {"," if (browser.ie)"," doc.selection.clear();"," else"," window.getSelection().removeAllRanges();"," }",""," this.enableScale = function () {"," //trace:2868"," if (editor.queryCommandState(\"source\") == 1) return;"," scale.style.display = \"\";"," this.scaleEnabled = true;"," domUtils.on(scale, \"mousedown\", down);"," };"," this.disableScale = function () {"," scale.style.display = \"none\";"," this.scaleEnabled = false;"," domUtils.un(scale, \"mousedown\", down);"," };"," },"," isFullScreen:function () {"," return this._fullscreen;"," },"," postRender:function () {"," UIBase.prototype.postRender.call(this);"," for (var i = 0; i < this.toolbars.length; i++) {"," this.toolbars[i].postRender();"," }"," var me = this;"," var timerId,"," domUtils = baidu.editor.dom.domUtils,"," updateFullScreenTime = function () {"," clearTimeout(timerId);"," timerId = setTimeout(function () {"," me._updateFullScreen();"," });"," };"," domUtils.on(window, 'resize', updateFullScreenTime);",""," me.addListener('destroy', function () {"," domUtils.un(window, 'resize', updateFullScreenTime);"," clearTimeout(timerId);"," })"," },"," showToolbarMsg:function (msg, flag) {"," this.getDom('toolbarmsg_label').innerHTML = msg;"," this.getDom('toolbarmsg').style.display = '';"," //"," if (!flag) {"," var w = this.getDom('upload_dialog');"," w.style.display = 'none';"," }"," },"," hideToolbarMsg:function () {"," this.getDom('toolbarmsg').style.display = 'none';"," },"," mapUrl:function (url) {"," return url ? url.replace('~/', this.editor.options.UEDITOR_HOME_URL || '') : ''"," },"," triggerLayout:function () {"," var dom = this.getDom();"," if (dom.style.zoom == '1') {"," dom.style.zoom = '100%';"," } else {"," dom.style.zoom = '1';"," }"," }"," };"," utils.inherits(EditorUI, baidu.editor.ui.UIBase);","",""," var instances = {};","",""," UE.ui.Editor = function (options) {"," var editor = new UE.Editor(options);"," editor.options.editor = editor;"," utils.loadFile(document, {"," href:editor.options.themePath + editor.options.theme + \"/_css/ueditor.css\","," tag:\"link\","," type:\"text/css\","," rel:\"stylesheet\""," });",""," var oldRender = editor.render;"," editor.render = function (holder) {"," if (holder.constructor === String) {"," editor.key = holder;"," instances[holder] = editor;"," }"," utils.domReady(function () {"," editor.langIsReady ? renderUI() : editor.addListener(\"langReady\", renderUI);"," function renderUI() {"," editor.setOpt({"," labelMap:editor.options.labelMap || editor.getLang('labelMap')"," });"," new EditorUI(editor.options);"," if (holder) {"," if (holder.constructor === String) {"," holder = document.getElementById(holder);"," }"," holder && holder.getAttribute('name') && ( editor.options.textarea = holder.getAttribute('name'));"," if (holder && /script|textarea/ig.test(holder.tagName)) {"," var newDiv = document.createElement('div');"," holder.parentNode.insertBefore(newDiv, holder);"," var cont = holder.value || holder.innerHTML;"," editor.options.initialContent = /^[\\t\\r\\n ]*$/.test(cont) ? editor.options.initialContent :"," cont.replace(/>[\\n\\r\\t]+([ ]{4})+/g, '>')"," .replace(/[\\n\\r\\t]+([ ]{4})+</g, '<')"," .replace(/>[\\n\\r\\t]+</g, '><');"," holder.className && (newDiv.className = holder.className);"," holder.style.cssText && (newDiv.style.cssText = holder.style.cssText);"," if (/textarea/i.test(holder.tagName)) {"," editor.textarea = holder;"," editor.textarea.style.display = 'none';",""," } else {"," holder.parentNode.removeChild(holder);"," holder.id && (newDiv.id = holder.id);"," }"," holder = newDiv;"," holder.innerHTML = '';"," }",""," }"," domUtils.addClass(holder, \"edui-\" + editor.options.theme);"," editor.ui.render(holder);"," var opt = editor.options;"," //给实例添加一个编辑器的容器引用"," editor.container = editor.ui.getDom();"," var parents = domUtils.findParents(holder,true);"," var displays = [];"," for(var i = 0 ,ci;ci=parents[i];i++){"," displays[i] = ci.style.display;"," ci.style.display = 'block'"," }"," if (opt.initialFrameWidth) {"," opt.minFrameWidth = opt.initialFrameWidth;"," } else {"," opt.minFrameWidth = opt.initialFrameWidth = holder.offsetWidth;"," }"," if (opt.initialFrameHeight) {"," opt.minFrameHeight = opt.initialFrameHeight;"," } else {"," opt.initialFrameHeight = opt.minFrameHeight = holder.offsetHeight;"," }"," for(var i = 0 ,ci;ci=parents[i];i++){"," ci.style.display = displays[i]"," }"," //编辑器最外容器设置了高度,会导致,编辑器不占位"," //todo 先去掉,没有找到原因"," if(holder.style.height){"," holder.style.height = ''"," }"," editor.container.style.width = opt.initialFrameWidth + (/%$/.test(opt.initialFrameWidth) ? '' : 'px');"," editor.container.style.zIndex = opt.zIndex;"," oldRender.call(editor, editor.ui.getDom('iframeholder'));",""," }"," })"," };"," return editor;"," };","",""," /**"," * @file"," * @name UE"," * @short UE"," * @desc UEditor的顶部命名空间"," */"," /**"," * @name getEditor"," * @since 1.2.4+"," * @grammar UE.getEditor(id,[opt]) => Editor实例"," * @desc 提供一个全局的方法得到编辑器实例"," *"," * * ''id'' 放置编辑器的容器id, 如果容器下的编辑器已经存在,就直接返回"," * * ''opt'' 编辑器的可选参数"," * @example"," * UE.getEditor('containerId',{onready:function(){//创建一个编辑器实例"," * this.setContent('hello')"," * }});"," * UE.getEditor('containerId'); //返回刚创建的实例"," *"," */"," UE.getEditor = function (id, opt) {"," var editor = instances[id];"," if (!editor) {"," editor = instances[id] = new UE.ui.Editor(opt);"," editor.render(id);"," }"," return editor;"," };","",""," UE.delEditor = function (id) {"," var editor;"," if (editor = instances[id]) {"," editor.key && editor.destroy();"," delete instances[id]"," }"," }","})();"]; +_$jscoverage['ui/editor.js'][5]++; +(function () { + _$jscoverage['ui/editor.js'][6]++; + var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, UIBase = baidu.editor.ui.UIBase, domUtils = baidu.editor.dom.domUtils; + _$jscoverage['ui/editor.js'][10]++; + var nodeStack = []; + _$jscoverage['ui/editor.js'][12]++; + function EditorUI(options) { + _$jscoverage['ui/editor.js'][13]++; + this.initOptions(options); + _$jscoverage['ui/editor.js'][14]++; + this.initEditorUI(); +} + _$jscoverage['ui/editor.js'][17]++; + EditorUI.prototype = {uiName: "editor", initEditorUI: (function () { + _$jscoverage['ui/editor.js'][20]++; + this.editor.ui = this; + _$jscoverage['ui/editor.js'][21]++; + this._dialogs = {}; + _$jscoverage['ui/editor.js'][22]++; + this.initUIBase(); + _$jscoverage['ui/editor.js'][23]++; + this._initToolbars(); + _$jscoverage['ui/editor.js'][24]++; + var editor = this.editor, me = this; + _$jscoverage['ui/editor.js'][27]++; + editor.addListener("ready", (function () { + _$jscoverage['ui/editor.js'][29]++; + editor.getDialog = (function (name) { + _$jscoverage['ui/editor.js'][30]++; + return editor.ui._dialogs[(name + "Dialog")]; +}); + _$jscoverage['ui/editor.js'][32]++; + domUtils.on(editor.window, "scroll", (function (evt) { + _$jscoverage['ui/editor.js'][33]++; + baidu.editor.ui.Popup.postHide(evt); +})); + _$jscoverage['ui/editor.js'][36]++; + editor.ui._actualFrameWidth = editor.options.initialFrameWidth; + _$jscoverage['ui/editor.js'][39]++; + if (editor.options.elementPathEnabled) { + _$jscoverage['ui/editor.js'][40]++; + editor.ui.getDom("elementpath").innerHTML = ("
    " + editor.getLang("elementPathTip") + ":
    "); + } + _$jscoverage['ui/editor.js'][42]++; + if (editor.options.wordCount) { + _$jscoverage['ui/editor.js'][43]++; + function countFn() { + _$jscoverage['ui/editor.js'][44]++; + setCount(editor, me); + _$jscoverage['ui/editor.js'][45]++; + domUtils.un(editor.document, "click", arguments.callee); +} + _$jscoverage['ui/editor.js'][47]++; + domUtils.on(editor.document, "click", countFn); + _$jscoverage['ui/editor.js'][48]++; + editor.ui.getDom("wordcount").innerHTML = editor.getLang("wordCountTip"); + } + _$jscoverage['ui/editor.js'][50]++; + editor.ui._scale(); + _$jscoverage['ui/editor.js'][51]++; + if (editor.options.scaleEnabled) { + _$jscoverage['ui/editor.js'][52]++; + if (editor.autoHeightEnabled) { + _$jscoverage['ui/editor.js'][53]++; + editor.disableAutoHeight(); + } + _$jscoverage['ui/editor.js'][55]++; + me.enableScale(); + } + else { + _$jscoverage['ui/editor.js'][57]++; + me.disableScale(); + } + _$jscoverage['ui/editor.js'][59]++; + if (((! editor.options.elementPathEnabled) && (! editor.options.wordCount) && (! editor.options.scaleEnabled))) { + _$jscoverage['ui/editor.js'][60]++; + editor.ui.getDom("elementpath").style.display = "none"; + _$jscoverage['ui/editor.js'][61]++; + editor.ui.getDom("wordcount").style.display = "none"; + _$jscoverage['ui/editor.js'][62]++; + editor.ui.getDom("scale").style.display = "none"; + } + _$jscoverage['ui/editor.js'][65]++; + if ((! editor.selection.isFocus())) { + _$jscoverage['ui/editor.js'][65]++; + return; + } + _$jscoverage['ui/editor.js'][66]++; + editor.fireEvent("selectionchange", false, true); +})); + _$jscoverage['ui/editor.js'][71]++; + editor.addListener("mousedown", (function (t, evt) { + _$jscoverage['ui/editor.js'][72]++; + var el = (evt.target || evt.srcElement); + _$jscoverage['ui/editor.js'][73]++; + baidu.editor.ui.Popup.postHide(evt, el); + _$jscoverage['ui/editor.js'][74]++; + baidu.editor.ui.ShortCutMenu.postHide(evt); +})); + _$jscoverage['ui/editor.js'][77]++; + editor.addListener("delcells", (function () { + _$jscoverage['ui/editor.js'][78]++; + if (UE.ui.edittip) { + _$jscoverage['ui/editor.js'][79]++; + new (UE.ui.edittip)(editor); + } + _$jscoverage['ui/editor.js'][81]++; + editor.getDialog("edittip").open(); +})); + _$jscoverage['ui/editor.js'][84]++; + var pastePop, isPaste = false, timer; + _$jscoverage['ui/editor.js'][85]++; + editor.addListener("afterpaste", (function () { + _$jscoverage['ui/editor.js'][86]++; + if (editor.queryCommandState("pasteplain")) { + _$jscoverage['ui/editor.js'][87]++; + return; + } + _$jscoverage['ui/editor.js'][88]++; + if (baidu.editor.ui.PastePicker) { + _$jscoverage['ui/editor.js'][89]++; + pastePop = new (baidu.editor.ui.Popup)({content: new (baidu.editor.ui.PastePicker)({editor: editor}), editor: editor, className: "edui-wordpastepop"}); + _$jscoverage['ui/editor.js'][94]++; + pastePop.render(); + } + _$jscoverage['ui/editor.js'][96]++; + isPaste = true; +})); + _$jscoverage['ui/editor.js'][99]++; + editor.addListener("afterinserthtml", (function () { + _$jscoverage['ui/editor.js'][100]++; + clearTimeout(timer); + _$jscoverage['ui/editor.js'][101]++; + timer = setTimeout((function () { + _$jscoverage['ui/editor.js'][102]++; + if ((pastePop && (isPaste || editor.ui._isTransfer))) { + _$jscoverage['ui/editor.js'][103]++; + if (pastePop.isHidden()) { + _$jscoverage['ui/editor.js'][104]++; + var span = domUtils.createElement(editor.document, "span", {"style": "line-height:0px;", "innerHTML": "\ufeff"}), range = editor.selection.getRange(); + _$jscoverage['ui/editor.js'][109]++; + range.insertNode(span); + _$jscoverage['ui/editor.js'][110]++; + var tmp = getDomNode(span, "firstChild", "previousSibling"); + _$jscoverage['ui/editor.js'][111]++; + pastePop.showAnchor(((tmp.nodeType == 3)? tmp.parentNode: tmp)); + _$jscoverage['ui/editor.js'][112]++; + domUtils.remove(span); + } + else { + _$jscoverage['ui/editor.js'][115]++; + pastePop.show(); + } + _$jscoverage['ui/editor.js'][117]++; + (delete editor.ui._isTransfer); + _$jscoverage['ui/editor.js'][118]++; + isPaste = false; + } +}), 200); +})); + _$jscoverage['ui/editor.js'][122]++; + editor.addListener("contextmenu", (function (t, evt) { + _$jscoverage['ui/editor.js'][123]++; + baidu.editor.ui.Popup.postHide(evt); +})); + _$jscoverage['ui/editor.js'][125]++; + editor.addListener("keydown", (function (t, evt) { + _$jscoverage['ui/editor.js'][126]++; + if (pastePop) { + _$jscoverage['ui/editor.js'][126]++; + pastePop.dispose(evt); + } + _$jscoverage['ui/editor.js'][127]++; + var keyCode = (evt.keyCode || evt.which); + _$jscoverage['ui/editor.js'][128]++; + if ((evt.altKey && (keyCode == 90))) { + _$jscoverage['ui/editor.js'][129]++; + UE.ui.buttons.fullscreen.onclick(); + } +})); + _$jscoverage['ui/editor.js'][132]++; + editor.addListener("wordcount", (function (type) { + _$jscoverage['ui/editor.js'][133]++; + setCount(this, me); +})); + _$jscoverage['ui/editor.js'][135]++; + function setCount(editor, ui) { + _$jscoverage['ui/editor.js'][136]++; + editor.setOpt({wordCount: true, maximumWords: 10000, wordCountMsg: (editor.options.wordCountMsg || editor.getLang("wordCountMsg")), wordOverFlowMsg: (editor.options.wordOverFlowMsg || editor.getLang("wordOverFlowMsg"))}); + _$jscoverage['ui/editor.js'][142]++; + var opt = editor.options, max = opt.maximumWords, msg = opt.wordCountMsg, errMsg = opt.wordOverFlowMsg, countDom = ui.getDom("wordcount"); + _$jscoverage['ui/editor.js'][147]++; + if ((! opt.wordCount)) { + _$jscoverage['ui/editor.js'][148]++; + return; + } + _$jscoverage['ui/editor.js'][150]++; + var count = editor.getContentLength(true); + _$jscoverage['ui/editor.js'][151]++; + if ((count > max)) { + _$jscoverage['ui/editor.js'][152]++; + countDom.innerHTML = errMsg; + _$jscoverage['ui/editor.js'][153]++; + editor.fireEvent("wordcountoverflow"); + } + else { + _$jscoverage['ui/editor.js'][155]++; + countDom.innerHTML = msg.replace("{#leave}", (max - count)).replace("{#count}", count); + } +} + _$jscoverage['ui/editor.js'][159]++; + editor.addListener("selectionchange", (function () { + _$jscoverage['ui/editor.js'][160]++; + if (editor.options.elementPathEnabled) { + _$jscoverage['ui/editor.js'][161]++; + (me[(((editor.queryCommandState("elementpath") == -1)? "dis": "en") + "ableElementPath")])(); + } + _$jscoverage['ui/editor.js'][163]++; + if (editor.options.scaleEnabled) { + _$jscoverage['ui/editor.js'][164]++; + (me[(((editor.queryCommandState("scale") == -1)? "dis": "en") + "ableScale")])(); + } +})); + _$jscoverage['ui/editor.js'][168]++; + var popup = new (baidu.editor.ui.Popup)({editor: editor, content: "", className: "edui-bubble", _onEditButtonClick: (function () { + _$jscoverage['ui/editor.js'][173]++; + this.hide(); + _$jscoverage['ui/editor.js'][174]++; + editor.ui._dialogs.linkDialog.open(); +}), _onImgEditButtonClick: (function (name) { + _$jscoverage['ui/editor.js'][177]++; + this.hide(); + _$jscoverage['ui/editor.js'][178]++; + (editor.ui._dialogs[name] && editor.ui._dialogs[name].open()); +}), _onImgSetFloat: (function (value) { + _$jscoverage['ui/editor.js'][182]++; + this.hide(); + _$jscoverage['ui/editor.js'][183]++; + editor.execCommand("imagefloat", value); +}), _setIframeAlign: (function (value) { + _$jscoverage['ui/editor.js'][187]++; + var frame = popup.anchorEl; + _$jscoverage['ui/editor.js'][188]++; + var newFrame = frame.cloneNode(true); + _$jscoverage['ui/editor.js'][189]++; + switch (value) { + case -2: + _$jscoverage['ui/editor.js'][191]++; + newFrame.setAttribute("align", ""); + _$jscoverage['ui/editor.js'][192]++; + break; + case -1: + _$jscoverage['ui/editor.js'][194]++; + newFrame.setAttribute("align", "left"); + _$jscoverage['ui/editor.js'][195]++; + break; + case 1: + _$jscoverage['ui/editor.js'][197]++; + newFrame.setAttribute("align", "right"); + _$jscoverage['ui/editor.js'][198]++; + break; + } + _$jscoverage['ui/editor.js'][200]++; + frame.parentNode.insertBefore(newFrame, frame); + _$jscoverage['ui/editor.js'][201]++; + domUtils.remove(frame); + _$jscoverage['ui/editor.js'][202]++; + popup.anchorEl = newFrame; + _$jscoverage['ui/editor.js'][203]++; + popup.showAnchor(popup.anchorEl); +}), _updateIframe: (function () { + _$jscoverage['ui/editor.js'][206]++; + editor._iframe = popup.anchorEl; + _$jscoverage['ui/editor.js'][207]++; + editor.ui._dialogs.insertframeDialog.open(); + _$jscoverage['ui/editor.js'][208]++; + popup.hide(); +}), _onRemoveButtonClick: (function (cmdName) { + _$jscoverage['ui/editor.js'][211]++; + editor.execCommand(cmdName); + _$jscoverage['ui/editor.js'][212]++; + this.hide(); +}), queryAutoHide: (function (el) { + _$jscoverage['ui/editor.js'][215]++; + if ((el && (el.ownerDocument == editor.document))) { + _$jscoverage['ui/editor.js'][216]++; + if (((el.tagName.toLowerCase() == "img") || domUtils.findParentByTagName(el, "a", true))) { + _$jscoverage['ui/editor.js'][217]++; + return (el !== popup.anchorEl); + } + } + _$jscoverage['ui/editor.js'][220]++; + return baidu.editor.ui.Popup.prototype.queryAutoHide.call(this, el); +})}); + _$jscoverage['ui/editor.js'][223]++; + popup.render(); + _$jscoverage['ui/editor.js'][224]++; + if (editor.options.imagePopup) { + _$jscoverage['ui/editor.js'][225]++; + editor.addListener("mouseover", (function (t, evt) { + _$jscoverage['ui/editor.js'][226]++; + evt = (evt || window.event); + _$jscoverage['ui/editor.js'][227]++; + var el = (evt.target || evt.srcElement); + _$jscoverage['ui/editor.js'][228]++; + if ((editor.ui._dialogs.insertframeDialog && /iframe/gi.test(el.tagName))) { + _$jscoverage['ui/editor.js'][229]++; + var html = popup.formatHtml(("" + editor.getLang("property") + ": " + editor.getLang("default") + "  " + editor.getLang("justifyleft") + "  " + editor.getLang("justifyright") + "  " + " " + editor.getLang("modify") + "")); + _$jscoverage['ui/editor.js'][232]++; + if (html) { + _$jscoverage['ui/editor.js'][233]++; + popup.getDom("content").innerHTML = html; + _$jscoverage['ui/editor.js'][234]++; + popup.anchorEl = el; + _$jscoverage['ui/editor.js'][235]++; + popup.showAnchor(popup.anchorEl); + } + else { + _$jscoverage['ui/editor.js'][237]++; + popup.hide(); + } + } +})); + _$jscoverage['ui/editor.js'][241]++; + editor.addListener("selectionchange", (function (t, causeByUi) { + _$jscoverage['ui/editor.js'][242]++; + if ((! causeByUi)) { + _$jscoverage['ui/editor.js'][242]++; + return; + } + _$jscoverage['ui/editor.js'][243]++; + var html = "", str = "", img = editor.selection.getRange().getClosedNode(), dialogs = editor.ui._dialogs; + _$jscoverage['ui/editor.js'][246]++; + if ((img && (img.tagName == "IMG"))) { + _$jscoverage['ui/editor.js'][247]++; + var dialogName = "insertimageDialog"; + _$jscoverage['ui/editor.js'][248]++; + if ((img.className.indexOf("edui-faked-video") != -1)) { + _$jscoverage['ui/editor.js'][249]++; + dialogName = "insertvideoDialog"; + } + _$jscoverage['ui/editor.js'][251]++; + if ((img.className.indexOf("edui-faked-webapp") != -1)) { + _$jscoverage['ui/editor.js'][252]++; + dialogName = "webappDialog"; + } + _$jscoverage['ui/editor.js'][254]++; + if ((img.src.indexOf("http://api.map.baidu.com") != -1)) { + _$jscoverage['ui/editor.js'][255]++; + dialogName = "mapDialog"; + } + _$jscoverage['ui/editor.js'][257]++; + if ((img.className.indexOf("edui-faked-music") != -1)) { + _$jscoverage['ui/editor.js'][258]++; + dialogName = "musicDialog"; + } + _$jscoverage['ui/editor.js'][260]++; + if ((img.src.indexOf("http://maps.google.com/maps/api/staticmap") != -1)) { + _$jscoverage['ui/editor.js'][261]++; + dialogName = "gmapDialog"; + } + _$jscoverage['ui/editor.js'][263]++; + if (img.getAttribute("anchorname")) { + _$jscoverage['ui/editor.js'][264]++; + dialogName = "anchorDialog"; + _$jscoverage['ui/editor.js'][265]++; + html = popup.formatHtml(("" + editor.getLang("property") + ": " + editor.getLang("modify") + "  " + "" + editor.getLang("delete") + "")); + } + _$jscoverage['ui/editor.js'][269]++; + if (img.getAttribute("word_img")) { + _$jscoverage['ui/editor.js'][271]++; + editor.word_img = [img.getAttribute("word_img")]; + _$jscoverage['ui/editor.js'][272]++; + dialogName = "wordimageDialog"; + } + _$jscoverage['ui/editor.js'][274]++; + if ((! dialogs[dialogName])) { + _$jscoverage['ui/editor.js'][275]++; + return; + } + _$jscoverage['ui/editor.js'][277]++; + str = ("" + editor.getLang("property") + ": " + "" + editor.getLang("default") + "  " + "" + editor.getLang("justifyleft") + "  " + "" + editor.getLang("justifyright") + "  " + "" + editor.getLang("justifycenter") + "  " + "" + editor.getLang("modify") + ""); + _$jscoverage['ui/editor.js'][284]++; + ((! html) && (html = popup.formatHtml(str))); + } + _$jscoverage['ui/editor.js'][287]++; + if (editor.ui._dialogs.linkDialog) { + _$jscoverage['ui/editor.js'][288]++; + var link = editor.queryCommandValue("link"); + _$jscoverage['ui/editor.js'][289]++; + var url; + _$jscoverage['ui/editor.js'][290]++; + if ((link && (url = (link.getAttribute("_href") || link.getAttribute("href", 2))))) { + _$jscoverage['ui/editor.js'][291]++; + var txt = url; + _$jscoverage['ui/editor.js'][292]++; + if ((url.length > 30)) { + _$jscoverage['ui/editor.js'][293]++; + txt = (url.substring(0, 20) + "..."); + } + _$jscoverage['ui/editor.js'][295]++; + if (html) { + _$jscoverage['ui/editor.js'][296]++; + html += "
    "; + } + _$jscoverage['ui/editor.js'][298]++; + html += popup.formatHtml(("" + editor.getLang("anthorMsg") + ": " + txt + "" + " " + editor.getLang("modify") + "" + " " + editor.getLang("clear") + "")); + _$jscoverage['ui/editor.js'][302]++; + popup.showAnchor(link); + } + } + _$jscoverage['ui/editor.js'][306]++; + if (html) { + _$jscoverage['ui/editor.js'][307]++; + popup.getDom("content").innerHTML = html; + _$jscoverage['ui/editor.js'][308]++; + popup.anchorEl = (img || link); + _$jscoverage['ui/editor.js'][309]++; + popup.showAnchor(popup.anchorEl); + } + else { + _$jscoverage['ui/editor.js'][311]++; + popup.hide(); + } +})); + } +}), _initToolbars: (function () { + _$jscoverage['ui/editor.js'][318]++; + var editor = this.editor; + _$jscoverage['ui/editor.js'][319]++; + var toolbars = (this.toolbars || []); + _$jscoverage['ui/editor.js'][320]++; + var toolbarUis = []; + _$jscoverage['ui/editor.js'][321]++; + for (var i = 0; (i < toolbars.length); (i++)) { + _$jscoverage['ui/editor.js'][322]++; + var toolbar = toolbars[i]; + _$jscoverage['ui/editor.js'][323]++; + var toolbarUi = new (baidu.editor.ui.Toolbar)({theme: editor.options.theme}); + _$jscoverage['ui/editor.js'][324]++; + for (var j = 0; (j < toolbar.length); (j++)) { + _$jscoverage['ui/editor.js'][325]++; + var toolbarItem = toolbar[j]; + _$jscoverage['ui/editor.js'][326]++; + var toolbarItemUi = null; + _$jscoverage['ui/editor.js'][327]++; + if (((typeof toolbarItem) == "string")) { + _$jscoverage['ui/editor.js'][328]++; + toolbarItem = toolbarItem.toLowerCase(); + _$jscoverage['ui/editor.js'][329]++; + if ((toolbarItem == "|")) { + _$jscoverage['ui/editor.js'][330]++; + toolbarItem = "Separator"; + } + _$jscoverage['ui/editor.js'][332]++; + if ((toolbarItem == "||")) { + _$jscoverage['ui/editor.js'][333]++; + toolbarItem = "Breakline"; + } + _$jscoverage['ui/editor.js'][335]++; + if (baidu.editor.ui[toolbarItem]) { + _$jscoverage['ui/editor.js'][336]++; + toolbarItemUi = new (baidu.editor.ui[toolbarItem])(editor); + } + _$jscoverage['ui/editor.js'][340]++; + if ((toolbarItem == "fullscreen")) { + _$jscoverage['ui/editor.js'][341]++; + if ((toolbarUis && toolbarUis[0])) { + _$jscoverage['ui/editor.js'][342]++; + toolbarUis[0].items.splice(0, 0, toolbarItemUi); + } + else { + _$jscoverage['ui/editor.js'][344]++; + (toolbarItemUi && toolbarUi.items.splice(0, 0, toolbarItemUi)); + } + _$jscoverage['ui/editor.js'][347]++; + continue; + } + } + else { + _$jscoverage['ui/editor.js'][352]++; + toolbarItemUi = toolbarItem; + } + _$jscoverage['ui/editor.js'][354]++; + if ((toolbarItemUi && toolbarItemUi.id)) { + _$jscoverage['ui/editor.js'][356]++; + toolbarUi.add(toolbarItemUi); + } +} + _$jscoverage['ui/editor.js'][359]++; + toolbarUis[i] = toolbarUi; +} + _$jscoverage['ui/editor.js'][361]++; + this.toolbars = toolbarUis; +}), getHtmlTpl: (function () { + _$jscoverage['ui/editor.js'][364]++; + return ("
    " + "
    " + (this.toolbars.length? ("
    " + this.renderToolbarBoxHtml() + "
    "): "") + "
    " + "
    " + this.editor.getLang("clickToUpload") + "
    " + "
    x
    " + "
    " + "
    " + "
    " + "
    " + "
    " + "
    " + "" + "" + "" + "
    " + "
    " + "
    "); +}), showWordImageDialog: (function () { + _$jscoverage['ui/editor.js'][388]++; + this.editor.execCommand("wordimage", "word_img"); + _$jscoverage['ui/editor.js'][389]++; + this._dialogs.wordimageDialog.open(); +}), renderToolbarBoxHtml: (function () { + _$jscoverage['ui/editor.js'][392]++; + var buff = []; + _$jscoverage['ui/editor.js'][393]++; + for (var i = 0; (i < this.toolbars.length); (i++)) { + _$jscoverage['ui/editor.js'][394]++; + buff.push(this.toolbars[i].renderHtml()); +} + _$jscoverage['ui/editor.js'][396]++; + return buff.join(""); +}), setFullScreen: (function (fullscreen) { + _$jscoverage['ui/editor.js'][400]++; + var editor = this.editor, container = editor.container.parentNode.parentNode; + _$jscoverage['ui/editor.js'][402]++; + if ((this._fullscreen != fullscreen)) { + _$jscoverage['ui/editor.js'][403]++; + this._fullscreen = fullscreen; + _$jscoverage['ui/editor.js'][404]++; + this.editor.fireEvent("beforefullscreenchange", fullscreen); + _$jscoverage['ui/editor.js'][405]++; + if (baidu.editor.browser.gecko) { + _$jscoverage['ui/editor.js'][406]++; + var bk = editor.selection.getRange().createBookmark(); + } + _$jscoverage['ui/editor.js'][408]++; + if (fullscreen) { + _$jscoverage['ui/editor.js'][409]++; + while ((container.tagName != "BODY")) { + _$jscoverage['ui/editor.js'][410]++; + var position = baidu.editor.dom.domUtils.getComputedStyle(container, "position"); + _$jscoverage['ui/editor.js'][411]++; + nodeStack.push(position); + _$jscoverage['ui/editor.js'][412]++; + container.style.position = "static"; + _$jscoverage['ui/editor.js'][413]++; + container = container.parentNode; +} + _$jscoverage['ui/editor.js'][415]++; + this._bakHtmlOverflow = document.documentElement.style.overflow; + _$jscoverage['ui/editor.js'][416]++; + this._bakBodyOverflow = document.body.style.overflow; + _$jscoverage['ui/editor.js'][417]++; + this._bakAutoHeight = this.editor.autoHeightEnabled; + _$jscoverage['ui/editor.js'][418]++; + this._bakScrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop); + _$jscoverage['ui/editor.js'][420]++; + this._bakEditorContaninerWidth = editor.iframe.parentNode.offsetWidth; + _$jscoverage['ui/editor.js'][421]++; + if (this._bakAutoHeight) { + _$jscoverage['ui/editor.js'][423]++; + editor.autoHeightEnabled = false; + _$jscoverage['ui/editor.js'][424]++; + this.editor.disableAutoHeight(); + } + _$jscoverage['ui/editor.js'][427]++; + document.documentElement.style.overflow = "hidden"; + _$jscoverage['ui/editor.js'][428]++; + document.body.style.overflow = "hidden"; + _$jscoverage['ui/editor.js'][429]++; + this._bakCssText = this.getDom().style.cssText; + _$jscoverage['ui/editor.js'][430]++; + this._bakCssText1 = this.getDom("iframeholder").style.cssText; + _$jscoverage['ui/editor.js'][431]++; + editor.iframe.parentNode.style.width = ""; + _$jscoverage['ui/editor.js'][432]++; + this._updateFullScreen(); + } + else { + _$jscoverage['ui/editor.js'][434]++; + while ((container.tagName != "BODY")) { + _$jscoverage['ui/editor.js'][435]++; + container.style.position = nodeStack.shift(); + _$jscoverage['ui/editor.js'][436]++; + container = container.parentNode; +} + _$jscoverage['ui/editor.js'][438]++; + this.getDom().style.cssText = this._bakCssText; + _$jscoverage['ui/editor.js'][439]++; + this.getDom("iframeholder").style.cssText = this._bakCssText1; + _$jscoverage['ui/editor.js'][440]++; + if (this._bakAutoHeight) { + _$jscoverage['ui/editor.js'][441]++; + editor.autoHeightEnabled = true; + _$jscoverage['ui/editor.js'][442]++; + this.editor.enableAutoHeight(); + } + _$jscoverage['ui/editor.js'][445]++; + document.documentElement.style.overflow = this._bakHtmlOverflow; + _$jscoverage['ui/editor.js'][446]++; + document.body.style.overflow = this._bakBodyOverflow; + _$jscoverage['ui/editor.js'][447]++; + editor.iframe.parentNode.style.width = (this._bakEditorContaninerWidth + "px"); + _$jscoverage['ui/editor.js'][448]++; + window.scrollTo(0, this._bakScrollTop); + } + _$jscoverage['ui/editor.js'][450]++; + if ((browser.gecko && (editor.body.contentEditable === "true"))) { + _$jscoverage['ui/editor.js'][451]++; + var input = document.createElement("input"); + _$jscoverage['ui/editor.js'][452]++; + document.body.appendChild(input); + _$jscoverage['ui/editor.js'][453]++; + editor.body.contentEditable = false; + _$jscoverage['ui/editor.js'][454]++; + setTimeout((function () { + _$jscoverage['ui/editor.js'][455]++; + input.focus(); + _$jscoverage['ui/editor.js'][456]++; + setTimeout((function () { + _$jscoverage['ui/editor.js'][457]++; + editor.body.contentEditable = true; + _$jscoverage['ui/editor.js'][458]++; + editor.fireEvent("fullscreenchanged", fullscreen); + _$jscoverage['ui/editor.js'][459]++; + editor.selection.getRange().moveToBookmark(bk).select(true); + _$jscoverage['ui/editor.js'][460]++; + baidu.editor.dom.domUtils.remove(input); + _$jscoverage['ui/editor.js'][461]++; + (fullscreen && window.scroll(0, 0)); +}), 0); +}), 0); + } + _$jscoverage['ui/editor.js'][466]++; + if ((editor.body.contentEditable === "true")) { + _$jscoverage['ui/editor.js'][467]++; + this.editor.fireEvent("fullscreenchanged", fullscreen); + _$jscoverage['ui/editor.js'][468]++; + this.triggerLayout(); + } + } +}), _updateFullScreen: (function () { + _$jscoverage['ui/editor.js'][474]++; + if (this._fullscreen) { + _$jscoverage['ui/editor.js'][475]++; + var vpRect = uiUtils.getViewportRect(); + _$jscoverage['ui/editor.js'][476]++; + this.getDom().style.cssText = ("border:0;position:absolute;left:0;top:" + (this.editor.options.topOffset || 0) + "px;width:" + vpRect.width + "px;height:" + vpRect.height + "px;z-index:" + ((this.getDom().style.zIndex * 1) + 100)); + _$jscoverage['ui/editor.js'][477]++; + uiUtils.setViewportOffset(this.getDom(), {left: 0, top: (this.editor.options.topOffset || 0)}); + _$jscoverage['ui/editor.js'][478]++; + this.editor.setHeight((vpRect.height - this.getDom("toolbarbox").offsetHeight - this.getDom("bottombar").offsetHeight - (this.editor.options.topOffset || 0))); + _$jscoverage['ui/editor.js'][480]++; + if (browser.gecko) { + _$jscoverage['ui/editor.js'][481]++; + try { + _$jscoverage['ui/editor.js'][482]++; + window.onresize(); + } + catch (e) { + } + } + } +}), _updateElementPath: (function () { + _$jscoverage['ui/editor.js'][491]++; + var bottom = this.getDom("elementpath"), list; + _$jscoverage['ui/editor.js'][492]++; + if ((this.elementPathEnabled && (list = this.editor.queryCommandValue("elementpath")))) { + _$jscoverage['ui/editor.js'][494]++; + var buff = []; + _$jscoverage['ui/editor.js'][495]++; + for (var i = 0, ci; (ci = list[i]); (i++)) { + _$jscoverage['ui/editor.js'][496]++; + buff[i] = this.formatHtml(("" + ci + "")); +} + _$jscoverage['ui/editor.js'][498]++; + bottom.innerHTML = ("
    " + this.editor.getLang("elementPathTip") + ": " + buff.join(" > ") + "
    "); + } + else { + _$jscoverage['ui/editor.js'][501]++; + bottom.style.display = "none"; + } +}), disableElementPath: (function () { + _$jscoverage['ui/editor.js'][505]++; + var bottom = this.getDom("elementpath"); + _$jscoverage['ui/editor.js'][506]++; + bottom.innerHTML = ""; + _$jscoverage['ui/editor.js'][507]++; + bottom.style.display = "none"; + _$jscoverage['ui/editor.js'][508]++; + this.elementPathEnabled = false; +}), enableElementPath: (function () { + _$jscoverage['ui/editor.js'][512]++; + var bottom = this.getDom("elementpath"); + _$jscoverage['ui/editor.js'][513]++; + bottom.style.display = ""; + _$jscoverage['ui/editor.js'][514]++; + this.elementPathEnabled = true; + _$jscoverage['ui/editor.js'][515]++; + this._updateElementPath(); +}), _scale: (function () { + _$jscoverage['ui/editor.js'][518]++; + var doc = document, editor = this.editor, editorHolder = editor.container, editorDocument = editor.document, toolbarBox = this.getDom("toolbarbox"), bottombar = this.getDom("bottombar"), scale = this.getDom("scale"), scalelayer = this.getDom("scalelayer"); + _$jscoverage['ui/editor.js'][527]++; + var isMouseMove = false, position = null, minEditorHeight = 0, minEditorWidth = editor.options.minFrameWidth, pageX = 0, pageY = 0, scaleWidth = 0, scaleHeight = 0; + _$jscoverage['ui/editor.js'][536]++; + function down() { + _$jscoverage['ui/editor.js'][537]++; + position = domUtils.getXY(editorHolder); + _$jscoverage['ui/editor.js'][539]++; + if ((! minEditorHeight)) { + _$jscoverage['ui/editor.js'][540]++; + minEditorHeight = (editor.options.minFrameHeight + toolbarBox.offsetHeight + bottombar.offsetHeight); + } + _$jscoverage['ui/editor.js'][543]++; + scalelayer.style.cssText = ("position:absolute;left:0;display:;top:0;background-color:#41ABFF;opacity:0.4;filter: Alpha(opacity=40);width:" + editorHolder.offsetWidth + "px;height:" + editorHolder.offsetHeight + "px;z-index:" + (editor.options.zIndex + 1)); + _$jscoverage['ui/editor.js'][546]++; + domUtils.on(doc, "mousemove", move); + _$jscoverage['ui/editor.js'][547]++; + domUtils.on(editorDocument, "mouseup", up); + _$jscoverage['ui/editor.js'][548]++; + domUtils.on(doc, "mouseup", up); +} + _$jscoverage['ui/editor.js'][551]++; + var me = this; + _$jscoverage['ui/editor.js'][553]++; + this.editor.addListener("fullscreenchanged", (function (e, fullScreen) { + _$jscoverage['ui/editor.js'][554]++; + if (fullScreen) { + _$jscoverage['ui/editor.js'][555]++; + me.disableScale(); + } + else { + _$jscoverage['ui/editor.js'][558]++; + if (me.editor.options.scaleEnabled) { + _$jscoverage['ui/editor.js'][559]++; + me.enableScale(); + _$jscoverage['ui/editor.js'][560]++; + var tmpNode = me.editor.document.createElement("span"); + _$jscoverage['ui/editor.js'][561]++; + me.editor.body.appendChild(tmpNode); + _$jscoverage['ui/editor.js'][562]++; + me.editor.body.style.height = (Math.max(domUtils.getXY(tmpNode).y, (me.editor.iframe.offsetHeight - 20)) + "px"); + _$jscoverage['ui/editor.js'][563]++; + domUtils.remove(tmpNode); + } + } +})); + _$jscoverage['ui/editor.js'][567]++; + function move(event) { + _$jscoverage['ui/editor.js'][568]++; + clearSelection(); + _$jscoverage['ui/editor.js'][569]++; + var e = (event || window.event); + _$jscoverage['ui/editor.js'][570]++; + pageX = (e.pageX || (doc.documentElement.scrollLeft + e.clientX)); + _$jscoverage['ui/editor.js'][571]++; + pageY = (e.pageY || (doc.documentElement.scrollTop + e.clientY)); + _$jscoverage['ui/editor.js'][572]++; + scaleWidth = (pageX - position.x); + _$jscoverage['ui/editor.js'][573]++; + scaleHeight = (pageY - position.y); + _$jscoverage['ui/editor.js'][575]++; + if ((scaleWidth >= minEditorWidth)) { + _$jscoverage['ui/editor.js'][576]++; + isMouseMove = true; + _$jscoverage['ui/editor.js'][577]++; + scalelayer.style.width = (scaleWidth + "px"); + } + _$jscoverage['ui/editor.js'][579]++; + if ((scaleHeight >= minEditorHeight)) { + _$jscoverage['ui/editor.js'][580]++; + isMouseMove = true; + _$jscoverage['ui/editor.js'][581]++; + scalelayer.style.height = (scaleHeight + "px"); + } +} + _$jscoverage['ui/editor.js'][585]++; + function up() { + _$jscoverage['ui/editor.js'][586]++; + if (isMouseMove) { + _$jscoverage['ui/editor.js'][587]++; + isMouseMove = false; + _$jscoverage['ui/editor.js'][588]++; + editor.ui._actualFrameWidth = (scalelayer.offsetWidth - 2); + _$jscoverage['ui/editor.js'][589]++; + editorHolder.style.width = (editor.ui._actualFrameWidth + "px"); + _$jscoverage['ui/editor.js'][591]++; + editor.setHeight((scalelayer.offsetHeight - bottombar.offsetHeight - toolbarBox.offsetHeight - 2)); + } + _$jscoverage['ui/editor.js'][593]++; + if (scalelayer) { + _$jscoverage['ui/editor.js'][594]++; + scalelayer.style.display = "none"; + } + _$jscoverage['ui/editor.js'][596]++; + clearSelection(); + _$jscoverage['ui/editor.js'][597]++; + domUtils.un(doc, "mousemove", move); + _$jscoverage['ui/editor.js'][598]++; + domUtils.un(editorDocument, "mouseup", up); + _$jscoverage['ui/editor.js'][599]++; + domUtils.un(doc, "mouseup", up); +} + _$jscoverage['ui/editor.js'][602]++; + function clearSelection() { + _$jscoverage['ui/editor.js'][603]++; + if (browser.ie) { + _$jscoverage['ui/editor.js'][604]++; + doc.selection.clear(); + } + else { + _$jscoverage['ui/editor.js'][606]++; + window.getSelection().removeAllRanges(); + } +} + _$jscoverage['ui/editor.js'][609]++; + this.enableScale = (function () { + _$jscoverage['ui/editor.js'][611]++; + if ((editor.queryCommandState("source") == 1)) { + _$jscoverage['ui/editor.js'][611]++; + return; + } + _$jscoverage['ui/editor.js'][612]++; + scale.style.display = ""; + _$jscoverage['ui/editor.js'][613]++; + this.scaleEnabled = true; + _$jscoverage['ui/editor.js'][614]++; + domUtils.on(scale, "mousedown", down); +}); + _$jscoverage['ui/editor.js'][616]++; + this.disableScale = (function () { + _$jscoverage['ui/editor.js'][617]++; + scale.style.display = "none"; + _$jscoverage['ui/editor.js'][618]++; + this.scaleEnabled = false; + _$jscoverage['ui/editor.js'][619]++; + domUtils.un(scale, "mousedown", down); +}); +}), isFullScreen: (function () { + _$jscoverage['ui/editor.js'][623]++; + return this._fullscreen; +}), postRender: (function () { + _$jscoverage['ui/editor.js'][626]++; + UIBase.prototype.postRender.call(this); + _$jscoverage['ui/editor.js'][627]++; + for (var i = 0; (i < this.toolbars.length); (i++)) { + _$jscoverage['ui/editor.js'][628]++; + this.toolbars[i].postRender(); +} + _$jscoverage['ui/editor.js'][630]++; + var me = this; + _$jscoverage['ui/editor.js'][631]++; + var timerId, domUtils = baidu.editor.dom.domUtils, updateFullScreenTime = (function () { + _$jscoverage['ui/editor.js'][634]++; + clearTimeout(timerId); + _$jscoverage['ui/editor.js'][635]++; + timerId = setTimeout((function () { + _$jscoverage['ui/editor.js'][636]++; + me._updateFullScreen(); +})); +}); + _$jscoverage['ui/editor.js'][639]++; + domUtils.on(window, "resize", updateFullScreenTime); + _$jscoverage['ui/editor.js'][641]++; + me.addListener("destroy", (function () { + _$jscoverage['ui/editor.js'][642]++; + domUtils.un(window, "resize", updateFullScreenTime); + _$jscoverage['ui/editor.js'][643]++; + clearTimeout(timerId); +})); +}), showToolbarMsg: (function (msg, flag) { + _$jscoverage['ui/editor.js'][647]++; + this.getDom("toolbarmsg_label").innerHTML = msg; + _$jscoverage['ui/editor.js'][648]++; + this.getDom("toolbarmsg").style.display = ""; + _$jscoverage['ui/editor.js'][650]++; + if ((! flag)) { + _$jscoverage['ui/editor.js'][651]++; + var w = this.getDom("upload_dialog"); + _$jscoverage['ui/editor.js'][652]++; + w.style.display = "none"; + } +}), hideToolbarMsg: (function () { + _$jscoverage['ui/editor.js'][656]++; + this.getDom("toolbarmsg").style.display = "none"; +}), mapUrl: (function (url) { + _$jscoverage['ui/editor.js'][659]++; + return (url? url.replace("~/", (this.editor.options.UEDITOR_HOME_URL || "")): ""); +}), triggerLayout: (function () { + _$jscoverage['ui/editor.js'][662]++; + var dom = this.getDom(); + _$jscoverage['ui/editor.js'][663]++; + if ((dom.style.zoom == "1")) { + _$jscoverage['ui/editor.js'][664]++; + dom.style.zoom = "100%"; + } + else { + _$jscoverage['ui/editor.js'][666]++; + dom.style.zoom = "1"; + } +})}; + _$jscoverage['ui/editor.js'][670]++; + utils.inherits(EditorUI, baidu.editor.ui.UIBase); + _$jscoverage['ui/editor.js'][673]++; + var instances = {}; + _$jscoverage['ui/editor.js'][676]++; + UE.ui.Editor = (function (options) { + _$jscoverage['ui/editor.js'][677]++; + var editor = new (UE.Editor)(options); + _$jscoverage['ui/editor.js'][678]++; + editor.options.editor = editor; + _$jscoverage['ui/editor.js'][679]++; + utils.loadFile(document, {href: (editor.options.themePath + editor.options.theme + "/_css/ueditor.css"), tag: "link", type: "text/css", rel: "stylesheet"}); + _$jscoverage['ui/editor.js'][686]++; + var oldRender = editor.render; + _$jscoverage['ui/editor.js'][687]++; + editor.render = (function (holder) { + _$jscoverage['ui/editor.js'][688]++; + if ((holder.constructor === String)) { + _$jscoverage['ui/editor.js'][689]++; + editor.key = holder; + _$jscoverage['ui/editor.js'][690]++; + instances[holder] = editor; + } + _$jscoverage['ui/editor.js'][692]++; + utils.domReady((function () { + _$jscoverage['ui/editor.js'][693]++; + (editor.langIsReady? renderUI(): editor.addListener("langReady", renderUI)); + _$jscoverage['ui/editor.js'][694]++; + function renderUI() { + _$jscoverage['ui/editor.js'][695]++; + editor.setOpt({labelMap: (editor.options.labelMap || editor.getLang("labelMap"))}); + _$jscoverage['ui/editor.js'][698]++; + new EditorUI(editor.options); + _$jscoverage['ui/editor.js'][699]++; + if (holder) { + _$jscoverage['ui/editor.js'][700]++; + if ((holder.constructor === String)) { + _$jscoverage['ui/editor.js'][701]++; + holder = document.getElementById(holder); + } + _$jscoverage['ui/editor.js'][703]++; + (holder && holder.getAttribute("name") && (editor.options.textarea = holder.getAttribute("name"))); + _$jscoverage['ui/editor.js'][704]++; + if ((holder && /script|textarea/gi.test(holder.tagName))) { + _$jscoverage['ui/editor.js'][705]++; + var newDiv = document.createElement("div"); + _$jscoverage['ui/editor.js'][706]++; + holder.parentNode.insertBefore(newDiv, holder); + _$jscoverage['ui/editor.js'][707]++; + var cont = (holder.value || holder.innerHTML); + _$jscoverage['ui/editor.js'][708]++; + editor.options.initialContent = (/^[\t\r\n ]*$/.test(cont)? editor.options.initialContent: cont.replace(/>[\n\r\t]+([ ]{4})+/g, ">").replace(/[\n\r\t]+([ ]{4})+[\n\r\t]+<")); + _$jscoverage['ui/editor.js'][712]++; + (holder.className && (newDiv.className = holder.className)); + _$jscoverage['ui/editor.js'][713]++; + (holder.style.cssText && (newDiv.style.cssText = holder.style.cssText)); + _$jscoverage['ui/editor.js'][714]++; + if (/textarea/i.test(holder.tagName)) { + _$jscoverage['ui/editor.js'][715]++; + editor.textarea = holder; + _$jscoverage['ui/editor.js'][716]++; + editor.textarea.style.display = "none"; + } + else { + _$jscoverage['ui/editor.js'][719]++; + holder.parentNode.removeChild(holder); + _$jscoverage['ui/editor.js'][720]++; + (holder.id && (newDiv.id = holder.id)); + } + _$jscoverage['ui/editor.js'][722]++; + holder = newDiv; + _$jscoverage['ui/editor.js'][723]++; + holder.innerHTML = ""; + } + } + _$jscoverage['ui/editor.js'][727]++; + domUtils.addClass(holder, ("edui-" + editor.options.theme)); + _$jscoverage['ui/editor.js'][728]++; + editor.ui.render(holder); + _$jscoverage['ui/editor.js'][729]++; + var opt = editor.options; + _$jscoverage['ui/editor.js'][731]++; + editor.container = editor.ui.getDom(); + _$jscoverage['ui/editor.js'][732]++; + var parents = domUtils.findParents(holder, true); + _$jscoverage['ui/editor.js'][733]++; + var displays = []; + _$jscoverage['ui/editor.js'][734]++; + for (var i = 0, ci; (ci = parents[i]); (i++)) { + _$jscoverage['ui/editor.js'][735]++; + displays[i] = ci.style.display; + _$jscoverage['ui/editor.js'][736]++; + ci.style.display = "block"; +} + _$jscoverage['ui/editor.js'][738]++; + if (opt.initialFrameWidth) { + _$jscoverage['ui/editor.js'][739]++; + opt.minFrameWidth = opt.initialFrameWidth; + } + else { + _$jscoverage['ui/editor.js'][741]++; + opt.minFrameWidth = (opt.initialFrameWidth = holder.offsetWidth); + } + _$jscoverage['ui/editor.js'][743]++; + if (opt.initialFrameHeight) { + _$jscoverage['ui/editor.js'][744]++; + opt.minFrameHeight = opt.initialFrameHeight; + } + else { + _$jscoverage['ui/editor.js'][746]++; + opt.initialFrameHeight = (opt.minFrameHeight = holder.offsetHeight); + } + _$jscoverage['ui/editor.js'][748]++; + for (var i = 0, ci = ci; (ci = parents[i]); (i++)) { + _$jscoverage['ui/editor.js'][749]++; + ci.style.display = displays[i]; +} + _$jscoverage['ui/editor.js'][753]++; + if (holder.style.height) { + _$jscoverage['ui/editor.js'][754]++; + holder.style.height = ""; + } + _$jscoverage['ui/editor.js'][756]++; + editor.container.style.width = (opt.initialFrameWidth + (/%$/.test(opt.initialFrameWidth)? "": "px")); + _$jscoverage['ui/editor.js'][757]++; + editor.container.style.zIndex = opt.zIndex; + _$jscoverage['ui/editor.js'][758]++; + oldRender.call(editor, editor.ui.getDom("iframeholder")); +} +})); +}); + _$jscoverage['ui/editor.js'][763]++; + return editor; +}); + _$jscoverage['ui/editor.js'][788]++; + UE.getEditor = (function (id, opt) { + _$jscoverage['ui/editor.js'][789]++; + var editor = instances[id]; + _$jscoverage['ui/editor.js'][790]++; + if ((! editor)) { + _$jscoverage['ui/editor.js'][791]++; + editor = (instances[id] = new (UE.ui.Editor)(opt)); + _$jscoverage['ui/editor.js'][792]++; + editor.render(id); + } + _$jscoverage['ui/editor.js'][794]++; + return editor; +}); + _$jscoverage['ui/editor.js'][798]++; + UE.delEditor = (function (id) { + _$jscoverage['ui/editor.js'][799]++; + var editor; + _$jscoverage['ui/editor.js'][800]++; + if ((editor = instances[id])) { + _$jscoverage['ui/editor.js'][801]++; + (editor.key && editor.destroy()); + _$jscoverage['ui/editor.js'][802]++; + (delete instances[id]); + } +}); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/editorui.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/editorui.js new file mode 100644 index 000000000..61249dfff --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/editorui.js @@ -0,0 +1,1302 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/editorui.js']) { + _$jscoverage['ui/editorui.js'] = []; + _$jscoverage['ui/editorui.js'][4] = 0; + _$jscoverage['ui/editorui.js'][5] = 0; + _$jscoverage['ui/editorui.js'][6] = 0; + _$jscoverage['ui/editorui.js'][7] = 0; + _$jscoverage['ui/editorui.js'][8] = 0; + _$jscoverage['ui/editorui.js'][10] = 0; + _$jscoverage['ui/editorui.js'][11] = 0; + _$jscoverage['ui/editorui.js'][12] = 0; + _$jscoverage['ui/editorui.js'][14] = 0; + _$jscoverage['ui/editorui.js'][15] = 0; + _$jscoverage['ui/editorui.js'][16] = 0; + _$jscoverage['ui/editorui.js'][17] = 0; + _$jscoverage['ui/editorui.js'][18] = 0; + _$jscoverage['ui/editorui.js'][20] = 0; + _$jscoverage['ui/editorui.js'][21] = 0; + _$jscoverage['ui/editorui.js'][23] = 0; + _$jscoverage['ui/editorui.js'][31] = 0; + _$jscoverage['ui/editorui.js'][34] = 0; + _$jscoverage['ui/editorui.js'][60] = 0; + _$jscoverage['ui/editorui.js'][68] = 0; + _$jscoverage['ui/editorui.js'][69] = 0; + _$jscoverage['ui/editorui.js'][70] = 0; + _$jscoverage['ui/editorui.js'][71] = 0; + _$jscoverage['ui/editorui.js'][72] = 0; + _$jscoverage['ui/editorui.js'][76] = 0; + _$jscoverage['ui/editorui.js'][81] = 0; + _$jscoverage['ui/editorui.js'][82] = 0; + _$jscoverage['ui/editorui.js'][83] = 0; + _$jscoverage['ui/editorui.js'][84] = 0; + _$jscoverage['ui/editorui.js'][85] = 0; + _$jscoverage['ui/editorui.js'][86] = 0; + _$jscoverage['ui/editorui.js'][88] = 0; + _$jscoverage['ui/editorui.js'][89] = 0; + _$jscoverage['ui/editorui.js'][90] = 0; + _$jscoverage['ui/editorui.js'][94] = 0; + _$jscoverage['ui/editorui.js'][100] = 0; + _$jscoverage['ui/editorui.js'][101] = 0; + _$jscoverage['ui/editorui.js'][106] = 0; + _$jscoverage['ui/editorui.js'][107] = 0; + _$jscoverage['ui/editorui.js'][111] = 0; + _$jscoverage['ui/editorui.js'][112] = 0; + _$jscoverage['ui/editorui.js'][113] = 0; + _$jscoverage['ui/editorui.js'][115] = 0; + _$jscoverage['ui/editorui.js'][119] = 0; + _$jscoverage['ui/editorui.js'][125] = 0; + _$jscoverage['ui/editorui.js'][127] = 0; + _$jscoverage['ui/editorui.js'][128] = 0; + _$jscoverage['ui/editorui.js'][129] = 0; + _$jscoverage['ui/editorui.js'][130] = 0; + _$jscoverage['ui/editorui.js'][131] = 0; + _$jscoverage['ui/editorui.js'][136] = 0; + _$jscoverage['ui/editorui.js'][139] = 0; + _$jscoverage['ui/editorui.js'][140] = 0; + _$jscoverage['ui/editorui.js'][141] = 0; + _$jscoverage['ui/editorui.js'][142] = 0; + _$jscoverage['ui/editorui.js'][144] = 0; + _$jscoverage['ui/editorui.js'][152] = 0; + _$jscoverage['ui/editorui.js'][153] = 0; + _$jscoverage['ui/editorui.js'][154] = 0; + _$jscoverage['ui/editorui.js'][155] = 0; + _$jscoverage['ui/editorui.js'][161] = 0; + _$jscoverage['ui/editorui.js'][164] = 0; + _$jscoverage['ui/editorui.js'][165] = 0; + _$jscoverage['ui/editorui.js'][166] = 0; + _$jscoverage['ui/editorui.js'][169] = 0; + _$jscoverage['ui/editorui.js'][172] = 0; + _$jscoverage['ui/editorui.js'][173] = 0; + _$jscoverage['ui/editorui.js'][174] = 0; + _$jscoverage['ui/editorui.js'][176] = 0; + _$jscoverage['ui/editorui.js'][182] = 0; + _$jscoverage['ui/editorui.js'][189] = 0; + _$jscoverage['ui/editorui.js'][190] = 0; + _$jscoverage['ui/editorui.js'][191] = 0; + _$jscoverage['ui/editorui.js'][193] = 0; + _$jscoverage['ui/editorui.js'][194] = 0; + _$jscoverage['ui/editorui.js'][196] = 0; + _$jscoverage['ui/editorui.js'][197] = 0; + _$jscoverage['ui/editorui.js'][198] = 0; + _$jscoverage['ui/editorui.js'][199] = 0; + _$jscoverage['ui/editorui.js'][201] = 0; + _$jscoverage['ui/editorui.js'][203] = 0; + _$jscoverage['ui/editorui.js'][204] = 0; + _$jscoverage['ui/editorui.js'][218] = 0; + _$jscoverage['ui/editorui.js'][226] = 0; + _$jscoverage['ui/editorui.js'][232] = 0; + _$jscoverage['ui/editorui.js'][235] = 0; + _$jscoverage['ui/editorui.js'][239] = 0; + _$jscoverage['ui/editorui.js'][240] = 0; + _$jscoverage['ui/editorui.js'][242] = 0; + _$jscoverage['ui/editorui.js'][243] = 0; + _$jscoverage['ui/editorui.js'][244] = 0; + _$jscoverage['ui/editorui.js'][245] = 0; + _$jscoverage['ui/editorui.js'][247] = 0; + _$jscoverage['ui/editorui.js'][249] = 0; + _$jscoverage['ui/editorui.js'][250] = 0; + _$jscoverage['ui/editorui.js'][251] = 0; + _$jscoverage['ui/editorui.js'][254] = 0; + _$jscoverage['ui/editorui.js'][256] = 0; + _$jscoverage['ui/editorui.js'][257] = 0; + _$jscoverage['ui/editorui.js'][264] = 0; + _$jscoverage['ui/editorui.js'][265] = 0; + _$jscoverage['ui/editorui.js'][267] = 0; + _$jscoverage['ui/editorui.js'][268] = 0; + _$jscoverage['ui/editorui.js'][270] = 0; + _$jscoverage['ui/editorui.js'][271] = 0; + _$jscoverage['ui/editorui.js'][272] = 0; + _$jscoverage['ui/editorui.js'][273] = 0; + _$jscoverage['ui/editorui.js'][278] = 0; + _$jscoverage['ui/editorui.js'][285] = 0; + _$jscoverage['ui/editorui.js'][286] = 0; + _$jscoverage['ui/editorui.js'][287] = 0; + _$jscoverage['ui/editorui.js'][291] = 0; + _$jscoverage['ui/editorui.js'][296] = 0; + _$jscoverage['ui/editorui.js'][297] = 0; + _$jscoverage['ui/editorui.js'][298] = 0; + _$jscoverage['ui/editorui.js'][299] = 0; + _$jscoverage['ui/editorui.js'][310] = 0; + _$jscoverage['ui/editorui.js'][318] = 0; + _$jscoverage['ui/editorui.js'][324] = 0; + _$jscoverage['ui/editorui.js'][325] = 0; + _$jscoverage['ui/editorui.js'][327] = 0; + _$jscoverage['ui/editorui.js'][328] = 0; + _$jscoverage['ui/editorui.js'][330] = 0; + _$jscoverage['ui/editorui.js'][333] = 0; + _$jscoverage['ui/editorui.js'][334] = 0; + _$jscoverage['ui/editorui.js'][335] = 0; + _$jscoverage['ui/editorui.js'][337] = 0; + _$jscoverage['ui/editorui.js'][338] = 0; + _$jscoverage['ui/editorui.js'][339] = 0; + _$jscoverage['ui/editorui.js'][344] = 0; + _$jscoverage['ui/editorui.js'][349] = 0; + _$jscoverage['ui/editorui.js'][353] = 0; + _$jscoverage['ui/editorui.js'][356] = 0; + _$jscoverage['ui/editorui.js'][362] = 0; + _$jscoverage['ui/editorui.js'][363] = 0; + _$jscoverage['ui/editorui.js'][364] = 0; + _$jscoverage['ui/editorui.js'][365] = 0; + _$jscoverage['ui/editorui.js'][369] = 0; + _$jscoverage['ui/editorui.js'][372] = 0; + _$jscoverage['ui/editorui.js'][373] = 0; + _$jscoverage['ui/editorui.js'][374] = 0; + _$jscoverage['ui/editorui.js'][375] = 0; + _$jscoverage['ui/editorui.js'][376] = 0; + _$jscoverage['ui/editorui.js'][377] = 0; + _$jscoverage['ui/editorui.js'][379] = 0; + _$jscoverage['ui/editorui.js'][380] = 0; + _$jscoverage['ui/editorui.js'][381] = 0; + _$jscoverage['ui/editorui.js'][382] = 0; + _$jscoverage['ui/editorui.js'][383] = 0; + _$jscoverage['ui/editorui.js'][386] = 0; + _$jscoverage['ui/editorui.js'][387] = 0; + _$jscoverage['ui/editorui.js'][393] = 0; + _$jscoverage['ui/editorui.js'][395] = 0; + _$jscoverage['ui/editorui.js'][397] = 0; + _$jscoverage['ui/editorui.js'][398] = 0; + _$jscoverage['ui/editorui.js'][399] = 0; + _$jscoverage['ui/editorui.js'][400] = 0; + _$jscoverage['ui/editorui.js'][401] = 0; + _$jscoverage['ui/editorui.js'][402] = 0; + _$jscoverage['ui/editorui.js'][403] = 0; + _$jscoverage['ui/editorui.js'][408] = 0; + _$jscoverage['ui/editorui.js'][414] = 0; + _$jscoverage['ui/editorui.js'][418] = 0; + _$jscoverage['ui/editorui.js'][421] = 0; + _$jscoverage['ui/editorui.js'][427] = 0; + _$jscoverage['ui/editorui.js'][428] = 0; + _$jscoverage['ui/editorui.js'][429] = 0; + _$jscoverage['ui/editorui.js'][430] = 0; + _$jscoverage['ui/editorui.js'][434] = 0; + _$jscoverage['ui/editorui.js'][437] = 0; + _$jscoverage['ui/editorui.js'][438] = 0; + _$jscoverage['ui/editorui.js'][439] = 0; + _$jscoverage['ui/editorui.js'][440] = 0; + _$jscoverage['ui/editorui.js'][441] = 0; + _$jscoverage['ui/editorui.js'][442] = 0; + _$jscoverage['ui/editorui.js'][444] = 0; + _$jscoverage['ui/editorui.js'][445] = 0; + _$jscoverage['ui/editorui.js'][447] = 0; + _$jscoverage['ui/editorui.js'][448] = 0; + _$jscoverage['ui/editorui.js'][454] = 0; + _$jscoverage['ui/editorui.js'][457] = 0; + _$jscoverage['ui/editorui.js'][458] = 0; + _$jscoverage['ui/editorui.js'][459] = 0; + _$jscoverage['ui/editorui.js'][460] = 0; + _$jscoverage['ui/editorui.js'][461] = 0; + _$jscoverage['ui/editorui.js'][462] = 0; + _$jscoverage['ui/editorui.js'][463] = 0; + _$jscoverage['ui/editorui.js'][464] = 0; + _$jscoverage['ui/editorui.js'][469] = 0; + _$jscoverage['ui/editorui.js'][474] = 0; + _$jscoverage['ui/editorui.js'][480] = 0; + _$jscoverage['ui/editorui.js'][483] = 0; + _$jscoverage['ui/editorui.js'][487] = 0; + _$jscoverage['ui/editorui.js'][488] = 0; + _$jscoverage['ui/editorui.js'][489] = 0; + _$jscoverage['ui/editorui.js'][490] = 0; + _$jscoverage['ui/editorui.js'][491] = 0; + _$jscoverage['ui/editorui.js'][492] = 0; + _$jscoverage['ui/editorui.js'][494] = 0; + _$jscoverage['ui/editorui.js'][495] = 0; + _$jscoverage['ui/editorui.js'][500] = 0; + _$jscoverage['ui/editorui.js'][503] = 0; + _$jscoverage['ui/editorui.js'][504] = 0; + _$jscoverage['ui/editorui.js'][505] = 0; + _$jscoverage['ui/editorui.js'][506] = 0; + _$jscoverage['ui/editorui.js'][507] = 0; + _$jscoverage['ui/editorui.js'][508] = 0; + _$jscoverage['ui/editorui.js'][509] = 0; + _$jscoverage['ui/editorui.js'][514] = 0; + _$jscoverage['ui/editorui.js'][518] = 0; + _$jscoverage['ui/editorui.js'][525] = 0; + _$jscoverage['ui/editorui.js'][528] = 0; + _$jscoverage['ui/editorui.js'][531] = 0; + _$jscoverage['ui/editorui.js'][532] = 0; + _$jscoverage['ui/editorui.js'][533] = 0; + _$jscoverage['ui/editorui.js'][534] = 0; + _$jscoverage['ui/editorui.js'][535] = 0; + _$jscoverage['ui/editorui.js'][536] = 0; + _$jscoverage['ui/editorui.js'][538] = 0; + _$jscoverage['ui/editorui.js'][539] = 0; + _$jscoverage['ui/editorui.js'][540] = 0; + _$jscoverage['ui/editorui.js'][541] = 0; + _$jscoverage['ui/editorui.js'][542] = 0; + _$jscoverage['ui/editorui.js'][544] = 0; + _$jscoverage['ui/editorui.js'][550] = 0; + _$jscoverage['ui/editorui.js'][555] = 0; + _$jscoverage['ui/editorui.js'][556] = 0; + _$jscoverage['ui/editorui.js'][558] = 0; + _$jscoverage['ui/editorui.js'][559] = 0; + _$jscoverage['ui/editorui.js'][560] = 0; + _$jscoverage['ui/editorui.js'][561] = 0; + _$jscoverage['ui/editorui.js'][562] = 0; + _$jscoverage['ui/editorui.js'][563] = 0; + _$jscoverage['ui/editorui.js'][564] = 0; + _$jscoverage['ui/editorui.js'][565] = 0; + _$jscoverage['ui/editorui.js'][566] = 0; + _$jscoverage['ui/editorui.js'][567] = 0; + _$jscoverage['ui/editorui.js'][572] = 0; + _$jscoverage['ui/editorui.js'][580] = 0; + _$jscoverage['ui/editorui.js'][587] = 0; + _$jscoverage['ui/editorui.js'][590] = 0; + _$jscoverage['ui/editorui.js'][593] = 0; + _$jscoverage['ui/editorui.js'][594] = 0; + _$jscoverage['ui/editorui.js'][595] = 0; + _$jscoverage['ui/editorui.js'][598] = 0; + _$jscoverage['ui/editorui.js'][601] = 0; + _$jscoverage['ui/editorui.js'][602] = 0; + _$jscoverage['ui/editorui.js'][603] = 0; + _$jscoverage['ui/editorui.js'][604] = 0; + _$jscoverage['ui/editorui.js'][605] = 0; + _$jscoverage['ui/editorui.js'][606] = 0; + _$jscoverage['ui/editorui.js'][608] = 0; + _$jscoverage['ui/editorui.js'][609] = 0; + _$jscoverage['ui/editorui.js'][610] = 0; + _$jscoverage['ui/editorui.js'][611] = 0; + _$jscoverage['ui/editorui.js'][612] = 0; + _$jscoverage['ui/editorui.js'][614] = 0; + _$jscoverage['ui/editorui.js'][620] = 0; + _$jscoverage['ui/editorui.js'][622] = 0; + _$jscoverage['ui/editorui.js'][623] = 0; + _$jscoverage['ui/editorui.js'][624] = 0; + _$jscoverage['ui/editorui.js'][629] = 0; + _$jscoverage['ui/editorui.js'][632] = 0; + _$jscoverage['ui/editorui.js'][635] = 0; + _$jscoverage['ui/editorui.js'][636] = 0; + _$jscoverage['ui/editorui.js'][637] = 0; + _$jscoverage['ui/editorui.js'][639] = 0; + _$jscoverage['ui/editorui.js'][642] = 0; + _$jscoverage['ui/editorui.js'][643] = 0; + _$jscoverage['ui/editorui.js'][644] = 0; + _$jscoverage['ui/editorui.js'][645] = 0; + _$jscoverage['ui/editorui.js'][646] = 0; + _$jscoverage['ui/editorui.js'][652] = 0; + _$jscoverage['ui/editorui.js'][656] = 0; + _$jscoverage['ui/editorui.js'][662] = 0; + _$jscoverage['ui/editorui.js'][663] = 0; + _$jscoverage['ui/editorui.js'][666] = 0; + _$jscoverage['ui/editorui.js'][667] = 0; + _$jscoverage['ui/editorui.js'][668] = 0; + _$jscoverage['ui/editorui.js'][669] = 0; + _$jscoverage['ui/editorui.js'][670] = 0; + _$jscoverage['ui/editorui.js'][672] = 0; + _$jscoverage['ui/editorui.js'][673] = 0; + _$jscoverage['ui/editorui.js'][674] = 0; + _$jscoverage['ui/editorui.js'][675] = 0; + _$jscoverage['ui/editorui.js'][678] = 0; + _$jscoverage['ui/editorui.js'][681] = 0; + _$jscoverage['ui/editorui.js'][682] = 0; + _$jscoverage['ui/editorui.js'][683] = 0; + _$jscoverage['ui/editorui.js'][684] = 0; + _$jscoverage['ui/editorui.js'][685] = 0; + _$jscoverage['ui/editorui.js'][686] = 0; + _$jscoverage['ui/editorui.js'][687] = 0; + _$jscoverage['ui/editorui.js'][688] = 0; + _$jscoverage['ui/editorui.js'][693] = 0; + _$jscoverage['ui/editorui.js'][697] = 0; + _$jscoverage['ui/editorui.js'][703] = 0; + _$jscoverage['ui/editorui.js'][704] = 0; + _$jscoverage['ui/editorui.js'][707] = 0; + _$jscoverage['ui/editorui.js'][708] = 0; + _$jscoverage['ui/editorui.js'][709] = 0; + _$jscoverage['ui/editorui.js'][710] = 0; + _$jscoverage['ui/editorui.js'][711] = 0; + _$jscoverage['ui/editorui.js'][713] = 0; + _$jscoverage['ui/editorui.js'][714] = 0; + _$jscoverage['ui/editorui.js'][715] = 0; + _$jscoverage['ui/editorui.js'][716] = 0; + _$jscoverage['ui/editorui.js'][719] = 0; + _$jscoverage['ui/editorui.js'][724] = 0; + _$jscoverage['ui/editorui.js'][725] = 0; + _$jscoverage['ui/editorui.js'][726] = 0; + _$jscoverage['ui/editorui.js'][727] = 0; + _$jscoverage['ui/editorui.js'][728] = 0; + _$jscoverage['ui/editorui.js'][730] = 0; + _$jscoverage['ui/editorui.js'][732] = 0; + _$jscoverage['ui/editorui.js'][733] = 0; + _$jscoverage['ui/editorui.js'][740] = 0; + _$jscoverage['ui/editorui.js'][746] = 0; + _$jscoverage['ui/editorui.js'][747] = 0; + _$jscoverage['ui/editorui.js'][750] = 0; + _$jscoverage['ui/editorui.js'][751] = 0; + _$jscoverage['ui/editorui.js'][752] = 0; + _$jscoverage['ui/editorui.js'][753] = 0; + _$jscoverage['ui/editorui.js'][754] = 0; + _$jscoverage['ui/editorui.js'][756] = 0; + _$jscoverage['ui/editorui.js'][757] = 0; + _$jscoverage['ui/editorui.js'][758] = 0; + _$jscoverage['ui/editorui.js'][759] = 0; + _$jscoverage['ui/editorui.js'][762] = 0; + _$jscoverage['ui/editorui.js'][767] = 0; + _$jscoverage['ui/editorui.js'][768] = 0; + _$jscoverage['ui/editorui.js'][769] = 0; + _$jscoverage['ui/editorui.js'][774] = 0; + _$jscoverage['ui/editorui.js'][775] = 0; + _$jscoverage['ui/editorui.js'][777] = 0; + _$jscoverage['ui/editorui.js'][780] = 0; + _$jscoverage['ui/editorui.js'][781] = 0; + _$jscoverage['ui/editorui.js'][782] = 0; + _$jscoverage['ui/editorui.js'][783] = 0; + _$jscoverage['ui/editorui.js'][784] = 0; + _$jscoverage['ui/editorui.js'][786] = 0; + _$jscoverage['ui/editorui.js'][790] = 0; + _$jscoverage['ui/editorui.js'][791] = 0; + _$jscoverage['ui/editorui.js'][792] = 0; + _$jscoverage['ui/editorui.js'][798] = 0; + _$jscoverage['ui/editorui.js'][800] = 0; + _$jscoverage['ui/editorui.js'][801] = 0; + _$jscoverage['ui/editorui.js'][803] = 0; + _$jscoverage['ui/editorui.js'][806] = 0; + _$jscoverage['ui/editorui.js'][807] = 0; + _$jscoverage['ui/editorui.js'][812] = 0; + _$jscoverage['ui/editorui.js'][815] = 0; + _$jscoverage['ui/editorui.js'][816] = 0; + _$jscoverage['ui/editorui.js'][817] = 0; + _$jscoverage['ui/editorui.js'][819] = 0; +} +_$jscoverage['ui/editorui.js'].source = ["//ui跟编辑器的适配層","//那个按钮弹出是dialog,是下拉筐等都是在这个js中配置","//自己写的ui也要在这里配置,放到baidu.editor.ui下边,当编辑器实例化的时候会根据ueditor.config中的toolbars找到相应的进行实例化","(function () {"," var utils = baidu.editor.utils;"," var editorui = baidu.editor.ui;"," var _Dialog = editorui.Dialog;"," editorui.buttons = {};",""," editorui.Dialog = function (options) {"," var dialog = new _Dialog(options);"," dialog.addListener('hide', function () {",""," if (dialog.editor) {"," var editor = dialog.editor;"," try {"," if (browser.gecko) {"," var y = editor.window.scrollY,"," x = editor.window.scrollX;"," editor.body.focus();"," editor.window.scrollTo(x, y);"," } else {"," editor.focus();"," }","",""," } catch (ex) {"," }"," }"," });"," return dialog;"," };",""," var iframeUrlMap = {"," 'anchor':'~/dialogs/anchor/anchor.html',"," 'insertimage':'~/dialogs/image/image.html',"," 'link':'~/dialogs/link/link.html',"," 'spechars':'~/dialogs/spechars/spechars.html',"," 'searchreplace':'~/dialogs/searchreplace/searchreplace.html',"," 'map':'~/dialogs/map/map.html',"," 'gmap':'~/dialogs/gmap/gmap.html',"," 'insertvideo':'~/dialogs/video/video.html',"," 'help':'~/dialogs/help/help.html',"," //'highlightcode':'~/dialogs/highlightcode/highlightcode.html',"," 'emotion':'~/dialogs/emotion/emotion.html',"," 'wordimage':'~/dialogs/wordimage/wordimage.html',"," 'attachment':'~/dialogs/attachment/attachment.html',"," 'insertframe':'~/dialogs/insertframe/insertframe.html',"," 'edittip':'~/dialogs/table/edittip.html',"," 'edittable':'~/dialogs/table/edittable.html',"," 'edittd':'~/dialogs/table/edittd.html',"," 'webapp':'~/dialogs/webapp/webapp.html',"," 'snapscreen':'~/dialogs/snapscreen/snapscreen.html',"," 'scrawl':'~/dialogs/scrawl/scrawl.html',"," 'music':'~/dialogs/music/music.html',"," 'template':'~/dialogs/template/template.html',"," 'background':'~/dialogs/background/background.html'"," };"," //为工具栏添加按钮,以下都是统一的按钮触发命令,所以写在一起"," var btnCmds = ['undo', 'redo', 'formatmatch',"," 'bold', 'italic', 'underline', 'fontborder', 'touppercase', 'tolowercase',"," 'strikethrough', 'subscript', 'superscript', 'source', 'indent', 'outdent',"," 'blockquote', 'pasteplain', 'pagebreak',"," 'selectall', 'print', 'preview', 'horizontal', 'removeformat', 'time', 'date', 'unlink',"," 'insertparagraphbeforetable', 'insertrow', 'insertcol', 'mergeright', 'mergedown', 'deleterow',"," 'deletecol', 'splittorows', 'splittocols', 'splittocells', 'mergecells', 'deletetable'];",""," for (var i = 0, ci; ci = btnCmds[i++];) {"," ci = ci.toLowerCase();"," editorui[ci] = function (cmd) {"," return function (editor) {"," var ui = new editorui.Button({"," className:'edui-for-' + cmd,"," title:editor.options.labelMap[cmd] || editor.getLang(\"labelMap.\" + cmd) || '',"," onclick:function () {"," editor.execCommand(cmd);"," },"," theme:editor.options.theme,"," showText:false"," });"," editorui.buttons[cmd] = ui;"," editor.addListener('selectionchange', function (type, causeByUi, uiReady) {"," var state = editor.queryCommandState(cmd);"," if (state == -1) {"," ui.setDisabled(true);"," ui.setChecked(false);"," } else {"," if (!uiReady) {"," ui.setDisabled(false);"," ui.setChecked(state);"," }"," }"," });"," return ui;"," };"," }(ci);"," }",""," //清除文档"," editorui.cleardoc = function (editor) {"," var ui = new editorui.Button({"," className:'edui-for-cleardoc',"," title:editor.options.labelMap.cleardoc || editor.getLang(\"labelMap.cleardoc\") || '',"," theme:editor.options.theme,"," onclick:function () {"," if (confirm(editor.getLang(\"confirmClear\"))) {"," editor.execCommand('cleardoc');"," }"," }"," });"," editorui.buttons[\"cleardoc\"] = ui;"," editor.addListener('selectionchange', function () {"," ui.setDisabled(editor.queryCommandState('cleardoc') == -1);"," });"," return ui;"," };",""," //排版,图片排版,文字方向"," var typeset = {"," 'justify':['left', 'right', 'center', 'justify'],"," 'imagefloat':['none', 'left', 'center', 'right'],"," 'directionality':['ltr', 'rtl']"," };",""," for (var p in typeset) {",""," (function (cmd, val) {"," for (var i = 0, ci; ci = val[i++];) {"," (function (cmd2) {"," editorui[cmd.replace('float', '') + cmd2] = function (editor) {"," var ui = new editorui.Button({"," className:'edui-for-' + cmd.replace('float', '') + cmd2,"," title:editor.options.labelMap[cmd.replace('float', '') + cmd2] || editor.getLang(\"labelMap.\" + cmd.replace('float', '') + cmd2) || '',"," theme:editor.options.theme,"," onclick:function () {"," editor.execCommand(cmd, cmd2);"," }"," });"," editorui.buttons[cmd] = ui;"," editor.addListener('selectionchange', function (type, causeByUi, uiReady) {"," ui.setDisabled(editor.queryCommandState(cmd) == -1);"," ui.setChecked(editor.queryCommandValue(cmd) == cmd2 && !uiReady);"," });"," return ui;"," };"," })(ci)"," }"," })(p, typeset[p])"," }",""," //字体颜色和背景颜色"," for (var i = 0, ci; ci = ['backcolor', 'forecolor'][i++];) {"," editorui[ci] = function (cmd) {"," return function (editor) {"," var ui = new editorui.ColorButton({"," className:'edui-for-' + cmd,"," color:'default',"," title:editor.options.labelMap[cmd] || editor.getLang(\"labelMap.\" + cmd) || '',"," editor:editor,"," onpickcolor:function (t, color) {"," editor.execCommand(cmd, color);"," },"," onpicknocolor:function () {"," editor.execCommand(cmd, 'default');"," this.setColor('transparent');"," this.color = 'default';"," },"," onbuttonclick:function () {"," editor.execCommand(cmd, this.color);"," }"," });"," editorui.buttons[cmd] = ui;"," editor.addListener('selectionchange', function () {"," ui.setDisabled(editor.queryCommandState(cmd) == -1);"," });"," return ui;"," };"," }(ci);"," }","",""," var dialogBtns = {"," noOk:['searchreplace', 'help', 'spechars', 'webapp'],"," ok:['attachment', 'anchor', 'link', 'insertimage', 'map', 'gmap', 'insertframe', 'wordimage',"," 'insertvideo', 'insertframe', 'edittip', 'edittable', 'edittd', 'scrawl', 'template', 'music', 'background']",""," };",""," for (var p in dialogBtns) {"," (function (type, vals) {"," for (var i = 0, ci; ci = vals[i++];) {"," //todo opera下存在问题"," if (browser.opera && ci === \"searchreplace\") {"," continue;"," }"," (function (cmd) {"," editorui[cmd] = function (editor, iframeUrl, title) {"," iframeUrl = iframeUrl || (editor.options.iframeUrlMap || {})[cmd] || iframeUrlMap[cmd];"," title = editor.options.labelMap[cmd] || editor.getLang(\"labelMap.\" + cmd) || '';",""," var dialog;"," //没有iframeUrl不创建dialog"," if (iframeUrl) {"," dialog = new editorui.Dialog(utils.extend({"," iframeUrl:editor.ui.mapUrl(iframeUrl),"," editor:editor,"," className:'edui-for-' + cmd,"," title:title,"," holdScroll: cmd === 'insertimage',"," closeDialog:editor.getLang(\"closeDialog\")"," }, type == 'ok' ? {"," buttons:["," {"," className:'edui-okbutton',"," label:editor.getLang(\"ok\"),"," editor:editor,"," onclick:function () {"," dialog.close(true);"," }"," },"," {"," className:'edui-cancelbutton',"," label:editor.getLang(\"cancel\"),"," editor:editor,"," onclick:function () {"," dialog.close(false);"," }"," }"," ]"," } : {}));",""," editor.ui._dialogs[cmd + \"Dialog\"] = dialog;"," }",""," var ui = new editorui.Button({"," className:'edui-for-' + cmd,"," title:title,"," onclick:function () {"," if (dialog) {"," switch (cmd) {"," case \"wordimage\":"," editor.execCommand(\"wordimage\", \"word_img\");"," if (editor.word_img) {"," dialog.render();"," dialog.open();"," }"," break;"," case \"scrawl\":"," if (editor.queryCommandState(\"scrawl\") != -1) {"," dialog.render();"," dialog.open();"," }",""," break;"," default:"," dialog.render();"," dialog.open();"," }"," }"," },"," theme:editor.options.theme,"," disabled:cmd == 'scrawl' && editor.queryCommandState(\"scrawl\") == -1"," });"," editorui.buttons[cmd] = ui;"," editor.addListener('selectionchange', function () {"," //只存在于右键菜单而无工具栏按钮的ui不需要检测状态"," var unNeedCheckState = {'edittable':1};"," if (cmd in unNeedCheckState)return;",""," var state = editor.queryCommandState(cmd);"," if (ui.getDom()) {"," ui.setDisabled(state == -1);"," ui.setChecked(state);"," }",""," });",""," return ui;"," };"," })(ci.toLowerCase())"," }"," })(p, dialogBtns[p])"," }",""," editorui.snapscreen = function (editor, iframeUrl, title) {"," title = editor.options.labelMap['snapscreen'] || editor.getLang(\"labelMap.snapscreen\") || '';"," var ui = new editorui.Button({"," className:'edui-for-snapscreen',"," title:title,"," onclick:function () {"," editor.execCommand(\"snapscreen\");"," },"," theme:editor.options.theme",""," });"," editorui.buttons['snapscreen'] = ui;"," iframeUrl = iframeUrl || (editor.options.iframeUrlMap || {})[\"snapscreen\"] || iframeUrlMap[\"snapscreen\"];"," if (iframeUrl) {"," var dialog = new editorui.Dialog({"," iframeUrl:editor.ui.mapUrl(iframeUrl),"," editor:editor,"," className:'edui-for-snapscreen',"," title:title,"," buttons:["," {"," className:'edui-okbutton',"," label:editor.getLang(\"ok\"),"," editor:editor,"," onclick:function () {"," dialog.close(true);"," }"," },"," {"," className:'edui-cancelbutton',"," label:editor.getLang(\"cancel\"),"," editor:editor,"," onclick:function () {"," dialog.close(false);"," }"," }"," ]",""," });"," dialog.render();"," editor.ui._dialogs[\"snapscreenDialog\"] = dialog;"," }"," editor.addListener('selectionchange', function () {"," ui.setDisabled(editor.queryCommandState('snapscreen') == -1);"," });"," return ui;"," };",""," editorui.insertcode = function (editor, list, title) {"," list = editor.options['insertcode'] || [];"," title = editor.options.labelMap['insertcode'] || editor.getLang(\"labelMap.insertcode\") || '';"," // if (!list.length) return;"," var items = [];"," utils.each(list,function(key,val){"," items.push({"," label:key,"," value:val,"," theme:editor.options.theme,"," renderLabelHtml:function () {"," return '<div class=\"edui-label %%-label\" >' + (this.label || '') + '</div>';"," }"," });"," });",""," var ui = new editorui.Combox({"," editor:editor,"," items:items,"," onselect:function (t, index) {"," editor.execCommand('insertcode', this.items[index].value);"," },"," onbuttonclick:function () {"," this.showPopup();"," },"," title:title,"," initValue:title,"," className:'edui-for-insertcode',"," indexByValue:function (value) {"," if (value) {"," for (var i = 0, ci; ci = this.items[i]; i++) {"," if (ci.value.indexOf(value) != -1)"," return i;"," }"," }",""," return -1;"," }"," });"," editorui.buttons['insertcode'] = ui;"," editor.addListener('selectionchange', function (type, causeByUi, uiReady) {"," if (!uiReady) {"," var state = editor.queryCommandState('insertcode');"," if (state == -1) {"," ui.setDisabled(true);"," } else {"," ui.setDisabled(false);"," var value = editor.queryCommandValue('insertcode');"," if(!value){"," ui.setValue(title);"," return;"," }"," //trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号"," value && (value = value.replace(/['\"]/g, '').split(',')[0]);"," ui.setValue(value);",""," }"," }",""," });"," return ui;"," };"," editorui.fontfamily = function (editor, list, title) {",""," list = editor.options['fontfamily'] || [];"," title = editor.options.labelMap['fontfamily'] || editor.getLang(\"labelMap.fontfamily\") || '';"," if (!list.length) return;"," for (var i = 0, ci, items = []; ci = list[i]; i++) {"," var langLabel = editor.getLang('fontfamily')[ci.name] || \"\";"," (function (key, val) {"," items.push({"," label:key,"," value:val,"," theme:editor.options.theme,"," renderLabelHtml:function () {"," return '<div class=\"edui-label %%-label\" style=\"font-family:' +"," utils.unhtml(this.value) + '\">' + (this.label || '') + '</div>';"," }"," });"," })(ci.label || langLabel, ci.val)"," }"," var ui = new editorui.Combox({"," editor:editor,"," items:items,"," onselect:function (t, index) {"," editor.execCommand('FontFamily', this.items[index].value);"," },"," onbuttonclick:function () {"," this.showPopup();"," },"," title:title,"," initValue:title,"," className:'edui-for-fontfamily',"," indexByValue:function (value) {"," if (value) {"," for (var i = 0, ci; ci = this.items[i]; i++) {"," if (ci.value.indexOf(value) != -1)"," return i;"," }"," }",""," return -1;"," }"," });"," editorui.buttons['fontfamily'] = ui;"," editor.addListener('selectionchange', function (type, causeByUi, uiReady) {"," if (!uiReady) {"," var state = editor.queryCommandState('FontFamily');"," if (state == -1) {"," ui.setDisabled(true);"," } else {"," ui.setDisabled(false);"," var value = editor.queryCommandValue('FontFamily');"," //trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号"," value && (value = value.replace(/['\"]/g, '').split(',')[0]);"," ui.setValue(value);",""," }"," }",""," });"," return ui;"," };",""," editorui.fontsize = function (editor, list, title) {"," title = editor.options.labelMap['fontsize'] || editor.getLang(\"labelMap.fontsize\") || '';"," list = list || editor.options['fontsize'] || [];"," if (!list.length) return;"," var items = [];"," for (var i = 0; i < list.length; i++) {"," var size = list[i] + 'px';"," items.push({"," label:size,"," value:size,"," theme:editor.options.theme,"," renderLabelHtml:function () {"," return '<div class=\"edui-label %%-label\" style=\"line-height:1;font-size:' +"," this.value + '\">' + (this.label || '') + '</div>';"," }"," });"," }"," var ui = new editorui.Combox({"," editor:editor,"," items:items,"," title:title,"," initValue:title,"," onselect:function (t, index) {"," editor.execCommand('FontSize', this.items[index].value);"," },"," onbuttonclick:function () {"," this.showPopup();"," },"," className:'edui-for-fontsize'"," });"," editorui.buttons['fontsize'] = ui;"," editor.addListener('selectionchange', function (type, causeByUi, uiReady) {"," if (!uiReady) {"," var state = editor.queryCommandState('FontSize');"," if (state == -1) {"," ui.setDisabled(true);"," } else {"," ui.setDisabled(false);"," ui.setValue(editor.queryCommandValue('FontSize'));"," }"," }",""," });"," return ui;"," };",""," editorui.paragraph = function (editor, list, title) {"," title = editor.options.labelMap['paragraph'] || editor.getLang(\"labelMap.paragraph\") || '';"," list = editor.options['paragraph'] || [];"," if (utils.isEmptyObject(list)) return;"," var items = [];"," for (var i in list) {"," items.push({"," value:i,"," label:list[i] || editor.getLang(\"paragraph\")[i],"," theme:editor.options.theme,"," renderLabelHtml:function () {"," return '<div class=\"edui-label %%-label\"><span class=\"edui-for-' + this.value + '\">' + (this.label || '') + '</span></div>';"," }"," })"," }"," var ui = new editorui.Combox({"," editor:editor,"," items:items,"," title:title,"," initValue:title,"," className:'edui-for-paragraph',"," onselect:function (t, index) {"," editor.execCommand('Paragraph', this.items[index].value);"," },"," onbuttonclick:function () {"," this.showPopup();"," }"," });"," editorui.buttons['paragraph'] = ui;"," editor.addListener('selectionchange', function (type, causeByUi, uiReady) {"," if (!uiReady) {"," var state = editor.queryCommandState('Paragraph');"," if (state == -1) {"," ui.setDisabled(true);"," } else {"," ui.setDisabled(false);"," var value = editor.queryCommandValue('Paragraph');"," var index = ui.indexByValue(value);"," if (index != -1) {"," ui.setValue(value);"," } else {"," ui.setValue(ui.initValue);"," }"," }"," }",""," });"," return ui;"," };","",""," //自定义标题"," editorui.customstyle = function (editor) {"," var list = editor.options['customstyle'] || [],"," title = editor.options.labelMap['customstyle'] || editor.getLang(\"labelMap.customstyle\") || '';"," if (!list.length)return;"," var langCs = editor.getLang('customstyle');"," for (var i = 0, items = [], t; t = list[i++];) {"," (function (t) {"," var ck = {};"," ck.label = t.label ? t.label : langCs[t.name];"," ck.style = t.style;"," ck.className = t.className;"," ck.tag = t.tag;"," items.push({"," label:ck.label,"," value:ck,"," theme:editor.options.theme,"," renderLabelHtml:function () {"," return '<div class=\"edui-label %%-label\">' + '<' + ck.tag + ' ' + (ck.className ? ' class=\"' + ck.className + '\"' : \"\")"," + (ck.style ? ' style=\"' + ck.style + '\"' : \"\") + '>' + ck.label + \"<\\/\" + ck.tag + \">\""," + '</div>';"," }"," });"," })(t);"," }",""," var ui = new editorui.Combox({"," editor:editor,"," items:items,"," title:title,"," initValue:title,"," className:'edui-for-customstyle',"," onselect:function (t, index) {"," editor.execCommand('customstyle', this.items[index].value);"," },"," onbuttonclick:function () {"," this.showPopup();"," },"," indexByValue:function (value) {"," for (var i = 0, ti; ti = this.items[i++];) {"," if (ti.label == value) {"," return i - 1"," }"," }"," return -1;"," }"," });"," editorui.buttons['customstyle'] = ui;"," editor.addListener('selectionchange', function (type, causeByUi, uiReady) {"," if (!uiReady) {"," var state = editor.queryCommandState('customstyle');"," if (state == -1) {"," ui.setDisabled(true);"," } else {"," ui.setDisabled(false);"," var value = editor.queryCommandValue('customstyle');"," var index = ui.indexByValue(value);"," if (index != -1) {"," ui.setValue(value);"," } else {"," ui.setValue(ui.initValue);"," }"," }"," }",""," });"," return ui;"," };"," editorui.inserttable = function (editor, iframeUrl, title) {"," title = editor.options.labelMap['inserttable'] || editor.getLang(\"labelMap.inserttable\") || '';"," var ui = new editorui.TableButton({"," editor:editor,"," title:title,"," className:'edui-for-inserttable',"," onpicktable:function (t, numCols, numRows) {"," editor.execCommand('InsertTable', {numRows:numRows, numCols:numCols, border:1});"," },"," onbuttonclick:function () {"," this.showPopup();"," }"," });"," editorui.buttons['inserttable'] = ui;"," editor.addListener('selectionchange', function () {"," ui.setDisabled(editor.queryCommandState('inserttable') == -1);"," });"," return ui;"," };",""," editorui.lineheight = function (editor) {"," var val = editor.options.lineheight || [];"," if (!val.length)return;"," for (var i = 0, ci, items = []; ci = val[i++];) {"," items.push({"," //todo:写死了"," label:ci,"," value:ci,"," theme:editor.options.theme,"," onclick:function () {"," editor.execCommand(\"lineheight\", this.value);"," }"," })"," }"," var ui = new editorui.MenuButton({"," editor:editor,"," className:'edui-for-lineheight',"," title:editor.options.labelMap['lineheight'] || editor.getLang(\"labelMap.lineheight\") || '',"," items:items,"," onbuttonclick:function () {"," var value = editor.queryCommandValue('LineHeight') || this.value;"," editor.execCommand(\"LineHeight\", value);"," }"," });"," editorui.buttons['lineheight'] = ui;"," editor.addListener('selectionchange', function () {"," var state = editor.queryCommandState('LineHeight');"," if (state == -1) {"," ui.setDisabled(true);"," } else {"," ui.setDisabled(false);"," var value = editor.queryCommandValue('LineHeight');"," value && ui.setValue((value + '').replace(/cm/, ''));"," ui.setChecked(state)"," }"," });"," return ui;"," };",""," var rowspacings = ['top', 'bottom'];"," for (var r = 0, ri; ri = rowspacings[r++];) {"," (function (cmd) {"," editorui['rowspacing' + cmd] = function (editor) {"," var val = editor.options['rowspacing' + cmd] || [];"," if (!val.length) return null;"," for (var i = 0, ci, items = []; ci = val[i++];) {"," items.push({"," label:ci,"," value:ci,"," theme:editor.options.theme,"," onclick:function () {"," editor.execCommand(\"rowspacing\", this.value, cmd);"," }"," })"," }"," var ui = new editorui.MenuButton({"," editor:editor,"," className:'edui-for-rowspacing' + cmd,"," title:editor.options.labelMap['rowspacing' + cmd] || editor.getLang(\"labelMap.rowspacing\" + cmd) || '',"," items:items,"," onbuttonclick:function () {"," var value = editor.queryCommandValue('rowspacing', cmd) || this.value;"," editor.execCommand(\"rowspacing\", value, cmd);"," }"," });"," editorui.buttons[cmd] = ui;"," editor.addListener('selectionchange', function () {"," var state = editor.queryCommandState('rowspacing', cmd);"," if (state == -1) {"," ui.setDisabled(true);"," } else {"," ui.setDisabled(false);"," var value = editor.queryCommandValue('rowspacing', cmd);"," value && ui.setValue((value + '').replace(/%/, ''));"," ui.setChecked(state)"," }"," });"," return ui;"," }"," })(ri)"," }"," //有序,无序列表"," var lists = ['insertorderedlist', 'insertunorderedlist'];"," for (var l = 0, cl; cl = lists[l++];) {"," (function (cmd) {"," editorui[cmd] = function (editor) {"," var vals = editor.options[cmd],"," _onMenuClick = function () {"," editor.execCommand(cmd, this.value);"," }, items = [];"," for (var i in vals) {"," items.push({"," label:vals[i] || editor.getLang()[cmd][i] || \"\","," value:i,"," theme:editor.options.theme,"," onclick:_onMenuClick"," })"," }"," var ui = new editorui.MenuButton({"," editor:editor,"," className:'edui-for-' + cmd,"," title:editor.getLang(\"labelMap.\" + cmd) || '',"," 'items':items,"," onbuttonclick:function () {"," var value = editor.queryCommandValue(cmd) || this.value;"," editor.execCommand(cmd, value);"," }"," });"," editorui.buttons[cmd] = ui;"," editor.addListener('selectionchange', function () {"," var state = editor.queryCommandState(cmd);"," if (state == -1) {"," ui.setDisabled(true);"," } else {"," ui.setDisabled(false);"," var value = editor.queryCommandValue(cmd);"," ui.setValue(value);"," ui.setChecked(state)"," }"," });"," return ui;"," };"," })(cl)"," }",""," editorui.fullscreen = function (editor, title) {"," title = editor.options.labelMap['fullscreen'] || editor.getLang(\"labelMap.fullscreen\") || '';"," var ui = new editorui.Button({"," className:'edui-for-fullscreen',"," title:title,"," theme:editor.options.theme,"," onclick:function () {"," if (editor.ui) {"," editor.ui.setFullScreen(!editor.ui.isFullScreen());"," }"," this.setChecked(editor.ui.isFullScreen());"," }"," });"," editorui.buttons['fullscreen'] = ui;"," editor.addListener('selectionchange', function () {"," var state = editor.queryCommandState('fullscreen');"," ui.setDisabled(state == -1);"," ui.setChecked(editor.ui.isFullScreen());"," });"," return ui;"," };",""," // 表情"," editorui[\"emotion\"] = function (editor, iframeUrl) {"," var cmd = \"emotion\";"," var ui = new editorui.MultiMenuPop({"," title:editor.options.labelMap[cmd] || editor.getLang(\"labelMap.\" + cmd + \"\") || '',"," editor:editor,"," className:'edui-for-' + cmd,"," iframeUrl:editor.ui.mapUrl(iframeUrl || (editor.options.iframeUrlMap || {})[cmd] || iframeUrlMap[cmd])"," });"," editorui.buttons[cmd] = ui;",""," editor.addListener('selectionchange', function () {"," ui.setDisabled(editor.queryCommandState(cmd) == -1)"," });"," return ui;"," };",""," editorui.autotypeset = function (editor) {"," var ui = new editorui.AutoTypeSetButton({"," editor:editor,"," title:editor.options.labelMap['autotypeset'] || editor.getLang(\"labelMap.autotypeset\") || '',"," className:'edui-for-autotypeset',"," onbuttonclick:function () {"," editor.execCommand('autotypeset')"," }"," });"," editorui.buttons['autotypeset'] = ui;"," editor.addListener('selectionchange', function () {"," ui.setDisabled(editor.queryCommandState('autotypeset') == -1);"," });"," return ui;"," };","","})();"]; +_$jscoverage['ui/editorui.js'][4]++; +(function () { + _$jscoverage['ui/editorui.js'][5]++; + var utils = baidu.editor.utils; + _$jscoverage['ui/editorui.js'][6]++; + var editorui = baidu.editor.ui; + _$jscoverage['ui/editorui.js'][7]++; + var _Dialog = editorui.Dialog; + _$jscoverage['ui/editorui.js'][8]++; + editorui.buttons = {}; + _$jscoverage['ui/editorui.js'][10]++; + editorui.Dialog = (function (options) { + _$jscoverage['ui/editorui.js'][11]++; + var dialog = new _Dialog(options); + _$jscoverage['ui/editorui.js'][12]++; + dialog.addListener("hide", (function () { + _$jscoverage['ui/editorui.js'][14]++; + if (dialog.editor) { + _$jscoverage['ui/editorui.js'][15]++; + var editor = dialog.editor; + _$jscoverage['ui/editorui.js'][16]++; + try { + _$jscoverage['ui/editorui.js'][17]++; + if (browser.gecko) { + _$jscoverage['ui/editorui.js'][18]++; + var y = editor.window.scrollY, x = editor.window.scrollX; + _$jscoverage['ui/editorui.js'][20]++; + editor.body.focus(); + _$jscoverage['ui/editorui.js'][21]++; + editor.window.scrollTo(x, y); + } + else { + _$jscoverage['ui/editorui.js'][23]++; + editor.focus(); + } + } + catch (ex) { + } + } +})); + _$jscoverage['ui/editorui.js'][31]++; + return dialog; +}); + _$jscoverage['ui/editorui.js'][34]++; + var iframeUrlMap = {"anchor": "~/dialogs/anchor/anchor.html", "insertimage": "~/dialogs/image/image.html", "link": "~/dialogs/link/link.html", "spechars": "~/dialogs/spechars/spechars.html", "searchreplace": "~/dialogs/searchreplace/searchreplace.html", "map": "~/dialogs/map/map.html", "gmap": "~/dialogs/gmap/gmap.html", "insertvideo": "~/dialogs/video/video.html", "help": "~/dialogs/help/help.html", "emotion": "~/dialogs/emotion/emotion.html", "wordimage": "~/dialogs/wordimage/wordimage.html", "attachment": "~/dialogs/attachment/attachment.html", "insertframe": "~/dialogs/insertframe/insertframe.html", "edittip": "~/dialogs/table/edittip.html", "edittable": "~/dialogs/table/edittable.html", "edittd": "~/dialogs/table/edittd.html", "webapp": "~/dialogs/webapp/webapp.html", "snapscreen": "~/dialogs/snapscreen/snapscreen.html", "scrawl": "~/dialogs/scrawl/scrawl.html", "music": "~/dialogs/music/music.html", "template": "~/dialogs/template/template.html", "background": "~/dialogs/background/background.html"}; + _$jscoverage['ui/editorui.js'][60]++; + var btnCmds = ["undo", "redo", "formatmatch", "bold", "italic", "underline", "fontborder", "touppercase", "tolowercase", "strikethrough", "subscript", "superscript", "source", "indent", "outdent", "blockquote", "pasteplain", "pagebreak", "selectall", "print", "preview", "horizontal", "removeformat", "time", "date", "unlink", "insertparagraphbeforetable", "insertrow", "insertcol", "mergeright", "mergedown", "deleterow", "deletecol", "splittorows", "splittocols", "splittocells", "mergecells", "deletetable"]; + _$jscoverage['ui/editorui.js'][68]++; + for (var i = 0, ci; (ci = btnCmds[(i++)]);) { + _$jscoverage['ui/editorui.js'][69]++; + ci = ci.toLowerCase(); + _$jscoverage['ui/editorui.js'][70]++; + editorui[ci] = (function (cmd) { + _$jscoverage['ui/editorui.js'][71]++; + return (function (editor) { + _$jscoverage['ui/editorui.js'][72]++; + var ui = new (editorui.Button)({className: ("edui-for-" + cmd), title: (editor.options.labelMap[cmd] || editor.getLang(("labelMap." + cmd)) || ""), onclick: (function () { + _$jscoverage['ui/editorui.js'][76]++; + editor.execCommand(cmd); +}), theme: editor.options.theme, showText: false}); + _$jscoverage['ui/editorui.js'][81]++; + editorui.buttons[cmd] = ui; + _$jscoverage['ui/editorui.js'][82]++; + editor.addListener("selectionchange", (function (type, causeByUi, uiReady) { + _$jscoverage['ui/editorui.js'][83]++; + var state = editor.queryCommandState(cmd); + _$jscoverage['ui/editorui.js'][84]++; + if ((state == -1)) { + _$jscoverage['ui/editorui.js'][85]++; + ui.setDisabled(true); + _$jscoverage['ui/editorui.js'][86]++; + ui.setChecked(false); + } + else { + _$jscoverage['ui/editorui.js'][88]++; + if ((! uiReady)) { + _$jscoverage['ui/editorui.js'][89]++; + ui.setDisabled(false); + _$jscoverage['ui/editorui.js'][90]++; + ui.setChecked(state); + } + } +})); + _$jscoverage['ui/editorui.js'][94]++; + return ui; +}); +})(ci); +} + _$jscoverage['ui/editorui.js'][100]++; + editorui.cleardoc = (function (editor) { + _$jscoverage['ui/editorui.js'][101]++; + var ui = new (editorui.Button)({className: "edui-for-cleardoc", title: (editor.options.labelMap.cleardoc || editor.getLang("labelMap.cleardoc") || ""), theme: editor.options.theme, onclick: (function () { + _$jscoverage['ui/editorui.js'][106]++; + if (confirm(editor.getLang("confirmClear"))) { + _$jscoverage['ui/editorui.js'][107]++; + editor.execCommand("cleardoc"); + } +})}); + _$jscoverage['ui/editorui.js'][111]++; + editorui.buttons.cleardoc = ui; + _$jscoverage['ui/editorui.js'][112]++; + editor.addListener("selectionchange", (function () { + _$jscoverage['ui/editorui.js'][113]++; + ui.setDisabled((editor.queryCommandState("cleardoc") == -1)); +})); + _$jscoverage['ui/editorui.js'][115]++; + return ui; +}); + _$jscoverage['ui/editorui.js'][119]++; + var typeset = {"justify": ["left", "right", "center", "justify"], "imagefloat": ["none", "left", "center", "right"], "directionality": ["ltr", "rtl"]}; + _$jscoverage['ui/editorui.js'][125]++; + for (var p in typeset) { + _$jscoverage['ui/editorui.js'][127]++; + (function (cmd, val) { + _$jscoverage['ui/editorui.js'][128]++; + for (var i = 0, ci; (ci = val[(i++)]);) { + _$jscoverage['ui/editorui.js'][129]++; + (function (cmd2) { + _$jscoverage['ui/editorui.js'][130]++; + editorui[(cmd.replace("float", "") + cmd2)] = (function (editor) { + _$jscoverage['ui/editorui.js'][131]++; + var ui = new (editorui.Button)({className: ("edui-for-" + cmd.replace("float", "") + cmd2), title: (editor.options.labelMap[(cmd.replace("float", "") + cmd2)] || editor.getLang(("labelMap." + cmd.replace("float", "") + cmd2)) || ""), theme: editor.options.theme, onclick: (function () { + _$jscoverage['ui/editorui.js'][136]++; + editor.execCommand(cmd, cmd2); +})}); + _$jscoverage['ui/editorui.js'][139]++; + editorui.buttons[cmd] = ui; + _$jscoverage['ui/editorui.js'][140]++; + editor.addListener("selectionchange", (function (type, causeByUi, uiReady) { + _$jscoverage['ui/editorui.js'][141]++; + ui.setDisabled((editor.queryCommandState(cmd) == -1)); + _$jscoverage['ui/editorui.js'][142]++; + ui.setChecked(((editor.queryCommandValue(cmd) == cmd2) && (! uiReady))); +})); + _$jscoverage['ui/editorui.js'][144]++; + return ui; +}); +})(ci); +} +})(p, typeset[p]); +} + _$jscoverage['ui/editorui.js'][152]++; + for (var i = 0, ci = ci; (ci = ["backcolor", "forecolor"][(i++)]);) { + _$jscoverage['ui/editorui.js'][153]++; + editorui[ci] = (function (cmd) { + _$jscoverage['ui/editorui.js'][154]++; + return (function (editor) { + _$jscoverage['ui/editorui.js'][155]++; + var ui = new (editorui.ColorButton)({className: ("edui-for-" + cmd), color: "default", title: (editor.options.labelMap[cmd] || editor.getLang(("labelMap." + cmd)) || ""), editor: editor, onpickcolor: (function (t, color) { + _$jscoverage['ui/editorui.js'][161]++; + editor.execCommand(cmd, color); +}), onpicknocolor: (function () { + _$jscoverage['ui/editorui.js'][164]++; + editor.execCommand(cmd, "default"); + _$jscoverage['ui/editorui.js'][165]++; + this.setColor("transparent"); + _$jscoverage['ui/editorui.js'][166]++; + this.color = "default"; +}), onbuttonclick: (function () { + _$jscoverage['ui/editorui.js'][169]++; + editor.execCommand(cmd, this.color); +})}); + _$jscoverage['ui/editorui.js'][172]++; + editorui.buttons[cmd] = ui; + _$jscoverage['ui/editorui.js'][173]++; + editor.addListener("selectionchange", (function () { + _$jscoverage['ui/editorui.js'][174]++; + ui.setDisabled((editor.queryCommandState(cmd) == -1)); +})); + _$jscoverage['ui/editorui.js'][176]++; + return ui; +}); +})(ci); +} + _$jscoverage['ui/editorui.js'][182]++; + var dialogBtns = {noOk: ["searchreplace", "help", "spechars", "webapp"], ok: ["attachment", "anchor", "link", "insertimage", "map", "gmap", "insertframe", "wordimage", "insertvideo", "insertframe", "edittip", "edittable", "edittd", "scrawl", "template", "music", "background"]}; + _$jscoverage['ui/editorui.js'][189]++; + for (var p = p in dialogBtns) { + _$jscoverage['ui/editorui.js'][190]++; + (function (type, vals) { + _$jscoverage['ui/editorui.js'][191]++; + for (var i = 0, ci; (ci = vals[(i++)]);) { + _$jscoverage['ui/editorui.js'][193]++; + if ((browser.opera && (ci === "searchreplace"))) { + _$jscoverage['ui/editorui.js'][194]++; + continue; + } + _$jscoverage['ui/editorui.js'][196]++; + (function (cmd) { + _$jscoverage['ui/editorui.js'][197]++; + editorui[cmd] = (function (editor, iframeUrl, title) { + _$jscoverage['ui/editorui.js'][198]++; + iframeUrl = (iframeUrl || (editor.options.iframeUrlMap || {})[cmd] || iframeUrlMap[cmd]); + _$jscoverage['ui/editorui.js'][199]++; + title = (editor.options.labelMap[cmd] || editor.getLang(("labelMap." + cmd)) || ""); + _$jscoverage['ui/editorui.js'][201]++; + var dialog; + _$jscoverage['ui/editorui.js'][203]++; + if (iframeUrl) { + _$jscoverage['ui/editorui.js'][204]++; + dialog = new (editorui.Dialog)(utils.extend({iframeUrl: editor.ui.mapUrl(iframeUrl), editor: editor, className: ("edui-for-" + cmd), title: title, holdScroll: (cmd === "insertimage"), closeDialog: editor.getLang("closeDialog")}, ((type == "ok")? {buttons: [{className: "edui-okbutton", label: editor.getLang("ok"), editor: editor, onclick: (function () { + _$jscoverage['ui/editorui.js'][218]++; + dialog.close(true); +})}, {className: "edui-cancelbutton", label: editor.getLang("cancel"), editor: editor, onclick: (function () { + _$jscoverage['ui/editorui.js'][226]++; + dialog.close(false); +})}]}: {}))); + _$jscoverage['ui/editorui.js'][232]++; + editor.ui._dialogs[(cmd + "Dialog")] = dialog; + } + _$jscoverage['ui/editorui.js'][235]++; + var ui = new (editorui.Button)({className: ("edui-for-" + cmd), title: title, onclick: (function () { + _$jscoverage['ui/editorui.js'][239]++; + if (dialog) { + _$jscoverage['ui/editorui.js'][240]++; + switch (cmd) { + case "wordimage": + _$jscoverage['ui/editorui.js'][242]++; + editor.execCommand("wordimage", "word_img"); + _$jscoverage['ui/editorui.js'][243]++; + if (editor.word_img) { + _$jscoverage['ui/editorui.js'][244]++; + dialog.render(); + _$jscoverage['ui/editorui.js'][245]++; + dialog.open(); + } + _$jscoverage['ui/editorui.js'][247]++; + break; + case "scrawl": + _$jscoverage['ui/editorui.js'][249]++; + if ((editor.queryCommandState("scrawl") != -1)) { + _$jscoverage['ui/editorui.js'][250]++; + dialog.render(); + _$jscoverage['ui/editorui.js'][251]++; + dialog.open(); + } + _$jscoverage['ui/editorui.js'][254]++; + break; + default: + _$jscoverage['ui/editorui.js'][256]++; + dialog.render(); + _$jscoverage['ui/editorui.js'][257]++; + dialog.open(); + } + } +}), theme: editor.options.theme, disabled: ((cmd == "scrawl") && (editor.queryCommandState("scrawl") == -1))}); + _$jscoverage['ui/editorui.js'][264]++; + editorui.buttons[cmd] = ui; + _$jscoverage['ui/editorui.js'][265]++; + editor.addListener("selectionchange", (function () { + _$jscoverage['ui/editorui.js'][267]++; + var unNeedCheckState = {"edittable": 1}; + _$jscoverage['ui/editorui.js'][268]++; + if ((cmd in unNeedCheckState)) { + _$jscoverage['ui/editorui.js'][268]++; + return; + } + _$jscoverage['ui/editorui.js'][270]++; + var state = editor.queryCommandState(cmd); + _$jscoverage['ui/editorui.js'][271]++; + if (ui.getDom()) { + _$jscoverage['ui/editorui.js'][272]++; + ui.setDisabled((state == -1)); + _$jscoverage['ui/editorui.js'][273]++; + ui.setChecked(state); + } +})); + _$jscoverage['ui/editorui.js'][278]++; + return ui; +}); +})(ci.toLowerCase()); +} +})(p, dialogBtns[p]); +} + _$jscoverage['ui/editorui.js'][285]++; + editorui.snapscreen = (function (editor, iframeUrl, title) { + _$jscoverage['ui/editorui.js'][286]++; + title = (editor.options.labelMap.snapscreen || editor.getLang("labelMap.snapscreen") || ""); + _$jscoverage['ui/editorui.js'][287]++; + var ui = new (editorui.Button)({className: "edui-for-snapscreen", title: title, onclick: (function () { + _$jscoverage['ui/editorui.js'][291]++; + editor.execCommand("snapscreen"); +}), theme: editor.options.theme}); + _$jscoverage['ui/editorui.js'][296]++; + editorui.buttons.snapscreen = ui; + _$jscoverage['ui/editorui.js'][297]++; + iframeUrl = (iframeUrl || (editor.options.iframeUrlMap || {}).snapscreen || iframeUrlMap.snapscreen); + _$jscoverage['ui/editorui.js'][298]++; + if (iframeUrl) { + _$jscoverage['ui/editorui.js'][299]++; + var dialog = new (editorui.Dialog)({iframeUrl: editor.ui.mapUrl(iframeUrl), editor: editor, className: "edui-for-snapscreen", title: title, buttons: [{className: "edui-okbutton", label: editor.getLang("ok"), editor: editor, onclick: (function () { + _$jscoverage['ui/editorui.js'][310]++; + dialog.close(true); +})}, {className: "edui-cancelbutton", label: editor.getLang("cancel"), editor: editor, onclick: (function () { + _$jscoverage['ui/editorui.js'][318]++; + dialog.close(false); +})}]}); + _$jscoverage['ui/editorui.js'][324]++; + dialog.render(); + _$jscoverage['ui/editorui.js'][325]++; + editor.ui._dialogs.snapscreenDialog = dialog; + } + _$jscoverage['ui/editorui.js'][327]++; + editor.addListener("selectionchange", (function () { + _$jscoverage['ui/editorui.js'][328]++; + ui.setDisabled((editor.queryCommandState("snapscreen") == -1)); +})); + _$jscoverage['ui/editorui.js'][330]++; + return ui; +}); + _$jscoverage['ui/editorui.js'][333]++; + editorui.insertcode = (function (editor, list, title) { + _$jscoverage['ui/editorui.js'][334]++; + list = (editor.options.insertcode || []); + _$jscoverage['ui/editorui.js'][335]++; + title = (editor.options.labelMap.insertcode || editor.getLang("labelMap.insertcode") || ""); + _$jscoverage['ui/editorui.js'][337]++; + var items = []; + _$jscoverage['ui/editorui.js'][338]++; + utils.each(list, (function (key, val) { + _$jscoverage['ui/editorui.js'][339]++; + items.push({label: key, value: val, theme: editor.options.theme, renderLabelHtml: (function () { + _$jscoverage['ui/editorui.js'][344]++; + return ("
    " + (this.label || "") + "
    "); +})}); +})); + _$jscoverage['ui/editorui.js'][349]++; + var ui = new (editorui.Combox)({editor: editor, items: items, onselect: (function (t, index) { + _$jscoverage['ui/editorui.js'][353]++; + editor.execCommand("insertcode", this.items[index].value); +}), onbuttonclick: (function () { + _$jscoverage['ui/editorui.js'][356]++; + this.showPopup(); +}), title: title, initValue: title, className: "edui-for-insertcode", indexByValue: (function (value) { + _$jscoverage['ui/editorui.js'][362]++; + if (value) { + _$jscoverage['ui/editorui.js'][363]++; + for (var i = 0, ci; (ci = this.items[i]); (i++)) { + _$jscoverage['ui/editorui.js'][364]++; + if ((ci.value.indexOf(value) != -1)) { + _$jscoverage['ui/editorui.js'][365]++; + return i; + } +} + } + _$jscoverage['ui/editorui.js'][369]++; + return -1; +})}); + _$jscoverage['ui/editorui.js'][372]++; + editorui.buttons.insertcode = ui; + _$jscoverage['ui/editorui.js'][373]++; + editor.addListener("selectionchange", (function (type, causeByUi, uiReady) { + _$jscoverage['ui/editorui.js'][374]++; + if ((! uiReady)) { + _$jscoverage['ui/editorui.js'][375]++; + var state = editor.queryCommandState("insertcode"); + _$jscoverage['ui/editorui.js'][376]++; + if ((state == -1)) { + _$jscoverage['ui/editorui.js'][377]++; + ui.setDisabled(true); + } + else { + _$jscoverage['ui/editorui.js'][379]++; + ui.setDisabled(false); + _$jscoverage['ui/editorui.js'][380]++; + var value = editor.queryCommandValue("insertcode"); + _$jscoverage['ui/editorui.js'][381]++; + if ((! value)) { + _$jscoverage['ui/editorui.js'][382]++; + ui.setValue(title); + _$jscoverage['ui/editorui.js'][383]++; + return; + } + _$jscoverage['ui/editorui.js'][386]++; + (value && (value = value.replace(/['"]/g, "").split(",")[0])); + _$jscoverage['ui/editorui.js'][387]++; + ui.setValue(value); + } + } +})); + _$jscoverage['ui/editorui.js'][393]++; + return ui; +}); + _$jscoverage['ui/editorui.js'][395]++; + editorui.fontfamily = (function (editor, list, title) { + _$jscoverage['ui/editorui.js'][397]++; + list = (editor.options.fontfamily || []); + _$jscoverage['ui/editorui.js'][398]++; + title = (editor.options.labelMap.fontfamily || editor.getLang("labelMap.fontfamily") || ""); + _$jscoverage['ui/editorui.js'][399]++; + if ((! list.length)) { + _$jscoverage['ui/editorui.js'][399]++; + return; + } + _$jscoverage['ui/editorui.js'][400]++; + for (var i = 0, ci, items = []; (ci = list[i]); (i++)) { + _$jscoverage['ui/editorui.js'][401]++; + var langLabel = (editor.getLang("fontfamily")[ci.name] || ""); + _$jscoverage['ui/editorui.js'][402]++; + (function (key, val) { + _$jscoverage['ui/editorui.js'][403]++; + items.push({label: key, value: val, theme: editor.options.theme, renderLabelHtml: (function () { + _$jscoverage['ui/editorui.js'][408]++; + return ("
    " + (this.label || "") + "
    "); +})}); +})((ci.label || langLabel), ci.val); +} + _$jscoverage['ui/editorui.js'][414]++; + var ui = new (editorui.Combox)({editor: editor, items: items, onselect: (function (t, index) { + _$jscoverage['ui/editorui.js'][418]++; + editor.execCommand("FontFamily", this.items[index].value); +}), onbuttonclick: (function () { + _$jscoverage['ui/editorui.js'][421]++; + this.showPopup(); +}), title: title, initValue: title, className: "edui-for-fontfamily", indexByValue: (function (value) { + _$jscoverage['ui/editorui.js'][427]++; + if (value) { + _$jscoverage['ui/editorui.js'][428]++; + for (var i = 0, ci; (ci = this.items[i]); (i++)) { + _$jscoverage['ui/editorui.js'][429]++; + if ((ci.value.indexOf(value) != -1)) { + _$jscoverage['ui/editorui.js'][430]++; + return i; + } +} + } + _$jscoverage['ui/editorui.js'][434]++; + return -1; +})}); + _$jscoverage['ui/editorui.js'][437]++; + editorui.buttons.fontfamily = ui; + _$jscoverage['ui/editorui.js'][438]++; + editor.addListener("selectionchange", (function (type, causeByUi, uiReady) { + _$jscoverage['ui/editorui.js'][439]++; + if ((! uiReady)) { + _$jscoverage['ui/editorui.js'][440]++; + var state = editor.queryCommandState("FontFamily"); + _$jscoverage['ui/editorui.js'][441]++; + if ((state == -1)) { + _$jscoverage['ui/editorui.js'][442]++; + ui.setDisabled(true); + } + else { + _$jscoverage['ui/editorui.js'][444]++; + ui.setDisabled(false); + _$jscoverage['ui/editorui.js'][445]++; + var value = editor.queryCommandValue("FontFamily"); + _$jscoverage['ui/editorui.js'][447]++; + (value && (value = value.replace(/['"]/g, "").split(",")[0])); + _$jscoverage['ui/editorui.js'][448]++; + ui.setValue(value); + } + } +})); + _$jscoverage['ui/editorui.js'][454]++; + return ui; +}); + _$jscoverage['ui/editorui.js'][457]++; + editorui.fontsize = (function (editor, list, title) { + _$jscoverage['ui/editorui.js'][458]++; + title = (editor.options.labelMap.fontsize || editor.getLang("labelMap.fontsize") || ""); + _$jscoverage['ui/editorui.js'][459]++; + list = (list || editor.options.fontsize || []); + _$jscoverage['ui/editorui.js'][460]++; + if ((! list.length)) { + _$jscoverage['ui/editorui.js'][460]++; + return; + } + _$jscoverage['ui/editorui.js'][461]++; + var items = []; + _$jscoverage['ui/editorui.js'][462]++; + for (var i = 0; (i < list.length); (i++)) { + _$jscoverage['ui/editorui.js'][463]++; + var size = (list[i] + "px"); + _$jscoverage['ui/editorui.js'][464]++; + items.push({label: size, value: size, theme: editor.options.theme, renderLabelHtml: (function () { + _$jscoverage['ui/editorui.js'][469]++; + return ("
    " + (this.label || "") + "
    "); +})}); +} + _$jscoverage['ui/editorui.js'][474]++; + var ui = new (editorui.Combox)({editor: editor, items: items, title: title, initValue: title, onselect: (function (t, index) { + _$jscoverage['ui/editorui.js'][480]++; + editor.execCommand("FontSize", this.items[index].value); +}), onbuttonclick: (function () { + _$jscoverage['ui/editorui.js'][483]++; + this.showPopup(); +}), className: "edui-for-fontsize"}); + _$jscoverage['ui/editorui.js'][487]++; + editorui.buttons.fontsize = ui; + _$jscoverage['ui/editorui.js'][488]++; + editor.addListener("selectionchange", (function (type, causeByUi, uiReady) { + _$jscoverage['ui/editorui.js'][489]++; + if ((! uiReady)) { + _$jscoverage['ui/editorui.js'][490]++; + var state = editor.queryCommandState("FontSize"); + _$jscoverage['ui/editorui.js'][491]++; + if ((state == -1)) { + _$jscoverage['ui/editorui.js'][492]++; + ui.setDisabled(true); + } + else { + _$jscoverage['ui/editorui.js'][494]++; + ui.setDisabled(false); + _$jscoverage['ui/editorui.js'][495]++; + ui.setValue(editor.queryCommandValue("FontSize")); + } + } +})); + _$jscoverage['ui/editorui.js'][500]++; + return ui; +}); + _$jscoverage['ui/editorui.js'][503]++; + editorui.paragraph = (function (editor, list, title) { + _$jscoverage['ui/editorui.js'][504]++; + title = (editor.options.labelMap.paragraph || editor.getLang("labelMap.paragraph") || ""); + _$jscoverage['ui/editorui.js'][505]++; + list = (editor.options.paragraph || []); + _$jscoverage['ui/editorui.js'][506]++; + if (utils.isEmptyObject(list)) { + _$jscoverage['ui/editorui.js'][506]++; + return; + } + _$jscoverage['ui/editorui.js'][507]++; + var items = []; + _$jscoverage['ui/editorui.js'][508]++; + for (var i in list) { + _$jscoverage['ui/editorui.js'][509]++; + items.push({value: i, label: (list[i] || editor.getLang("paragraph")[i]), theme: editor.options.theme, renderLabelHtml: (function () { + _$jscoverage['ui/editorui.js'][514]++; + return ("
    " + (this.label || "") + "
    "); +})}); +} + _$jscoverage['ui/editorui.js'][518]++; + var ui = new (editorui.Combox)({editor: editor, items: items, title: title, initValue: title, className: "edui-for-paragraph", onselect: (function (t, index) { + _$jscoverage['ui/editorui.js'][525]++; + editor.execCommand("Paragraph", this.items[index].value); +}), onbuttonclick: (function () { + _$jscoverage['ui/editorui.js'][528]++; + this.showPopup(); +})}); + _$jscoverage['ui/editorui.js'][531]++; + editorui.buttons.paragraph = ui; + _$jscoverage['ui/editorui.js'][532]++; + editor.addListener("selectionchange", (function (type, causeByUi, uiReady) { + _$jscoverage['ui/editorui.js'][533]++; + if ((! uiReady)) { + _$jscoverage['ui/editorui.js'][534]++; + var state = editor.queryCommandState("Paragraph"); + _$jscoverage['ui/editorui.js'][535]++; + if ((state == -1)) { + _$jscoverage['ui/editorui.js'][536]++; + ui.setDisabled(true); + } + else { + _$jscoverage['ui/editorui.js'][538]++; + ui.setDisabled(false); + _$jscoverage['ui/editorui.js'][539]++; + var value = editor.queryCommandValue("Paragraph"); + _$jscoverage['ui/editorui.js'][540]++; + var index = ui.indexByValue(value); + _$jscoverage['ui/editorui.js'][541]++; + if ((index != -1)) { + _$jscoverage['ui/editorui.js'][542]++; + ui.setValue(value); + } + else { + _$jscoverage['ui/editorui.js'][544]++; + ui.setValue(ui.initValue); + } + } + } +})); + _$jscoverage['ui/editorui.js'][550]++; + return ui; +}); + _$jscoverage['ui/editorui.js'][555]++; + editorui.customstyle = (function (editor) { + _$jscoverage['ui/editorui.js'][556]++; + var list = (editor.options.customstyle || []), title = (editor.options.labelMap.customstyle || editor.getLang("labelMap.customstyle") || ""); + _$jscoverage['ui/editorui.js'][558]++; + if ((! list.length)) { + _$jscoverage['ui/editorui.js'][558]++; + return; + } + _$jscoverage['ui/editorui.js'][559]++; + var langCs = editor.getLang("customstyle"); + _$jscoverage['ui/editorui.js'][560]++; + for (var i = 0, items = [], t; (t = list[(i++)]);) { + _$jscoverage['ui/editorui.js'][561]++; + (function (t) { + _$jscoverage['ui/editorui.js'][562]++; + var ck = {}; + _$jscoverage['ui/editorui.js'][563]++; + ck.label = (t.label? t.label: langCs[t.name]); + _$jscoverage['ui/editorui.js'][564]++; + ck.style = t.style; + _$jscoverage['ui/editorui.js'][565]++; + ck.className = t.className; + _$jscoverage['ui/editorui.js'][566]++; + ck.tag = t.tag; + _$jscoverage['ui/editorui.js'][567]++; + items.push({label: ck.label, value: ck, theme: editor.options.theme, renderLabelHtml: (function () { + _$jscoverage['ui/editorui.js'][572]++; + return ("
    " + "<" + ck.tag + " " + (ck.className? (" class=\"" + ck.className + "\""): "") + (ck.style? (" style=\"" + ck.style + "\""): "") + ">" + ck.label + "" + "
    "); +})}); +})(t); +} + _$jscoverage['ui/editorui.js'][580]++; + var ui = new (editorui.Combox)({editor: editor, items: items, title: title, initValue: title, className: "edui-for-customstyle", onselect: (function (t, index) { + _$jscoverage['ui/editorui.js'][587]++; + editor.execCommand("customstyle", this.items[index].value); +}), onbuttonclick: (function () { + _$jscoverage['ui/editorui.js'][590]++; + this.showPopup(); +}), indexByValue: (function (value) { + _$jscoverage['ui/editorui.js'][593]++; + for (var i = 0, ti; (ti = this.items[(i++)]);) { + _$jscoverage['ui/editorui.js'][594]++; + if ((ti.label == value)) { + _$jscoverage['ui/editorui.js'][595]++; + return (i - 1); + } +} + _$jscoverage['ui/editorui.js'][598]++; + return -1; +})}); + _$jscoverage['ui/editorui.js'][601]++; + editorui.buttons.customstyle = ui; + _$jscoverage['ui/editorui.js'][602]++; + editor.addListener("selectionchange", (function (type, causeByUi, uiReady) { + _$jscoverage['ui/editorui.js'][603]++; + if ((! uiReady)) { + _$jscoverage['ui/editorui.js'][604]++; + var state = editor.queryCommandState("customstyle"); + _$jscoverage['ui/editorui.js'][605]++; + if ((state == -1)) { + _$jscoverage['ui/editorui.js'][606]++; + ui.setDisabled(true); + } + else { + _$jscoverage['ui/editorui.js'][608]++; + ui.setDisabled(false); + _$jscoverage['ui/editorui.js'][609]++; + var value = editor.queryCommandValue("customstyle"); + _$jscoverage['ui/editorui.js'][610]++; + var index = ui.indexByValue(value); + _$jscoverage['ui/editorui.js'][611]++; + if ((index != -1)) { + _$jscoverage['ui/editorui.js'][612]++; + ui.setValue(value); + } + else { + _$jscoverage['ui/editorui.js'][614]++; + ui.setValue(ui.initValue); + } + } + } +})); + _$jscoverage['ui/editorui.js'][620]++; + return ui; +}); + _$jscoverage['ui/editorui.js'][622]++; + editorui.inserttable = (function (editor, iframeUrl, title) { + _$jscoverage['ui/editorui.js'][623]++; + title = (editor.options.labelMap.inserttable || editor.getLang("labelMap.inserttable") || ""); + _$jscoverage['ui/editorui.js'][624]++; + var ui = new (editorui.TableButton)({editor: editor, title: title, className: "edui-for-inserttable", onpicktable: (function (t, numCols, numRows) { + _$jscoverage['ui/editorui.js'][629]++; + editor.execCommand("InsertTable", {numRows: numRows, numCols: numCols, border: 1}); +}), onbuttonclick: (function () { + _$jscoverage['ui/editorui.js'][632]++; + this.showPopup(); +})}); + _$jscoverage['ui/editorui.js'][635]++; + editorui.buttons.inserttable = ui; + _$jscoverage['ui/editorui.js'][636]++; + editor.addListener("selectionchange", (function () { + _$jscoverage['ui/editorui.js'][637]++; + ui.setDisabled((editor.queryCommandState("inserttable") == -1)); +})); + _$jscoverage['ui/editorui.js'][639]++; + return ui; +}); + _$jscoverage['ui/editorui.js'][642]++; + editorui.lineheight = (function (editor) { + _$jscoverage['ui/editorui.js'][643]++; + var val = (editor.options.lineheight || []); + _$jscoverage['ui/editorui.js'][644]++; + if ((! val.length)) { + _$jscoverage['ui/editorui.js'][644]++; + return; + } + _$jscoverage['ui/editorui.js'][645]++; + for (var i = 0, ci, items = []; (ci = val[(i++)]);) { + _$jscoverage['ui/editorui.js'][646]++; + items.push({label: ci, value: ci, theme: editor.options.theme, onclick: (function () { + _$jscoverage['ui/editorui.js'][652]++; + editor.execCommand("lineheight", this.value); +})}); +} + _$jscoverage['ui/editorui.js'][656]++; + var ui = new (editorui.MenuButton)({editor: editor, className: "edui-for-lineheight", title: (editor.options.labelMap.lineheight || editor.getLang("labelMap.lineheight") || ""), items: items, onbuttonclick: (function () { + _$jscoverage['ui/editorui.js'][662]++; + var value = (editor.queryCommandValue("LineHeight") || this.value); + _$jscoverage['ui/editorui.js'][663]++; + editor.execCommand("LineHeight", value); +})}); + _$jscoverage['ui/editorui.js'][666]++; + editorui.buttons.lineheight = ui; + _$jscoverage['ui/editorui.js'][667]++; + editor.addListener("selectionchange", (function () { + _$jscoverage['ui/editorui.js'][668]++; + var state = editor.queryCommandState("LineHeight"); + _$jscoverage['ui/editorui.js'][669]++; + if ((state == -1)) { + _$jscoverage['ui/editorui.js'][670]++; + ui.setDisabled(true); + } + else { + _$jscoverage['ui/editorui.js'][672]++; + ui.setDisabled(false); + _$jscoverage['ui/editorui.js'][673]++; + var value = editor.queryCommandValue("LineHeight"); + _$jscoverage['ui/editorui.js'][674]++; + (value && ui.setValue((value + "").replace(/cm/, ""))); + _$jscoverage['ui/editorui.js'][675]++; + ui.setChecked(state); + } +})); + _$jscoverage['ui/editorui.js'][678]++; + return ui; +}); + _$jscoverage['ui/editorui.js'][681]++; + var rowspacings = ["top", "bottom"]; + _$jscoverage['ui/editorui.js'][682]++; + for (var r = 0, ri; (ri = rowspacings[(r++)]);) { + _$jscoverage['ui/editorui.js'][683]++; + (function (cmd) { + _$jscoverage['ui/editorui.js'][684]++; + editorui[("rowspacing" + cmd)] = (function (editor) { + _$jscoverage['ui/editorui.js'][685]++; + var val = (editor.options[("rowspacing" + cmd)] || []); + _$jscoverage['ui/editorui.js'][686]++; + if ((! val.length)) { + _$jscoverage['ui/editorui.js'][686]++; + return null; + } + _$jscoverage['ui/editorui.js'][687]++; + for (var i = 0, ci, items = []; (ci = val[(i++)]);) { + _$jscoverage['ui/editorui.js'][688]++; + items.push({label: ci, value: ci, theme: editor.options.theme, onclick: (function () { + _$jscoverage['ui/editorui.js'][693]++; + editor.execCommand("rowspacing", this.value, cmd); +})}); +} + _$jscoverage['ui/editorui.js'][697]++; + var ui = new (editorui.MenuButton)({editor: editor, className: ("edui-for-rowspacing" + cmd), title: (editor.options.labelMap[("rowspacing" + cmd)] || editor.getLang(("labelMap.rowspacing" + cmd)) || ""), items: items, onbuttonclick: (function () { + _$jscoverage['ui/editorui.js'][703]++; + var value = (editor.queryCommandValue("rowspacing", cmd) || this.value); + _$jscoverage['ui/editorui.js'][704]++; + editor.execCommand("rowspacing", value, cmd); +})}); + _$jscoverage['ui/editorui.js'][707]++; + editorui.buttons[cmd] = ui; + _$jscoverage['ui/editorui.js'][708]++; + editor.addListener("selectionchange", (function () { + _$jscoverage['ui/editorui.js'][709]++; + var state = editor.queryCommandState("rowspacing", cmd); + _$jscoverage['ui/editorui.js'][710]++; + if ((state == -1)) { + _$jscoverage['ui/editorui.js'][711]++; + ui.setDisabled(true); + } + else { + _$jscoverage['ui/editorui.js'][713]++; + ui.setDisabled(false); + _$jscoverage['ui/editorui.js'][714]++; + var value = editor.queryCommandValue("rowspacing", cmd); + _$jscoverage['ui/editorui.js'][715]++; + (value && ui.setValue((value + "").replace(/%/, ""))); + _$jscoverage['ui/editorui.js'][716]++; + ui.setChecked(state); + } +})); + _$jscoverage['ui/editorui.js'][719]++; + return ui; +}); +})(ri); +} + _$jscoverage['ui/editorui.js'][724]++; + var lists = ["insertorderedlist", "insertunorderedlist"]; + _$jscoverage['ui/editorui.js'][725]++; + for (var l = 0, cl; (cl = lists[(l++)]);) { + _$jscoverage['ui/editorui.js'][726]++; + (function (cmd) { + _$jscoverage['ui/editorui.js'][727]++; + editorui[cmd] = (function (editor) { + _$jscoverage['ui/editorui.js'][728]++; + var vals = editor.options[cmd], _onMenuClick = (function () { + _$jscoverage['ui/editorui.js'][730]++; + editor.execCommand(cmd, this.value); +}), items = []; + _$jscoverage['ui/editorui.js'][732]++; + for (var i in vals) { + _$jscoverage['ui/editorui.js'][733]++; + items.push({label: (vals[i] || editor.getLang()[cmd][i] || ""), value: i, theme: editor.options.theme, onclick: _onMenuClick}); +} + _$jscoverage['ui/editorui.js'][740]++; + var ui = new (editorui.MenuButton)({editor: editor, className: ("edui-for-" + cmd), title: (editor.getLang(("labelMap." + cmd)) || ""), "items": items, onbuttonclick: (function () { + _$jscoverage['ui/editorui.js'][746]++; + var value = (editor.queryCommandValue(cmd) || this.value); + _$jscoverage['ui/editorui.js'][747]++; + editor.execCommand(cmd, value); +})}); + _$jscoverage['ui/editorui.js'][750]++; + editorui.buttons[cmd] = ui; + _$jscoverage['ui/editorui.js'][751]++; + editor.addListener("selectionchange", (function () { + _$jscoverage['ui/editorui.js'][752]++; + var state = editor.queryCommandState(cmd); + _$jscoverage['ui/editorui.js'][753]++; + if ((state == -1)) { + _$jscoverage['ui/editorui.js'][754]++; + ui.setDisabled(true); + } + else { + _$jscoverage['ui/editorui.js'][756]++; + ui.setDisabled(false); + _$jscoverage['ui/editorui.js'][757]++; + var value = editor.queryCommandValue(cmd); + _$jscoverage['ui/editorui.js'][758]++; + ui.setValue(value); + _$jscoverage['ui/editorui.js'][759]++; + ui.setChecked(state); + } +})); + _$jscoverage['ui/editorui.js'][762]++; + return ui; +}); +})(cl); +} + _$jscoverage['ui/editorui.js'][767]++; + editorui.fullscreen = (function (editor, title) { + _$jscoverage['ui/editorui.js'][768]++; + title = (editor.options.labelMap.fullscreen || editor.getLang("labelMap.fullscreen") || ""); + _$jscoverage['ui/editorui.js'][769]++; + var ui = new (editorui.Button)({className: "edui-for-fullscreen", title: title, theme: editor.options.theme, onclick: (function () { + _$jscoverage['ui/editorui.js'][774]++; + if (editor.ui) { + _$jscoverage['ui/editorui.js'][775]++; + editor.ui.setFullScreen((! editor.ui.isFullScreen())); + } + _$jscoverage['ui/editorui.js'][777]++; + this.setChecked(editor.ui.isFullScreen()); +})}); + _$jscoverage['ui/editorui.js'][780]++; + editorui.buttons.fullscreen = ui; + _$jscoverage['ui/editorui.js'][781]++; + editor.addListener("selectionchange", (function () { + _$jscoverage['ui/editorui.js'][782]++; + var state = editor.queryCommandState("fullscreen"); + _$jscoverage['ui/editorui.js'][783]++; + ui.setDisabled((state == -1)); + _$jscoverage['ui/editorui.js'][784]++; + ui.setChecked(editor.ui.isFullScreen()); +})); + _$jscoverage['ui/editorui.js'][786]++; + return ui; +}); + _$jscoverage['ui/editorui.js'][790]++; + editorui.emotion = (function (editor, iframeUrl) { + _$jscoverage['ui/editorui.js'][791]++; + var cmd = "emotion"; + _$jscoverage['ui/editorui.js'][792]++; + var ui = new (editorui.MultiMenuPop)({title: (editor.options.labelMap[cmd] || editor.getLang(("labelMap." + cmd + "")) || ""), editor: editor, className: ("edui-for-" + cmd), iframeUrl: editor.ui.mapUrl((iframeUrl || (editor.options.iframeUrlMap || {})[cmd] || iframeUrlMap[cmd]))}); + _$jscoverage['ui/editorui.js'][798]++; + editorui.buttons[cmd] = ui; + _$jscoverage['ui/editorui.js'][800]++; + editor.addListener("selectionchange", (function () { + _$jscoverage['ui/editorui.js'][801]++; + ui.setDisabled((editor.queryCommandState(cmd) == -1)); +})); + _$jscoverage['ui/editorui.js'][803]++; + return ui; +}); + _$jscoverage['ui/editorui.js'][806]++; + editorui.autotypeset = (function (editor) { + _$jscoverage['ui/editorui.js'][807]++; + var ui = new (editorui.AutoTypeSetButton)({editor: editor, title: (editor.options.labelMap.autotypeset || editor.getLang("labelMap.autotypeset") || ""), className: "edui-for-autotypeset", onbuttonclick: (function () { + _$jscoverage['ui/editorui.js'][812]++; + editor.execCommand("autotypeset"); +})}); + _$jscoverage['ui/editorui.js'][815]++; + editorui.buttons.autotypeset = ui; + _$jscoverage['ui/editorui.js'][816]++; + editor.addListener("selectionchange", (function () { + _$jscoverage['ui/editorui.js'][817]++; + ui.setDisabled((editor.queryCommandState("autotypeset") == -1)); +})); + _$jscoverage['ui/editorui.js'][819]++; + return ui; +}); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/mask.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/mask.js new file mode 100644 index 000000000..c9498ee73 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/mask.js @@ -0,0 +1,127 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/mask.js']) { + _$jscoverage['ui/mask.js'] = []; + _$jscoverage['ui/mask.js'][3] = 0; + _$jscoverage['ui/mask.js'][4] = 0; + _$jscoverage['ui/mask.js'][9] = 0; + _$jscoverage['ui/mask.js'][10] = 0; + _$jscoverage['ui/mask.js'][11] = 0; + _$jscoverage['ui/mask.js'][13] = 0; + _$jscoverage['ui/mask.js'][15] = 0; + _$jscoverage['ui/mask.js'][18] = 0; + _$jscoverage['ui/mask.js'][19] = 0; + _$jscoverage['ui/mask.js'][20] = 0; + _$jscoverage['ui/mask.js'][21] = 0; + _$jscoverage['ui/mask.js'][22] = 0; + _$jscoverage['ui/mask.js'][28] = 0; + _$jscoverage['ui/mask.js'][29] = 0; + _$jscoverage['ui/mask.js'][30] = 0; + _$jscoverage['ui/mask.js'][33] = 0; + _$jscoverage['ui/mask.js'][34] = 0; + _$jscoverage['ui/mask.js'][37] = 0; + _$jscoverage['ui/mask.js'][40] = 0; + _$jscoverage['ui/mask.js'][43] = 0; + _$jscoverage['ui/mask.js'][44] = 0; + _$jscoverage['ui/mask.js'][45] = 0; + _$jscoverage['ui/mask.js'][46] = 0; + _$jscoverage['ui/mask.js'][49] = 0; +} +_$jscoverage['ui/mask.js'].source = ["///import core","///import uicore","(function (){"," var utils = baidu.editor.utils,"," domUtils = baidu.editor.dom.domUtils,"," UIBase = baidu.editor.ui.UIBase,"," uiUtils = baidu.editor.ui.uiUtils;"," "," var Mask = baidu.editor.ui.Mask = function (options){"," this.initOptions(options);"," this.initUIBase();"," };"," Mask.prototype = {"," getHtmlTpl: function (){"," return '<div id=\"##\" class=\"edui-mask %%\" onmousedown=\"return $$._onMouseDown(event, this);\"></div>';"," },"," postRender: function (){"," var me = this;"," domUtils.on(window, 'resize', function (){"," setTimeout(function (){"," if (!me.isHidden()) {"," me._fill();"," }"," });"," });"," },"," show: function (zIndex){"," this._fill();"," this.getDom().style.display = '';"," this.getDom().style.zIndex = zIndex;"," },"," hide: function (){"," this.getDom().style.display = 'none';"," this.getDom().style.zIndex = '';"," },"," isHidden: function (){"," return this.getDom().style.display == 'none';"," },"," _onMouseDown: function (){"," return false;"," },"," _fill: function (){"," var el = this.getDom();"," var vpRect = uiUtils.getViewportRect();"," el.style.width = vpRect.width + 'px';"," el.style.height = vpRect.height + 'px';"," }"," };"," utils.inherits(Mask, UIBase);","})();"]; +_$jscoverage['ui/mask.js'][3]++; +(function () { + _$jscoverage['ui/mask.js'][4]++; + var utils = baidu.editor.utils, domUtils = baidu.editor.dom.domUtils, UIBase = baidu.editor.ui.UIBase, uiUtils = baidu.editor.ui.uiUtils; + _$jscoverage['ui/mask.js'][9]++; + var Mask = (baidu.editor.ui.Mask = (function (options) { + _$jscoverage['ui/mask.js'][10]++; + this.initOptions(options); + _$jscoverage['ui/mask.js'][11]++; + this.initUIBase(); +})); + _$jscoverage['ui/mask.js'][13]++; + Mask.prototype = {getHtmlTpl: (function () { + _$jscoverage['ui/mask.js'][15]++; + return "
    "; +}), postRender: (function () { + _$jscoverage['ui/mask.js'][18]++; + var me = this; + _$jscoverage['ui/mask.js'][19]++; + domUtils.on(window, "resize", (function () { + _$jscoverage['ui/mask.js'][20]++; + setTimeout((function () { + _$jscoverage['ui/mask.js'][21]++; + if ((! me.isHidden())) { + _$jscoverage['ui/mask.js'][22]++; + me._fill(); + } +})); +})); +}), show: (function (zIndex) { + _$jscoverage['ui/mask.js'][28]++; + this._fill(); + _$jscoverage['ui/mask.js'][29]++; + this.getDom().style.display = ""; + _$jscoverage['ui/mask.js'][30]++; + this.getDom().style.zIndex = zIndex; +}), hide: (function () { + _$jscoverage['ui/mask.js'][33]++; + this.getDom().style.display = "none"; + _$jscoverage['ui/mask.js'][34]++; + this.getDom().style.zIndex = ""; +}), isHidden: (function () { + _$jscoverage['ui/mask.js'][37]++; + return (this.getDom().style.display == "none"); +}), _onMouseDown: (function () { + _$jscoverage['ui/mask.js'][40]++; + return false; +}), _fill: (function () { + _$jscoverage['ui/mask.js'][43]++; + var el = this.getDom(); + _$jscoverage['ui/mask.js'][44]++; + var vpRect = uiUtils.getViewportRect(); + _$jscoverage['ui/mask.js'][45]++; + el.style.width = (vpRect.width + "px"); + _$jscoverage['ui/mask.js'][46]++; + el.style.height = (vpRect.height + "px"); +})}; + _$jscoverage['ui/mask.js'][49]++; + utils.inherits(Mask, UIBase); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/menu.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/menu.js new file mode 100644 index 000000000..8f001266a --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/menu.js @@ -0,0 +1,541 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/menu.js']) { + _$jscoverage['ui/menu.js'] = []; + _$jscoverage['ui/menu.js'][5] = 0; + _$jscoverage['ui/menu.js'][6] = 0; + _$jscoverage['ui/menu.js'][15] = 0; + _$jscoverage['ui/menu.js'][16] = 0; + _$jscoverage['ui/menu.js'][19] = 0; + _$jscoverage['ui/menu.js'][21] = 0; + _$jscoverage['ui/menu.js'][26] = 0; + _$jscoverage['ui/menu.js'][29] = 0; + _$jscoverage['ui/menu.js'][33] = 0; + _$jscoverage['ui/menu.js'][34] = 0; + _$jscoverage['ui/menu.js'][35] = 0; + _$jscoverage['ui/menu.js'][38] = 0; + _$jscoverage['ui/menu.js'][39] = 0; + _$jscoverage['ui/menu.js'][40] = 0; + _$jscoverage['ui/menu.js'][41] = 0; + _$jscoverage['ui/menu.js'][42] = 0; + _$jscoverage['ui/menu.js'][43] = 0; + _$jscoverage['ui/menu.js'][44] = 0; + _$jscoverage['ui/menu.js'][45] = 0; + _$jscoverage['ui/menu.js'][50] = 0; + _$jscoverage['ui/menu.js'][54] = 0; + _$jscoverage['ui/menu.js'][55] = 0; + _$jscoverage['ui/menu.js'][59] = 0; + _$jscoverage['ui/menu.js'][60] = 0; + _$jscoverage['ui/menu.js'][62] = 0; + _$jscoverage['ui/menu.js'][63] = 0; + _$jscoverage['ui/menu.js'][64] = 0; + _$jscoverage['ui/menu.js'][65] = 0; + _$jscoverage['ui/menu.js'][67] = 0; + _$jscoverage['ui/menu.js'][71] = 0; + _$jscoverage['ui/menu.js'][72] = 0; + _$jscoverage['ui/menu.js'][73] = 0; + _$jscoverage['ui/menu.js'][74] = 0; + _$jscoverage['ui/menu.js'][75] = 0; + _$jscoverage['ui/menu.js'][77] = 0; + _$jscoverage['ui/menu.js'][78] = 0; + _$jscoverage['ui/menu.js'][79] = 0; + _$jscoverage['ui/menu.js'][80] = 0; + _$jscoverage['ui/menu.js'][81] = 0; + _$jscoverage['ui/menu.js'][82] = 0; + _$jscoverage['ui/menu.js'][85] = 0; + _$jscoverage['ui/menu.js'][88] = 0; + _$jscoverage['ui/menu.js'][89] = 0; + _$jscoverage['ui/menu.js'][90] = 0; + _$jscoverage['ui/menu.js'][92] = 0; + _$jscoverage['ui/menu.js'][93] = 0; + _$jscoverage['ui/menu.js'][94] = 0; + _$jscoverage['ui/menu.js'][95] = 0; + _$jscoverage['ui/menu.js'][101] = 0; + _$jscoverage['ui/menu.js'][102] = 0; + _$jscoverage['ui/menu.js'][103] = 0; + _$jscoverage['ui/menu.js'][104] = 0; + _$jscoverage['ui/menu.js'][105] = 0; + _$jscoverage['ui/menu.js'][106] = 0; + _$jscoverage['ui/menu.js'][109] = 0; + _$jscoverage['ui/menu.js'][112] = 0; + _$jscoverage['ui/menu.js'][113] = 0; + _$jscoverage['ui/menu.js'][115] = 0; + _$jscoverage['ui/menu.js'][118] = 0; + _$jscoverage['ui/menu.js'][121] = 0; + _$jscoverage['ui/menu.js'][127] = 0; + _$jscoverage['ui/menu.js'][128] = 0; + _$jscoverage['ui/menu.js'][129] = 0; + _$jscoverage['ui/menu.js'][130] = 0; + _$jscoverage['ui/menu.js'][131] = 0; + _$jscoverage['ui/menu.js'][132] = 0; + _$jscoverage['ui/menu.js'][133] = 0; + _$jscoverage['ui/menu.js'][136] = 0; + _$jscoverage['ui/menu.js'][138] = 0; + _$jscoverage['ui/menu.js'][143] = 0; + _$jscoverage['ui/menu.js'][144] = 0; + _$jscoverage['ui/menu.js'][148] = 0; + _$jscoverage['ui/menu.js'][149] = 0; + _$jscoverage['ui/menu.js'][150] = 0; + _$jscoverage['ui/menu.js'][154] = 0; + _$jscoverage['ui/menu.js'][158] = 0; + _$jscoverage['ui/menu.js'][165] = 0; + _$jscoverage['ui/menu.js'][172] = 0; + _$jscoverage['ui/menu.js'][173] = 0; + _$jscoverage['ui/menu.js'][174] = 0; + _$jscoverage['ui/menu.js'][175] = 0; + _$jscoverage['ui/menu.js'][176] = 0; + _$jscoverage['ui/menu.js'][179] = 0; + _$jscoverage['ui/menu.js'][180] = 0; + _$jscoverage['ui/menu.js'][181] = 0; + _$jscoverage['ui/menu.js'][182] = 0; + _$jscoverage['ui/menu.js'][183] = 0; + _$jscoverage['ui/menu.js'][185] = 0; + _$jscoverage['ui/menu.js'][186] = 0; + _$jscoverage['ui/menu.js'][187] = 0; + _$jscoverage['ui/menu.js'][188] = 0; + _$jscoverage['ui/menu.js'][190] = 0; + _$jscoverage['ui/menu.js'][191] = 0; + _$jscoverage['ui/menu.js'][193] = 0; + _$jscoverage['ui/menu.js'][194] = 0; + _$jscoverage['ui/menu.js'][195] = 0; + _$jscoverage['ui/menu.js'][198] = 0; + _$jscoverage['ui/menu.js'][199] = 0; + _$jscoverage['ui/menu.js'][200] = 0; + _$jscoverage['ui/menu.js'][201] = 0; + _$jscoverage['ui/menu.js'][203] = 0; + _$jscoverage['ui/menu.js'][206] = 0; + _$jscoverage['ui/menu.js'][207] = 0; + _$jscoverage['ui/menu.js'][208] = 0; + _$jscoverage['ui/menu.js'][211] = 0; + _$jscoverage['ui/menu.js'][212] = 0; + _$jscoverage['ui/menu.js'][213] = 0; + _$jscoverage['ui/menu.js'][214] = 0; + _$jscoverage['ui/menu.js'][215] = 0; + _$jscoverage['ui/menu.js'][216] = 0; + _$jscoverage['ui/menu.js'][217] = 0; + _$jscoverage['ui/menu.js'][218] = 0; + _$jscoverage['ui/menu.js'][223] = 0; + _$jscoverage['ui/menu.js'][224] = 0; + _$jscoverage['ui/menu.js'][225] = 0; + _$jscoverage['ui/menu.js'][226] = 0; + _$jscoverage['ui/menu.js'][227] = 0; + _$jscoverage['ui/menu.js'][228] = 0; + _$jscoverage['ui/menu.js'][229] = 0; + _$jscoverage['ui/menu.js'][230] = 0; + _$jscoverage['ui/menu.js'][232] = 0; + _$jscoverage['ui/menu.js'][238] = 0; + _$jscoverage['ui/menu.js'][243] = 0; + _$jscoverage['ui/menu.js'][246] = 0; + _$jscoverage['ui/menu.js'][247] = 0; + _$jscoverage['ui/menu.js'][251] = 0; + _$jscoverage['ui/menu.js'][252] = 0; + _$jscoverage['ui/menu.js'][253] = 0; + _$jscoverage['ui/menu.js'][254] = 0; + _$jscoverage['ui/menu.js'][256] = 0; + _$jscoverage['ui/menu.js'][261] = 0; + _$jscoverage['ui/menu.js'][262] = 0; + _$jscoverage['ui/menu.js'][263] = 0; + _$jscoverage['ui/menu.js'][264] = 0; + _$jscoverage['ui/menu.js'][265] = 0; + _$jscoverage['ui/menu.js'][266] = 0; + _$jscoverage['ui/menu.js'][267] = 0; + _$jscoverage['ui/menu.js'][268] = 0; + _$jscoverage['ui/menu.js'][271] = 0; + _$jscoverage['ui/menu.js'][274] = 0; + _$jscoverage['ui/menu.js'][275] = 0; +} +_$jscoverage['ui/menu.js'].source = ["///import core","///import uicore","///import ui\\popup.js","///import ui\\stateful.js","(function () {"," var utils = baidu.editor.utils,"," domUtils = baidu.editor.dom.domUtils,"," uiUtils = baidu.editor.ui.uiUtils,"," UIBase = baidu.editor.ui.UIBase,"," Popup = baidu.editor.ui.Popup,"," Stateful = baidu.editor.ui.Stateful,"," CellAlignPicker = baidu.editor.ui.CellAlignPicker,",""," Menu = baidu.editor.ui.Menu = function (options) {"," this.initOptions(options);"," this.initMenu();"," };",""," var menuSeparator = {"," renderHtml:function () {"," return '<div class=\"edui-menuitem edui-menuseparator\"><div class=\"edui-menuseparator-inner\"></div></div>';"," },"," postRender:function () {"," },"," queryAutoHide:function () {"," return true;"," }"," };"," Menu.prototype = {"," items:null,"," uiName:'menu',"," initMenu:function () {"," this.items = this.items || [];"," this.initPopup();"," this.initItems();"," },"," initItems:function () {"," for (var i = 0; i < this.items.length; i++) {"," var item = this.items[i];"," if (item == '-') {"," this.items[i] = this.getSeparator();"," } else if (!(item instanceof MenuItem)) {"," item.editor = this.editor;"," item.theme = this.editor.options.theme;"," this.items[i] = this.createItem(item);"," }"," }"," },"," getSeparator:function () {"," return menuSeparator;"," },"," createItem:function (item) {"," //新增一个参数menu, 该参数存储了menuItem所对应的menu引用"," item.menu = this;"," return new MenuItem(item);"," },"," _Popup_getContentHtmlTpl:Popup.prototype.getContentHtmlTpl,"," getContentHtmlTpl:function () {"," if (this.items.length == 0) {"," return this._Popup_getContentHtmlTpl();"," }"," var buff = [];"," for (var i = 0; i < this.items.length; i++) {"," var item = this.items[i];"," buff[i] = item.renderHtml();"," }"," return ('<div class=\"%%-body\">' + buff.join('') + '</div>');"," },"," _Popup_postRender:Popup.prototype.postRender,"," postRender:function () {"," var me = this;"," for (var i = 0; i < this.items.length; i++) {"," var item = this.items[i];"," item.ownerMenu = this;"," item.postRender();"," }"," domUtils.on(this.getDom(), 'mouseover', function (evt) {"," evt = evt || event;"," var rel = evt.relatedTarget || evt.fromElement;"," var el = me.getDom();"," if (!uiUtils.contains(el, rel) && el !== rel) {"," me.fireEvent('over');"," }"," });"," this._Popup_postRender();"," },"," queryAutoHide:function (el) {"," if (el) {"," if (uiUtils.contains(this.getDom(), el)) {"," return false;"," }"," for (var i = 0; i < this.items.length; i++) {"," var item = this.items[i];"," if (item.queryAutoHide(el) === false) {"," return false;"," }"," }"," }"," },"," clearItems:function () {"," for (var i = 0; i < this.items.length; i++) {"," var item = this.items[i];"," clearTimeout(item._showingTimer);"," clearTimeout(item._closingTimer);"," if (item.subMenu) {"," item.subMenu.destroy();"," }"," }"," this.items = [];"," },"," destroy:function () {"," if (this.getDom()) {"," domUtils.remove(this.getDom());"," }"," this.clearItems();"," },"," dispose:function () {"," this.destroy();"," }"," };"," utils.inherits(Menu, Popup);",""," /**"," * @update 2013/04/03 hancong03 新增一个参数menu, 该参数存储了menuItem所对应的menu引用"," * @type {Function}"," */"," var MenuItem = baidu.editor.ui.MenuItem = function (options) {"," this.initOptions(options);"," this.initUIBase();"," this.Stateful_init();"," if (this.subMenu && !(this.subMenu instanceof Menu)) {"," if (options.className && options.className.indexOf(\"aligntd\") != -1) {"," var me = this;",""," //获取单元格对齐初始状态"," this.subMenu.selected = this.editor.queryCommandValue( 'cellalignment' );",""," this.subMenu = new Popup({"," content:new CellAlignPicker(this.subMenu),"," parentMenu:me,"," editor:me.editor,"," destroy:function () {"," if (this.getDom()) {"," domUtils.remove(this.getDom());"," }"," }"," });"," this.subMenu.addListener(\"postRenderAfter\", function () {"," domUtils.on(this.getDom(), \"mouseover\", function () {"," me.addState('opened');"," });"," });"," } else {"," this.subMenu = new Menu(this.subMenu);"," }"," }"," };"," MenuItem.prototype = {"," label:'',"," subMenu:null,"," ownerMenu:null,"," uiName:'menuitem',"," alwalysHoverable:true,"," getHtmlTpl:function () {"," return '<div id=\"##\" class=\"%%\" stateful onclick=\"$$._onClick(event, this);\">' +"," '<div class=\"%%-body\">' +"," this.renderLabelHtml() +"," '</div>' +"," '</div>';"," },"," postRender:function () {"," var me = this;"," this.addListener('over', function () {"," me.ownerMenu.fireEvent('submenuover', me);"," if (me.subMenu) {"," me.delayShowSubMenu();"," }"," });"," if (this.subMenu) {"," this.getDom().className += ' edui-hassubmenu';"," this.subMenu.render();"," this.addListener('out', function () {"," me.delayHideSubMenu();"," });"," this.subMenu.addListener('over', function () {"," clearTimeout(me._closingTimer);"," me._closingTimer = null;"," me.addState('opened');"," });"," this.ownerMenu.addListener('hide', function () {"," me.hideSubMenu();"," });"," this.ownerMenu.addListener('submenuover', function (t, subMenu) {"," if (subMenu !== me) {"," me.delayHideSubMenu();"," }"," });"," this.subMenu._bakQueryAutoHide = this.subMenu.queryAutoHide;"," this.subMenu.queryAutoHide = function (el) {"," if (el && uiUtils.contains(me.getDom(), el)) {"," return false;"," }"," return this._bakQueryAutoHide(el);"," };"," }"," this.getDom().style.tabIndex = '-1';"," uiUtils.makeUnselectable(this.getDom());"," this.Stateful_postRender();"," },"," delayShowSubMenu:function () {"," var me = this;"," if (!me.isDisabled()) {"," me.addState('opened');"," clearTimeout(me._showingTimer);"," clearTimeout(me._closingTimer);"," me._closingTimer = null;"," me._showingTimer = setTimeout(function () {"," me.showSubMenu();"," }, 250);"," }"," },"," delayHideSubMenu:function () {"," var me = this;"," if (!me.isDisabled()) {"," me.removeState('opened');"," clearTimeout(me._showingTimer);"," if (!me._closingTimer) {"," me._closingTimer = setTimeout(function () {"," if (!me.hasState('opened')) {"," me.hideSubMenu();"," }"," me._closingTimer = null;"," }, 400);"," }"," }"," },"," renderLabelHtml:function () {"," return '<div class=\"edui-arrow\"></div>' +"," '<div class=\"edui-box edui-icon\"></div>' +"," '<div class=\"edui-box edui-label %%-label\">' + (this.label || '') + '</div>';"," },"," getStateDom:function () {"," return this.getDom();"," },"," queryAutoHide:function (el) {"," if (this.subMenu && this.hasState('opened')) {"," return this.subMenu.queryAutoHide(el);"," }"," },"," _onClick:function (event, this_) {"," if (this.hasState('disabled')) return;"," if (this.fireEvent('click', event, this_) !== false) {"," if (this.subMenu) {"," this.showSubMenu();"," } else {"," Popup.postHide(event);"," }"," }"," },"," showSubMenu:function () {"," var rect = uiUtils.getClientRect(this.getDom());"," rect.right -= 5;"," rect.left += 2;"," rect.width -= 7;"," rect.top -= 4;"," rect.bottom += 4;"," rect.height += 8;"," this.subMenu.showAnchorRect(rect, true, true);"," },"," hideSubMenu:function () {"," this.subMenu.hide();"," }"," };"," utils.inherits(MenuItem, UIBase);"," utils.extend(MenuItem.prototype, Stateful, true);","})();"]; +_$jscoverage['ui/menu.js'][5]++; +(function () { + _$jscoverage['ui/menu.js'][6]++; + var utils = baidu.editor.utils, domUtils = baidu.editor.dom.domUtils, uiUtils = baidu.editor.ui.uiUtils, UIBase = baidu.editor.ui.UIBase, Popup = baidu.editor.ui.Popup, Stateful = baidu.editor.ui.Stateful, CellAlignPicker = baidu.editor.ui.CellAlignPicker, Menu = (baidu.editor.ui.Menu = (function (options) { + _$jscoverage['ui/menu.js'][15]++; + this.initOptions(options); + _$jscoverage['ui/menu.js'][16]++; + this.initMenu(); +})); + _$jscoverage['ui/menu.js'][19]++; + var menuSeparator = {renderHtml: (function () { + _$jscoverage['ui/menu.js'][21]++; + return "
    "; +}), postRender: (function () { +}), queryAutoHide: (function () { + _$jscoverage['ui/menu.js'][26]++; + return true; +})}; + _$jscoverage['ui/menu.js'][29]++; + Menu.prototype = {items: null, uiName: "menu", initMenu: (function () { + _$jscoverage['ui/menu.js'][33]++; + this.items = (this.items || []); + _$jscoverage['ui/menu.js'][34]++; + this.initPopup(); + _$jscoverage['ui/menu.js'][35]++; + this.initItems(); +}), initItems: (function () { + _$jscoverage['ui/menu.js'][38]++; + for (var i = 0; (i < this.items.length); (i++)) { + _$jscoverage['ui/menu.js'][39]++; + var item = this.items[i]; + _$jscoverage['ui/menu.js'][40]++; + if ((item == "-")) { + _$jscoverage['ui/menu.js'][41]++; + this.items[i] = this.getSeparator(); + } + else { + _$jscoverage['ui/menu.js'][42]++; + if ((! (item instanceof MenuItem))) { + _$jscoverage['ui/menu.js'][43]++; + item.editor = this.editor; + _$jscoverage['ui/menu.js'][44]++; + item.theme = this.editor.options.theme; + _$jscoverage['ui/menu.js'][45]++; + this.items[i] = this.createItem(item); + } + } +} +}), getSeparator: (function () { + _$jscoverage['ui/menu.js'][50]++; + return menuSeparator; +}), createItem: (function (item) { + _$jscoverage['ui/menu.js'][54]++; + item.menu = this; + _$jscoverage['ui/menu.js'][55]++; + return new MenuItem(item); +}), _Popup_getContentHtmlTpl: Popup.prototype.getContentHtmlTpl, getContentHtmlTpl: (function () { + _$jscoverage['ui/menu.js'][59]++; + if ((this.items.length == 0)) { + _$jscoverage['ui/menu.js'][60]++; + return this._Popup_getContentHtmlTpl(); + } + _$jscoverage['ui/menu.js'][62]++; + var buff = []; + _$jscoverage['ui/menu.js'][63]++; + for (var i = 0; (i < this.items.length); (i++)) { + _$jscoverage['ui/menu.js'][64]++; + var item = this.items[i]; + _$jscoverage['ui/menu.js'][65]++; + buff[i] = item.renderHtml(); +} + _$jscoverage['ui/menu.js'][67]++; + return ("
    " + buff.join("") + "
    "); +}), _Popup_postRender: Popup.prototype.postRender, postRender: (function () { + _$jscoverage['ui/menu.js'][71]++; + var me = this; + _$jscoverage['ui/menu.js'][72]++; + for (var i = 0; (i < this.items.length); (i++)) { + _$jscoverage['ui/menu.js'][73]++; + var item = this.items[i]; + _$jscoverage['ui/menu.js'][74]++; + item.ownerMenu = this; + _$jscoverage['ui/menu.js'][75]++; + item.postRender(); +} + _$jscoverage['ui/menu.js'][77]++; + domUtils.on(this.getDom(), "mouseover", (function (evt) { + _$jscoverage['ui/menu.js'][78]++; + evt = (evt || event); + _$jscoverage['ui/menu.js'][79]++; + var rel = (evt.relatedTarget || evt.fromElement); + _$jscoverage['ui/menu.js'][80]++; + var el = me.getDom(); + _$jscoverage['ui/menu.js'][81]++; + if (((! uiUtils.contains(el, rel)) && (el !== rel))) { + _$jscoverage['ui/menu.js'][82]++; + me.fireEvent("over"); + } +})); + _$jscoverage['ui/menu.js'][85]++; + this._Popup_postRender(); +}), queryAutoHide: (function (el) { + _$jscoverage['ui/menu.js'][88]++; + if (el) { + _$jscoverage['ui/menu.js'][89]++; + if (uiUtils.contains(this.getDom(), el)) { + _$jscoverage['ui/menu.js'][90]++; + return false; + } + _$jscoverage['ui/menu.js'][92]++; + for (var i = 0; (i < this.items.length); (i++)) { + _$jscoverage['ui/menu.js'][93]++; + var item = this.items[i]; + _$jscoverage['ui/menu.js'][94]++; + if ((item.queryAutoHide(el) === false)) { + _$jscoverage['ui/menu.js'][95]++; + return false; + } +} + } +}), clearItems: (function () { + _$jscoverage['ui/menu.js'][101]++; + for (var i = 0; (i < this.items.length); (i++)) { + _$jscoverage['ui/menu.js'][102]++; + var item = this.items[i]; + _$jscoverage['ui/menu.js'][103]++; + clearTimeout(item._showingTimer); + _$jscoverage['ui/menu.js'][104]++; + clearTimeout(item._closingTimer); + _$jscoverage['ui/menu.js'][105]++; + if (item.subMenu) { + _$jscoverage['ui/menu.js'][106]++; + item.subMenu.destroy(); + } +} + _$jscoverage['ui/menu.js'][109]++; + this.items = []; +}), destroy: (function () { + _$jscoverage['ui/menu.js'][112]++; + if (this.getDom()) { + _$jscoverage['ui/menu.js'][113]++; + domUtils.remove(this.getDom()); + } + _$jscoverage['ui/menu.js'][115]++; + this.clearItems(); +}), dispose: (function () { + _$jscoverage['ui/menu.js'][118]++; + this.destroy(); +})}; + _$jscoverage['ui/menu.js'][121]++; + utils.inherits(Menu, Popup); + _$jscoverage['ui/menu.js'][127]++; + var MenuItem = (baidu.editor.ui.MenuItem = (function (options) { + _$jscoverage['ui/menu.js'][128]++; + this.initOptions(options); + _$jscoverage['ui/menu.js'][129]++; + this.initUIBase(); + _$jscoverage['ui/menu.js'][130]++; + this.Stateful_init(); + _$jscoverage['ui/menu.js'][131]++; + if ((this.subMenu && (! (this.subMenu instanceof Menu)))) { + _$jscoverage['ui/menu.js'][132]++; + if ((options.className && (options.className.indexOf("aligntd") != -1))) { + _$jscoverage['ui/menu.js'][133]++; + var me = this; + _$jscoverage['ui/menu.js'][136]++; + this.subMenu.selected = this.editor.queryCommandValue("cellalignment"); + _$jscoverage['ui/menu.js'][138]++; + this.subMenu = new Popup({content: new CellAlignPicker(this.subMenu), parentMenu: me, editor: me.editor, destroy: (function () { + _$jscoverage['ui/menu.js'][143]++; + if (this.getDom()) { + _$jscoverage['ui/menu.js'][144]++; + domUtils.remove(this.getDom()); + } +})}); + _$jscoverage['ui/menu.js'][148]++; + this.subMenu.addListener("postRenderAfter", (function () { + _$jscoverage['ui/menu.js'][149]++; + domUtils.on(this.getDom(), "mouseover", (function () { + _$jscoverage['ui/menu.js'][150]++; + me.addState("opened"); +})); +})); + } + else { + _$jscoverage['ui/menu.js'][154]++; + this.subMenu = new Menu(this.subMenu); + } + } +})); + _$jscoverage['ui/menu.js'][158]++; + MenuItem.prototype = {label: "", subMenu: null, ownerMenu: null, uiName: "menuitem", alwalysHoverable: true, getHtmlTpl: (function () { + _$jscoverage['ui/menu.js'][165]++; + return ("
    " + "
    " + this.renderLabelHtml() + "
    " + "
    "); +}), postRender: (function () { + _$jscoverage['ui/menu.js'][172]++; + var me = this; + _$jscoverage['ui/menu.js'][173]++; + this.addListener("over", (function () { + _$jscoverage['ui/menu.js'][174]++; + me.ownerMenu.fireEvent("submenuover", me); + _$jscoverage['ui/menu.js'][175]++; + if (me.subMenu) { + _$jscoverage['ui/menu.js'][176]++; + me.delayShowSubMenu(); + } +})); + _$jscoverage['ui/menu.js'][179]++; + if (this.subMenu) { + _$jscoverage['ui/menu.js'][180]++; + this.getDom().className += " edui-hassubmenu"; + _$jscoverage['ui/menu.js'][181]++; + this.subMenu.render(); + _$jscoverage['ui/menu.js'][182]++; + this.addListener("out", (function () { + _$jscoverage['ui/menu.js'][183]++; + me.delayHideSubMenu(); +})); + _$jscoverage['ui/menu.js'][185]++; + this.subMenu.addListener("over", (function () { + _$jscoverage['ui/menu.js'][186]++; + clearTimeout(me._closingTimer); + _$jscoverage['ui/menu.js'][187]++; + me._closingTimer = null; + _$jscoverage['ui/menu.js'][188]++; + me.addState("opened"); +})); + _$jscoverage['ui/menu.js'][190]++; + this.ownerMenu.addListener("hide", (function () { + _$jscoverage['ui/menu.js'][191]++; + me.hideSubMenu(); +})); + _$jscoverage['ui/menu.js'][193]++; + this.ownerMenu.addListener("submenuover", (function (t, subMenu) { + _$jscoverage['ui/menu.js'][194]++; + if ((subMenu !== me)) { + _$jscoverage['ui/menu.js'][195]++; + me.delayHideSubMenu(); + } +})); + _$jscoverage['ui/menu.js'][198]++; + this.subMenu._bakQueryAutoHide = this.subMenu.queryAutoHide; + _$jscoverage['ui/menu.js'][199]++; + this.subMenu.queryAutoHide = (function (el) { + _$jscoverage['ui/menu.js'][200]++; + if ((el && uiUtils.contains(me.getDom(), el))) { + _$jscoverage['ui/menu.js'][201]++; + return false; + } + _$jscoverage['ui/menu.js'][203]++; + return this._bakQueryAutoHide(el); +}); + } + _$jscoverage['ui/menu.js'][206]++; + this.getDom().style.tabIndex = "-1"; + _$jscoverage['ui/menu.js'][207]++; + uiUtils.makeUnselectable(this.getDom()); + _$jscoverage['ui/menu.js'][208]++; + this.Stateful_postRender(); +}), delayShowSubMenu: (function () { + _$jscoverage['ui/menu.js'][211]++; + var me = this; + _$jscoverage['ui/menu.js'][212]++; + if ((! me.isDisabled())) { + _$jscoverage['ui/menu.js'][213]++; + me.addState("opened"); + _$jscoverage['ui/menu.js'][214]++; + clearTimeout(me._showingTimer); + _$jscoverage['ui/menu.js'][215]++; + clearTimeout(me._closingTimer); + _$jscoverage['ui/menu.js'][216]++; + me._closingTimer = null; + _$jscoverage['ui/menu.js'][217]++; + me._showingTimer = setTimeout((function () { + _$jscoverage['ui/menu.js'][218]++; + me.showSubMenu(); +}), 250); + } +}), delayHideSubMenu: (function () { + _$jscoverage['ui/menu.js'][223]++; + var me = this; + _$jscoverage['ui/menu.js'][224]++; + if ((! me.isDisabled())) { + _$jscoverage['ui/menu.js'][225]++; + me.removeState("opened"); + _$jscoverage['ui/menu.js'][226]++; + clearTimeout(me._showingTimer); + _$jscoverage['ui/menu.js'][227]++; + if ((! me._closingTimer)) { + _$jscoverage['ui/menu.js'][228]++; + me._closingTimer = setTimeout((function () { + _$jscoverage['ui/menu.js'][229]++; + if ((! me.hasState("opened"))) { + _$jscoverage['ui/menu.js'][230]++; + me.hideSubMenu(); + } + _$jscoverage['ui/menu.js'][232]++; + me._closingTimer = null; +}), 400); + } + } +}), renderLabelHtml: (function () { + _$jscoverage['ui/menu.js'][238]++; + return ("
    " + "
    " + "
    " + (this.label || "") + "
    "); +}), getStateDom: (function () { + _$jscoverage['ui/menu.js'][243]++; + return this.getDom(); +}), queryAutoHide: (function (el) { + _$jscoverage['ui/menu.js'][246]++; + if ((this.subMenu && this.hasState("opened"))) { + _$jscoverage['ui/menu.js'][247]++; + return this.subMenu.queryAutoHide(el); + } +}), _onClick: (function (event, this_) { + _$jscoverage['ui/menu.js'][251]++; + if (this.hasState("disabled")) { + _$jscoverage['ui/menu.js'][251]++; + return; + } + _$jscoverage['ui/menu.js'][252]++; + if ((this.fireEvent("click", event, this_) !== false)) { + _$jscoverage['ui/menu.js'][253]++; + if (this.subMenu) { + _$jscoverage['ui/menu.js'][254]++; + this.showSubMenu(); + } + else { + _$jscoverage['ui/menu.js'][256]++; + Popup.postHide(event); + } + } +}), showSubMenu: (function () { + _$jscoverage['ui/menu.js'][261]++; + var rect = uiUtils.getClientRect(this.getDom()); + _$jscoverage['ui/menu.js'][262]++; + rect.right -= 5; + _$jscoverage['ui/menu.js'][263]++; + rect.left += 2; + _$jscoverage['ui/menu.js'][264]++; + rect.width -= 7; + _$jscoverage['ui/menu.js'][265]++; + rect.top -= 4; + _$jscoverage['ui/menu.js'][266]++; + rect.bottom += 4; + _$jscoverage['ui/menu.js'][267]++; + rect.height += 8; + _$jscoverage['ui/menu.js'][268]++; + this.subMenu.showAnchorRect(rect, true, true); +}), hideSubMenu: (function () { + _$jscoverage['ui/menu.js'][271]++; + this.subMenu.hide(); +})}; + _$jscoverage['ui/menu.js'][274]++; + utils.inherits(MenuItem, UIBase); + _$jscoverage['ui/menu.js'][275]++; + utils.extend(MenuItem.prototype, Stateful, true); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/menubutton.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/menubutton.js new file mode 100644 index 000000000..00f482ad9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/menubutton.js @@ -0,0 +1,104 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/menubutton.js']) { + _$jscoverage['ui/menubutton.js'] = []; + _$jscoverage['ui/menubutton.js'][5] = 0; + _$jscoverage['ui/menubutton.js'][6] = 0; + _$jscoverage['ui/menubutton.js'][10] = 0; + _$jscoverage['ui/menubutton.js'][11] = 0; + _$jscoverage['ui/menubutton.js'][13] = 0; + _$jscoverage['ui/menubutton.js'][15] = 0; + _$jscoverage['ui/menubutton.js'][16] = 0; + _$jscoverage['ui/menubutton.js'][17] = 0; + _$jscoverage['ui/menubutton.js'][22] = 0; + _$jscoverage['ui/menubutton.js'][23] = 0; + _$jscoverage['ui/menubutton.js'][24] = 0; + _$jscoverage['ui/menubutton.js'][25] = 0; + _$jscoverage['ui/menubutton.js'][26] = 0; + _$jscoverage['ui/menubutton.js'][27] = 0; + _$jscoverage['ui/menubutton.js'][28] = 0; + _$jscoverage['ui/menubutton.js'][32] = 0; + _$jscoverage['ui/menubutton.js'][35] = 0; + _$jscoverage['ui/menubutton.js'][39] = 0; +} +_$jscoverage['ui/menubutton.js'].source = ["///import core","///import uicore","///import ui/menu.js","///import ui/splitbutton.js","(function (){"," var utils = baidu.editor.utils,"," Menu = baidu.editor.ui.Menu,"," SplitButton = baidu.editor.ui.SplitButton,"," MenuButton = baidu.editor.ui.MenuButton = function (options){"," this.initOptions(options);"," this.initMenuButton();"," };"," MenuButton.prototype = {"," initMenuButton: function (){"," var me = this;"," this.uiName = \"menubutton\";"," this.popup = new Menu({"," items: me.items,"," className: me.className,"," editor:me.editor"," });"," this.popup.addListener('show', function (){"," var list = this;"," for (var i=0; i<list.items.length; i++) {"," list.items[i].removeState('checked');"," if (list.items[i].value == me._value) {"," list.items[i].addState('checked');"," this.value = me._value;"," }"," }"," });"," this.initSplitButton();"," },"," setValue : function(value){"," this._value = value;"," }"," "," };"," utils.inherits(MenuButton, SplitButton);","})();"]; +_$jscoverage['ui/menubutton.js'][5]++; +(function () { + _$jscoverage['ui/menubutton.js'][6]++; + var utils = baidu.editor.utils, Menu = baidu.editor.ui.Menu, SplitButton = baidu.editor.ui.SplitButton, MenuButton = (baidu.editor.ui.MenuButton = (function (options) { + _$jscoverage['ui/menubutton.js'][10]++; + this.initOptions(options); + _$jscoverage['ui/menubutton.js'][11]++; + this.initMenuButton(); +})); + _$jscoverage['ui/menubutton.js'][13]++; + MenuButton.prototype = {initMenuButton: (function () { + _$jscoverage['ui/menubutton.js'][15]++; + var me = this; + _$jscoverage['ui/menubutton.js'][16]++; + this.uiName = "menubutton"; + _$jscoverage['ui/menubutton.js'][17]++; + this.popup = new Menu({items: me.items, className: me.className, editor: me.editor}); + _$jscoverage['ui/menubutton.js'][22]++; + this.popup.addListener("show", (function () { + _$jscoverage['ui/menubutton.js'][23]++; + var list = this; + _$jscoverage['ui/menubutton.js'][24]++; + for (var i = 0; (i < list.items.length); (i++)) { + _$jscoverage['ui/menubutton.js'][25]++; + list.items[i].removeState("checked"); + _$jscoverage['ui/menubutton.js'][26]++; + if ((list.items[i].value == me._value)) { + _$jscoverage['ui/menubutton.js'][27]++; + list.items[i].addState("checked"); + _$jscoverage['ui/menubutton.js'][28]++; + this.value = me._value; + } +} +})); + _$jscoverage['ui/menubutton.js'][32]++; + this.initSplitButton(); +}), setValue: (function (value) { + _$jscoverage['ui/menubutton.js'][35]++; + this._value = value; +})}; + _$jscoverage['ui/menubutton.js'][39]++; + utils.inherits(MenuButton, SplitButton); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/multiMenu.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/multiMenu.js new file mode 100644 index 000000000..78557ac8f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/multiMenu.js @@ -0,0 +1,94 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/multiMenu.js']) { + _$jscoverage['ui/multiMenu.js'] = []; + _$jscoverage['ui/multiMenu.js'][4] = 0; + _$jscoverage['ui/multiMenu.js'][5] = 0; + _$jscoverage['ui/multiMenu.js'][9] = 0; + _$jscoverage['ui/multiMenu.js'][10] = 0; + _$jscoverage['ui/multiMenu.js'][13] = 0; + _$jscoverage['ui/multiMenu.js'][15] = 0; + _$jscoverage['ui/multiMenu.js'][16] = 0; + _$jscoverage['ui/multiMenu.js'][21] = 0; + _$jscoverage['ui/multiMenu.js'][22] = 0; + _$jscoverage['ui/multiMenu.js'][23] = 0; + _$jscoverage['ui/multiMenu.js'][24] = 0; + _$jscoverage['ui/multiMenu.js'][30] = 0; + _$jscoverage['ui/multiMenu.js'][31] = 0; + _$jscoverage['ui/multiMenu.js'][33] = 0; + _$jscoverage['ui/multiMenu.js'][38] = 0; +} +_$jscoverage['ui/multiMenu.js'].source = ["///import core","///import uicore"," ///commands 表情","(function(){"," var utils = baidu.editor.utils,"," Popup = baidu.editor.ui.Popup,"," SplitButton = baidu.editor.ui.SplitButton,"," MultiMenuPop = baidu.editor.ui.MultiMenuPop = function(options){"," this.initOptions(options);"," this.initMultiMenu();"," };",""," MultiMenuPop.prototype = {"," initMultiMenu: function (){"," var me = this;"," this.popup = new Popup({"," content: '',"," editor : me.editor,"," iframe_rendered: false,"," onshow: function (){"," if (!this.iframe_rendered) {"," this.iframe_rendered = true;"," this.getDom('content').innerHTML = '<iframe id=\"'+me.id+'_iframe\" src=\"'+ me.iframeUrl +'\" frameborder=\"0\"></iframe>';"," me.editor.container.style.zIndex && (this.getDom().style.zIndex = me.editor.container.style.zIndex * 1 + 1);"," }"," }"," // canSideUp:false,"," // canSideLeft:false"," });"," this.onbuttonclick = function(){"," this.showPopup();"," };"," this.initSplitButton();"," }",""," };",""," utils.inherits(MultiMenuPop, SplitButton);","})();"]; +_$jscoverage['ui/multiMenu.js'][4]++; +(function () { + _$jscoverage['ui/multiMenu.js'][5]++; + var utils = baidu.editor.utils, Popup = baidu.editor.ui.Popup, SplitButton = baidu.editor.ui.SplitButton, MultiMenuPop = (baidu.editor.ui.MultiMenuPop = (function (options) { + _$jscoverage['ui/multiMenu.js'][9]++; + this.initOptions(options); + _$jscoverage['ui/multiMenu.js'][10]++; + this.initMultiMenu(); +})); + _$jscoverage['ui/multiMenu.js'][13]++; + MultiMenuPop.prototype = {initMultiMenu: (function () { + _$jscoverage['ui/multiMenu.js'][15]++; + var me = this; + _$jscoverage['ui/multiMenu.js'][16]++; + this.popup = new Popup({content: "", editor: me.editor, iframe_rendered: false, onshow: (function () { + _$jscoverage['ui/multiMenu.js'][21]++; + if ((! this.iframe_rendered)) { + _$jscoverage['ui/multiMenu.js'][22]++; + this.iframe_rendered = true; + _$jscoverage['ui/multiMenu.js'][23]++; + this.getDom("content").innerHTML = (""); + _$jscoverage['ui/multiMenu.js'][24]++; + (me.editor.container.style.zIndex && (this.getDom().style.zIndex = ((me.editor.container.style.zIndex * 1) + 1))); + } +})}); + _$jscoverage['ui/multiMenu.js'][30]++; + this.onbuttonclick = (function () { + _$jscoverage['ui/multiMenu.js'][31]++; + this.showPopup(); +}); + _$jscoverage['ui/multiMenu.js'][33]++; + this.initSplitButton(); +})}; + _$jscoverage['ui/multiMenu.js'][38]++; + utils.inherits(MultiMenuPop, SplitButton); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/pastepicker.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/pastepicker.js new file mode 100644 index 000000000..d17ca60dc --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/pastepicker.js @@ -0,0 +1,125 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/pastepicker.js']) { + _$jscoverage['ui/pastepicker.js'] = []; + _$jscoverage['ui/pastepicker.js'][3] = 0; + _$jscoverage['ui/pastepicker.js'][4] = 0; + _$jscoverage['ui/pastepicker.js'][9] = 0; + _$jscoverage['ui/pastepicker.js'][10] = 0; + _$jscoverage['ui/pastepicker.js'][11] = 0; + _$jscoverage['ui/pastepicker.js'][13] = 0; + _$jscoverage['ui/pastepicker.js'][15] = 0; + _$jscoverage['ui/pastepicker.js'][16] = 0; + _$jscoverage['ui/pastepicker.js'][19] = 0; + _$jscoverage['ui/pastepicker.js'][34] = 0; + _$jscoverage['ui/pastepicker.js'][37] = 0; + _$jscoverage['ui/pastepicker.js'][38] = 0; + _$jscoverage['ui/pastepicker.js'][41] = 0; + _$jscoverage['ui/pastepicker.js'][45] = 0; + _$jscoverage['ui/pastepicker.js'][46] = 0; + _$jscoverage['ui/pastepicker.js'][48] = 0; + _$jscoverage['ui/pastepicker.js'][50] = 0; + _$jscoverage['ui/pastepicker.js'][51] = 0; + _$jscoverage['ui/pastepicker.js'][52] = 0; + _$jscoverage['ui/pastepicker.js'][54] = 0; + _$jscoverage['ui/pastepicker.js'][55] = 0; + _$jscoverage['ui/pastepicker.js'][60] = 0; + _$jscoverage['ui/pastepicker.js'][61] = 0; +} +_$jscoverage['ui/pastepicker.js'].source = ["///import core","///import uicore","(function () {"," var utils = baidu.editor.utils,"," Stateful = baidu.editor.ui.Stateful,"," uiUtils = baidu.editor.ui.uiUtils,"," UIBase = baidu.editor.ui.UIBase;",""," var PastePicker = baidu.editor.ui.PastePicker = function (options) {"," this.initOptions(options);"," this.initPastePicker();"," };"," PastePicker.prototype = {"," initPastePicker:function () {"," this.initUIBase();"," this.Stateful_init();"," },"," getHtmlTpl:function () {"," return '<div class=\"edui-pasteicon\" onclick=\"$$._onClick(this)\"></div>' +"," '<div class=\"edui-pastecontainer\">' +"," '<div class=\"edui-title\">' + this.editor.getLang(\"pasteOpt\") + '</div>' +"," '<div class=\"edui-button\">' +"," '<div title=\"' + this.editor.getLang(\"pasteSourceFormat\") + '\" onclick=\"$$.format(false)\" stateful>' +"," '<div class=\"edui-richtxticon\"></div></div>' +"," '<div title=\"' + this.editor.getLang(\"tagFormat\") + '\" onclick=\"$$.format(2)\" stateful>' +"," '<div class=\"edui-tagicon\"></div></div>' +"," '<div title=\"' + this.editor.getLang(\"pasteTextFormat\") + '\" onclick=\"$$.format(true)\" stateful>' +"," '<div class=\"edui-plaintxticon\"></div></div>' +"," '</div>' +"," '</div>' +"," '</div>'"," },"," getStateDom:function () {"," return this.target;"," },"," format:function (param) {"," this.editor.ui._isTransfer = true;"," this.editor.fireEvent('pasteTransfer', param);"," },"," _onClick:function (cur) {"," var node = domUtils.getNextDomNode(cur),"," screenHt = uiUtils.getViewportRect().height,"," subPop = uiUtils.getClientRect(node);",""," if ((subPop.top + subPop.height) > screenHt)"," node.style.top = (-subPop.height - cur.offsetHeight) + \"px\";"," else"," node.style.top = \"\";",""," if (/hidden/ig.test(domUtils.getComputedStyle(node, \"visibility\"))) {"," node.style.visibility = \"visible\";"," domUtils.addClass(cur, \"edui-state-opened\");"," } else {"," node.style.visibility = \"hidden\";"," domUtils.removeClasses(cur, \"edui-state-opened\")"," }"," },"," _UIBase_render:UIBase.prototype.render"," };"," utils.inherits(PastePicker, UIBase);"," utils.extend(PastePicker.prototype, Stateful, true);","})();","","","",""]; +_$jscoverage['ui/pastepicker.js'][3]++; +(function () { + _$jscoverage['ui/pastepicker.js'][4]++; + var utils = baidu.editor.utils, Stateful = baidu.editor.ui.Stateful, uiUtils = baidu.editor.ui.uiUtils, UIBase = baidu.editor.ui.UIBase; + _$jscoverage['ui/pastepicker.js'][9]++; + var PastePicker = (baidu.editor.ui.PastePicker = (function (options) { + _$jscoverage['ui/pastepicker.js'][10]++; + this.initOptions(options); + _$jscoverage['ui/pastepicker.js'][11]++; + this.initPastePicker(); +})); + _$jscoverage['ui/pastepicker.js'][13]++; + PastePicker.prototype = {initPastePicker: (function () { + _$jscoverage['ui/pastepicker.js'][15]++; + this.initUIBase(); + _$jscoverage['ui/pastepicker.js'][16]++; + this.Stateful_init(); +}), getHtmlTpl: (function () { + _$jscoverage['ui/pastepicker.js'][19]++; + return ("
    " + "
    " + "
    " + this.editor.getLang("pasteOpt") + "
    " + "
    " + "
    " + "
    " + "
    " + "
    " + "
    " + "
    " + "
    " + "
    " + "
    "); +}), getStateDom: (function () { + _$jscoverage['ui/pastepicker.js'][34]++; + return this.target; +}), format: (function (param) { + _$jscoverage['ui/pastepicker.js'][37]++; + this.editor.ui._isTransfer = true; + _$jscoverage['ui/pastepicker.js'][38]++; + this.editor.fireEvent("pasteTransfer", param); +}), _onClick: (function (cur) { + _$jscoverage['ui/pastepicker.js'][41]++; + var node = domUtils.getNextDomNode(cur), screenHt = uiUtils.getViewportRect().height, subPop = uiUtils.getClientRect(node); + _$jscoverage['ui/pastepicker.js'][45]++; + if (((subPop.top + subPop.height) > screenHt)) { + _$jscoverage['ui/pastepicker.js'][46]++; + node.style.top = (((- subPop.height) - cur.offsetHeight) + "px"); + } + else { + _$jscoverage['ui/pastepicker.js'][48]++; + node.style.top = ""; + } + _$jscoverage['ui/pastepicker.js'][50]++; + if (/hidden/gi.test(domUtils.getComputedStyle(node, "visibility"))) { + _$jscoverage['ui/pastepicker.js'][51]++; + node.style.visibility = "visible"; + _$jscoverage['ui/pastepicker.js'][52]++; + domUtils.addClass(cur, "edui-state-opened"); + } + else { + _$jscoverage['ui/pastepicker.js'][54]++; + node.style.visibility = "hidden"; + _$jscoverage['ui/pastepicker.js'][55]++; + domUtils.removeClasses(cur, "edui-state-opened"); + } +}), _UIBase_render: UIBase.prototype.render}; + _$jscoverage['ui/pastepicker.js'][60]++; + utils.inherits(PastePicker, UIBase); + _$jscoverage['ui/pastepicker.js'][61]++; + utils.extend(PastePicker.prototype, Stateful, true); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/popup.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/popup.js new file mode 100644 index 000000000..ced902dd1 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/popup.js @@ -0,0 +1,433 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/popup.js']) { + _$jscoverage['ui/popup.js'] = []; + _$jscoverage['ui/popup.js'][3] = 0; + _$jscoverage['ui/popup.js'][4] = 0; + _$jscoverage['ui/popup.js'][9] = 0; + _$jscoverage['ui/popup.js'][10] = 0; + _$jscoverage['ui/popup.js'][13] = 0; + _$jscoverage['ui/popup.js'][14] = 0; + _$jscoverage['ui/popup.js'][15] = 0; + _$jscoverage['ui/popup.js'][16] = 0; + _$jscoverage['ui/popup.js'][17] = 0; + _$jscoverage['ui/popup.js'][18] = 0; + _$jscoverage['ui/popup.js'][19] = 0; + _$jscoverage['ui/popup.js'][20] = 0; + _$jscoverage['ui/popup.js'][25] = 0; + _$jscoverage['ui/popup.js'][26] = 0; + _$jscoverage['ui/popup.js'][29] = 0; + _$jscoverage['ui/popup.js'][31] = 0; + _$jscoverage['ui/popup.js'][33] = 0; + _$jscoverage['ui/popup.js'][41] = 0; + _$jscoverage['ui/popup.js'][42] = 0; + _$jscoverage['ui/popup.js'][45] = 0; + _$jscoverage['ui/popup.js'][56] = 0; + _$jscoverage['ui/popup.js'][57] = 0; + _$jscoverage['ui/popup.js'][58] = 0; + _$jscoverage['ui/popup.js'][60] = 0; + _$jscoverage['ui/popup.js'][62] = 0; + _$jscoverage['ui/popup.js'][70] = 0; + _$jscoverage['ui/popup.js'][71] = 0; + _$jscoverage['ui/popup.js'][75] = 0; + _$jscoverage['ui/popup.js'][77] = 0; + _$jscoverage['ui/popup.js'][79] = 0; + _$jscoverage['ui/popup.js'][85] = 0; + _$jscoverage['ui/popup.js'][86] = 0; + _$jscoverage['ui/popup.js'][87] = 0; + _$jscoverage['ui/popup.js'][91] = 0; + _$jscoverage['ui/popup.js'][93] = 0; + _$jscoverage['ui/popup.js'][95] = 0; + _$jscoverage['ui/popup.js'][96] = 0; + _$jscoverage['ui/popup.js'][98] = 0; + _$jscoverage['ui/popup.js'][101] = 0; + _$jscoverage['ui/popup.js'][103] = 0; + _$jscoverage['ui/popup.js'][107] = 0; + _$jscoverage['ui/popup.js'][116] = 0; + _$jscoverage['ui/popup.js'][118] = 0; + _$jscoverage['ui/popup.js'][120] = 0; + _$jscoverage['ui/popup.js'][127] = 0; + _$jscoverage['ui/popup.js'][128] = 0; + _$jscoverage['ui/popup.js'][129] = 0; + _$jscoverage['ui/popup.js'][132] = 0; + _$jscoverage['ui/popup.js'][133] = 0; + _$jscoverage['ui/popup.js'][137] = 0; + _$jscoverage['ui/popup.js'][138] = 0; + _$jscoverage['ui/popup.js'][141] = 0; + _$jscoverage['ui/popup.js'][142] = 0; + _$jscoverage['ui/popup.js'][144] = 0; + _$jscoverage['ui/popup.js'][145] = 0; + _$jscoverage['ui/popup.js'][146] = 0; + _$jscoverage['ui/popup.js'][147] = 0; + _$jscoverage['ui/popup.js'][148] = 0; + _$jscoverage['ui/popup.js'][149] = 0; + _$jscoverage['ui/popup.js'][150] = 0; + _$jscoverage['ui/popup.js'][152] = 0; + _$jscoverage['ui/popup.js'][154] = 0; + _$jscoverage['ui/popup.js'][155] = 0; + _$jscoverage['ui/popup.js'][156] = 0; + _$jscoverage['ui/popup.js'][157] = 0; + _$jscoverage['ui/popup.js'][160] = 0; + _$jscoverage['ui/popup.js'][163] = 0; + _$jscoverage['ui/popup.js'][164] = 0; + _$jscoverage['ui/popup.js'][165] = 0; + _$jscoverage['ui/popup.js'][166] = 0; + _$jscoverage['ui/popup.js'][168] = 0; + _$jscoverage['ui/popup.js'][169] = 0; + _$jscoverage['ui/popup.js'][170] = 0; + _$jscoverage['ui/popup.js'][171] = 0; + _$jscoverage['ui/popup.js'][172] = 0; + _$jscoverage['ui/popup.js'][173] = 0; + _$jscoverage['ui/popup.js'][175] = 0; + _$jscoverage['ui/popup.js'][176] = 0; + _$jscoverage['ui/popup.js'][177] = 0; + _$jscoverage['ui/popup.js'][178] = 0; + _$jscoverage['ui/popup.js'][181] = 0; + _$jscoverage['ui/popup.js'][182] = 0; + _$jscoverage['ui/popup.js'][186] = 0; + _$jscoverage['ui/popup.js'][187] = 0; + _$jscoverage['ui/popup.js'][188] = 0; + _$jscoverage['ui/popup.js'][189] = 0; + _$jscoverage['ui/popup.js'][190] = 0; + _$jscoverage['ui/popup.js'][195] = 0; + _$jscoverage['ui/popup.js'][196] = 0; + _$jscoverage['ui/popup.js'][197] = 0; + _$jscoverage['ui/popup.js'][205] = 0; + _$jscoverage['ui/popup.js'][208] = 0; + _$jscoverage['ui/popup.js'][209] = 0; + _$jscoverage['ui/popup.js'][210] = 0; + _$jscoverage['ui/popup.js'][211] = 0; + _$jscoverage['ui/popup.js'][215] = 0; + _$jscoverage['ui/popup.js'][219] = 0; + _$jscoverage['ui/popup.js'][222] = 0; + _$jscoverage['ui/popup.js'][223] = 0; + _$jscoverage['ui/popup.js'][226] = 0; + _$jscoverage['ui/popup.js'][227] = 0; + _$jscoverage['ui/popup.js'][228] = 0; + _$jscoverage['ui/popup.js'][229] = 0; + _$jscoverage['ui/popup.js'][230] = 0; + _$jscoverage['ui/popup.js'][235] = 0; + _$jscoverage['ui/popup.js'][238] = 0; + _$jscoverage['ui/popup.js'][240] = 0; + _$jscoverage['ui/popup.js'][241] = 0; + _$jscoverage['ui/popup.js'][242] = 0; + _$jscoverage['ui/popup.js'][244] = 0; + _$jscoverage['ui/popup.js'][245] = 0; +} +_$jscoverage['ui/popup.js'].source = ["///import core","///import uicore","(function () {"," var utils = baidu.editor.utils,"," uiUtils = baidu.editor.ui.uiUtils,"," domUtils = baidu.editor.dom.domUtils,"," UIBase = baidu.editor.ui.UIBase,"," Popup = baidu.editor.ui.Popup = function (options){"," this.initOptions(options);"," this.initPopup();"," };",""," var allPopups = [];"," function closeAllPopup( evt,el ){"," for ( var i = 0; i < allPopups.length; i++ ) {"," var pop = allPopups[i];"," if (!pop.isHidden()) {"," if (pop.queryAutoHide(el) !== false) {"," if(evt&&/scroll/ig.test(evt.type)&&pop.className==\"edui-wordpastepop\") return;"," pop.hide();"," }"," }"," }",""," if(allPopups.length)"," pop.editor.fireEvent(\"afterhidepop\");"," }",""," Popup.postHide = closeAllPopup;",""," var ANCHOR_CLASSES = ['edui-anchor-topleft','edui-anchor-topright',"," 'edui-anchor-bottomleft','edui-anchor-bottomright'];"," Popup.prototype = {"," SHADOW_RADIUS: 5,"," content: null,"," _hidden: false,"," autoRender: true,"," canSideLeft: true,"," canSideUp: true,"," initPopup: function (){"," this.initUIBase();"," allPopups.push( this );"," },"," getHtmlTpl: function (){"," return '<div id=\"##\" class=\"edui-popup %%\" onmousedown=\"return false;\">' +"," ' <div id=\"##_body\" class=\"edui-popup-body\">' +"," ' <iframe style=\"position:absolute;z-index:-1;left:0;top:0;background-color: transparent;\" frameborder=\"0\" width=\"100%\" height=\"100%\" src=\"javascript:\"></iframe>' +"," ' <div class=\"edui-shadow\"></div>' +"," ' <div id=\"##_content\" class=\"edui-popup-content\">' +"," this.getContentHtmlTpl() +"," ' </div>' +"," ' </div>' +"," '</div>';"," },"," getContentHtmlTpl: function (){"," if(this.content){"," if (typeof this.content == 'string') {"," return this.content;"," }"," return this.content.renderHtml();"," }else{"," return ''"," }",""," },"," _UIBase_postRender: UIBase.prototype.postRender,"," postRender: function (){","",""," if (this.content instanceof UIBase) {"," this.content.postRender();"," }",""," //捕获鼠标滚轮"," if( this.captureWheel && !this.captured ) {",""," this.captured = true;",""," var winHeight = ( document.documentElement.clientHeight || document.body.clientHeight ) - 80,"," _height = this.getDom().offsetHeight,"," _top = domUtils.getXY( this.combox.getDom() ).y,"," content = this.getDom('content'),"," me = this;",""," while( _top + _height > winHeight ) {"," _height -= 30;"," content.style.height = _height + 'px';"," }",""," //阻止在combox上的鼠标滚轮事件, 防止用户的正常操作被误解"," if( window.XMLHttpRequest ) {",""," domUtils.on( content, ( 'onmousewheel' in document.body ) ? 'mousewheel' :'DOMMouseScroll' , function(e){",""," if(e.preventDefault) {"," e.preventDefault();"," } else {"," e.returnValue = false;"," }",""," if( e.wheelDelta ) {",""," content.scrollTop -= ( e.wheelDelta / 120 )*60;",""," } else {",""," content.scrollTop -= ( e.detail / -3 )*60;",""," }",""," });",""," } else {",""," //ie6"," domUtils.on( this.getDom(), 'mousewheel' , function(e){",""," e.returnValue = false;",""," me.getDom('content').scrollTop -= ( e.wheelDelta / 120 )*60;",""," });",""," }",""," }"," this.fireEvent('postRenderAfter');"," this.hide(true);"," this._UIBase_postRender();"," },"," _doAutoRender: function (){"," if (!this.getDom() && this.autoRender) {"," this.render();"," }"," },"," mesureSize: function (){"," var box = this.getDom('content');"," return uiUtils.getClientRect(box);"," },"," fitSize: function (){"," if( this.captureWheel && this.sized ) {"," return this.__size;"," }"," this.sized = true;"," var popBodyEl = this.getDom('body');"," popBodyEl.style.width = '';"," popBodyEl.style.height = '';"," var size = this.mesureSize();"," if( this.captureWheel ) {"," popBodyEl.style.width = -(-20 -size.width) + 'px';"," } else {"," popBodyEl.style.width = size.width + 'px';"," }"," popBodyEl.style.height = size.height + 'px';"," this.__size = size;"," this.captureWheel && (this.getDom('content').style.overflow = 'auto');"," return size;"," },"," showAnchor: function ( element, hoz ){"," this.showAnchorRect( uiUtils.getClientRect( element ), hoz );"," },"," showAnchorRect: function ( rect, hoz, adj ){"," this._doAutoRender();"," var vpRect = uiUtils.getViewportRect();"," this._show();"," var popSize = this.fitSize();",""," var sideLeft, sideUp, left, top;"," if (hoz) {"," sideLeft = this.canSideLeft && (rect.right + popSize.width > vpRect.right && rect.left > popSize.width);"," sideUp = this.canSideUp && (rect.top + popSize.height > vpRect.bottom && rect.bottom > popSize.height);"," left = (sideLeft ? rect.left - popSize.width : rect.right);"," top = (sideUp ? rect.bottom - popSize.height : rect.top);"," } else {"," sideLeft = this.canSideLeft && (rect.right + popSize.width > vpRect.right && rect.left > popSize.width);"," sideUp = this.canSideUp && (rect.top + popSize.height > vpRect.bottom && rect.bottom > popSize.height);"," left = (sideLeft ? rect.right - popSize.width : rect.left);"," top = (sideUp ? rect.top - popSize.height : rect.bottom);"," }",""," var popEl = this.getDom();"," uiUtils.setViewportOffset(popEl, {"," left: left,"," top: top"," });"," domUtils.removeClasses(popEl, ANCHOR_CLASSES);"," popEl.className += ' ' + ANCHOR_CLASSES[(sideUp ? 1 : 0) * 2 + (sideLeft ? 1 : 0)];"," if(this.editor){"," popEl.style.zIndex = this.editor.container.style.zIndex * 1 + 10;"," baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = popEl.style.zIndex - 1;"," }",""," },"," showAt: function (offset) {"," var left = offset.left;"," var top = offset.top;"," var rect = {"," left: left,"," top: top,"," right: left,"," bottom: top,"," height: 0,"," width: 0"," };"," this.showAnchorRect(rect, false, true);"," },"," _show: function (){"," if (this._hidden) {"," var box = this.getDom();"," box.style.display = '';"," this._hidden = false;","// if (box.setActive) {","// box.setActive();","// }"," this.fireEvent('show');"," }"," },"," isHidden: function (){"," return this._hidden;"," },"," show: function (){"," this._doAutoRender();"," this._show();"," },"," hide: function (notNofity){"," if (!this._hidden && this.getDom()) {"," this.getDom().style.display = 'none';"," this._hidden = true;"," if (!notNofity) {"," this.fireEvent('hide');"," }"," }"," },"," queryAutoHide: function (el){"," return !el || !uiUtils.contains(this.getDom(), el);"," }"," };"," utils.inherits(Popup, UIBase);"," "," domUtils.on( document, 'mousedown', function ( evt ) {"," var el = evt.target || evt.srcElement;"," closeAllPopup( evt,el );"," } );"," domUtils.on( window, 'scroll', function (evt,el) {"," closeAllPopup( evt,el );"," } );","","})();"]; +_$jscoverage['ui/popup.js'][3]++; +(function () { + _$jscoverage['ui/popup.js'][4]++; + var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, domUtils = baidu.editor.dom.domUtils, UIBase = baidu.editor.ui.UIBase, Popup = (baidu.editor.ui.Popup = (function (options) { + _$jscoverage['ui/popup.js'][9]++; + this.initOptions(options); + _$jscoverage['ui/popup.js'][10]++; + this.initPopup(); +})); + _$jscoverage['ui/popup.js'][13]++; + var allPopups = []; + _$jscoverage['ui/popup.js'][14]++; + function closeAllPopup(evt, el) { + _$jscoverage['ui/popup.js'][15]++; + for (var i = 0; (i < allPopups.length); (i++)) { + _$jscoverage['ui/popup.js'][16]++; + var pop = allPopups[i]; + _$jscoverage['ui/popup.js'][17]++; + if ((! pop.isHidden())) { + _$jscoverage['ui/popup.js'][18]++; + if ((pop.queryAutoHide(el) !== false)) { + _$jscoverage['ui/popup.js'][19]++; + if ((evt && /scroll/gi.test(evt.type) && (pop.className == "edui-wordpastepop"))) { + _$jscoverage['ui/popup.js'][19]++; + return; + } + _$jscoverage['ui/popup.js'][20]++; + pop.hide(); + } + } +} + _$jscoverage['ui/popup.js'][25]++; + if (allPopups.length) { + _$jscoverage['ui/popup.js'][26]++; + pop.editor.fireEvent("afterhidepop"); + } +} + _$jscoverage['ui/popup.js'][29]++; + Popup.postHide = closeAllPopup; + _$jscoverage['ui/popup.js'][31]++; + var ANCHOR_CLASSES = ["edui-anchor-topleft", "edui-anchor-topright", "edui-anchor-bottomleft", "edui-anchor-bottomright"]; + _$jscoverage['ui/popup.js'][33]++; + Popup.prototype = {SHADOW_RADIUS: 5, content: null, _hidden: false, autoRender: true, canSideLeft: true, canSideUp: true, initPopup: (function () { + _$jscoverage['ui/popup.js'][41]++; + this.initUIBase(); + _$jscoverage['ui/popup.js'][42]++; + allPopups.push(this); +}), getHtmlTpl: (function () { + _$jscoverage['ui/popup.js'][45]++; + return ("
    " + "
    " + " " + "
    " + "
    " + this.getContentHtmlTpl() + "
    " + "
    " + "
    "); +}), getContentHtmlTpl: (function () { + _$jscoverage['ui/popup.js'][56]++; + if (this.content) { + _$jscoverage['ui/popup.js'][57]++; + if (((typeof this.content) == "string")) { + _$jscoverage['ui/popup.js'][58]++; + return this.content; + } + _$jscoverage['ui/popup.js'][60]++; + return this.content.renderHtml(); + } + else { + _$jscoverage['ui/popup.js'][62]++; + return ""; + } +}), _UIBase_postRender: UIBase.prototype.postRender, postRender: (function () { + _$jscoverage['ui/popup.js'][70]++; + if ((this.content instanceof UIBase)) { + _$jscoverage['ui/popup.js'][71]++; + this.content.postRender(); + } + _$jscoverage['ui/popup.js'][75]++; + if ((this.captureWheel && (! this.captured))) { + _$jscoverage['ui/popup.js'][77]++; + this.captured = true; + _$jscoverage['ui/popup.js'][79]++; + var winHeight = ((document.documentElement.clientHeight || document.body.clientHeight) - 80), _height = this.getDom().offsetHeight, _top = domUtils.getXY(this.combox.getDom()).y, content = this.getDom("content"), me = this; + _$jscoverage['ui/popup.js'][85]++; + while (((_top + _height) > winHeight)) { + _$jscoverage['ui/popup.js'][86]++; + _height -= 30; + _$jscoverage['ui/popup.js'][87]++; + content.style.height = (_height + "px"); +} + _$jscoverage['ui/popup.js'][91]++; + if (window.XMLHttpRequest) { + _$jscoverage['ui/popup.js'][93]++; + domUtils.on(content, (("onmousewheel" in document.body)? "mousewheel": "DOMMouseScroll"), (function (e) { + _$jscoverage['ui/popup.js'][95]++; + if (e.preventDefault) { + _$jscoverage['ui/popup.js'][96]++; + e.preventDefault(); + } + else { + _$jscoverage['ui/popup.js'][98]++; + e.returnValue = false; + } + _$jscoverage['ui/popup.js'][101]++; + if (e.wheelDelta) { + _$jscoverage['ui/popup.js'][103]++; + content.scrollTop -= ((e.wheelDelta / 120) * 60); + } + else { + _$jscoverage['ui/popup.js'][107]++; + content.scrollTop -= ((e.detail / -3) * 60); + } +})); + } + else { + _$jscoverage['ui/popup.js'][116]++; + domUtils.on(this.getDom(), "mousewheel", (function (e) { + _$jscoverage['ui/popup.js'][118]++; + e.returnValue = false; + _$jscoverage['ui/popup.js'][120]++; + me.getDom("content").scrollTop -= ((e.wheelDelta / 120) * 60); +})); + } + } + _$jscoverage['ui/popup.js'][127]++; + this.fireEvent("postRenderAfter"); + _$jscoverage['ui/popup.js'][128]++; + this.hide(true); + _$jscoverage['ui/popup.js'][129]++; + this._UIBase_postRender(); +}), _doAutoRender: (function () { + _$jscoverage['ui/popup.js'][132]++; + if (((! this.getDom()) && this.autoRender)) { + _$jscoverage['ui/popup.js'][133]++; + this.render(); + } +}), mesureSize: (function () { + _$jscoverage['ui/popup.js'][137]++; + var box = this.getDom("content"); + _$jscoverage['ui/popup.js'][138]++; + return uiUtils.getClientRect(box); +}), fitSize: (function () { + _$jscoverage['ui/popup.js'][141]++; + if ((this.captureWheel && this.sized)) { + _$jscoverage['ui/popup.js'][142]++; + return this.__size; + } + _$jscoverage['ui/popup.js'][144]++; + this.sized = true; + _$jscoverage['ui/popup.js'][145]++; + var popBodyEl = this.getDom("body"); + _$jscoverage['ui/popup.js'][146]++; + popBodyEl.style.width = ""; + _$jscoverage['ui/popup.js'][147]++; + popBodyEl.style.height = ""; + _$jscoverage['ui/popup.js'][148]++; + var size = this.mesureSize(); + _$jscoverage['ui/popup.js'][149]++; + if (this.captureWheel) { + _$jscoverage['ui/popup.js'][150]++; + popBodyEl.style.width = ((- (-20 - size.width)) + "px"); + } + else { + _$jscoverage['ui/popup.js'][152]++; + popBodyEl.style.width = (size.width + "px"); + } + _$jscoverage['ui/popup.js'][154]++; + popBodyEl.style.height = (size.height + "px"); + _$jscoverage['ui/popup.js'][155]++; + this.__size = size; + _$jscoverage['ui/popup.js'][156]++; + (this.captureWheel && (this.getDom("content").style.overflow = "auto")); + _$jscoverage['ui/popup.js'][157]++; + return size; +}), showAnchor: (function (element, hoz) { + _$jscoverage['ui/popup.js'][160]++; + this.showAnchorRect(uiUtils.getClientRect(element), hoz); +}), showAnchorRect: (function (rect, hoz, adj) { + _$jscoverage['ui/popup.js'][163]++; + this._doAutoRender(); + _$jscoverage['ui/popup.js'][164]++; + var vpRect = uiUtils.getViewportRect(); + _$jscoverage['ui/popup.js'][165]++; + this._show(); + _$jscoverage['ui/popup.js'][166]++; + var popSize = this.fitSize(); + _$jscoverage['ui/popup.js'][168]++; + var sideLeft, sideUp, left, top; + _$jscoverage['ui/popup.js'][169]++; + if (hoz) { + _$jscoverage['ui/popup.js'][170]++; + sideLeft = (this.canSideLeft && (((rect.right + popSize.width) > vpRect.right) && (rect.left > popSize.width))); + _$jscoverage['ui/popup.js'][171]++; + sideUp = (this.canSideUp && (((rect.top + popSize.height) > vpRect.bottom) && (rect.bottom > popSize.height))); + _$jscoverage['ui/popup.js'][172]++; + left = (sideLeft? (rect.left - popSize.width): rect.right); + _$jscoverage['ui/popup.js'][173]++; + top = (sideUp? (rect.bottom - popSize.height): rect.top); + } + else { + _$jscoverage['ui/popup.js'][175]++; + sideLeft = (this.canSideLeft && (((rect.right + popSize.width) > vpRect.right) && (rect.left > popSize.width))); + _$jscoverage['ui/popup.js'][176]++; + sideUp = (this.canSideUp && (((rect.top + popSize.height) > vpRect.bottom) && (rect.bottom > popSize.height))); + _$jscoverage['ui/popup.js'][177]++; + left = (sideLeft? (rect.right - popSize.width): rect.left); + _$jscoverage['ui/popup.js'][178]++; + top = (sideUp? (rect.top - popSize.height): rect.bottom); + } + _$jscoverage['ui/popup.js'][181]++; + var popEl = this.getDom(); + _$jscoverage['ui/popup.js'][182]++; + uiUtils.setViewportOffset(popEl, {left: left, top: top}); + _$jscoverage['ui/popup.js'][186]++; + domUtils.removeClasses(popEl, ANCHOR_CLASSES); + _$jscoverage['ui/popup.js'][187]++; + popEl.className += (" " + ANCHOR_CLASSES[(((sideUp? 1: 0) * 2) + (sideLeft? 1: 0))]); + _$jscoverage['ui/popup.js'][188]++; + if (this.editor) { + _$jscoverage['ui/popup.js'][189]++; + popEl.style.zIndex = ((this.editor.container.style.zIndex * 1) + 10); + _$jscoverage['ui/popup.js'][190]++; + baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = (popEl.style.zIndex - 1); + } +}), showAt: (function (offset) { + _$jscoverage['ui/popup.js'][195]++; + var left = offset.left; + _$jscoverage['ui/popup.js'][196]++; + var top = offset.top; + _$jscoverage['ui/popup.js'][197]++; + var rect = {left: left, top: top, right: left, bottom: top, height: 0, width: 0}; + _$jscoverage['ui/popup.js'][205]++; + this.showAnchorRect(rect, false, true); +}), _show: (function () { + _$jscoverage['ui/popup.js'][208]++; + if (this._hidden) { + _$jscoverage['ui/popup.js'][209]++; + var box = this.getDom(); + _$jscoverage['ui/popup.js'][210]++; + box.style.display = ""; + _$jscoverage['ui/popup.js'][211]++; + this._hidden = false; + _$jscoverage['ui/popup.js'][215]++; + this.fireEvent("show"); + } +}), isHidden: (function () { + _$jscoverage['ui/popup.js'][219]++; + return this._hidden; +}), show: (function () { + _$jscoverage['ui/popup.js'][222]++; + this._doAutoRender(); + _$jscoverage['ui/popup.js'][223]++; + this._show(); +}), hide: (function (notNofity) { + _$jscoverage['ui/popup.js'][226]++; + if (((! this._hidden) && this.getDom())) { + _$jscoverage['ui/popup.js'][227]++; + this.getDom().style.display = "none"; + _$jscoverage['ui/popup.js'][228]++; + this._hidden = true; + _$jscoverage['ui/popup.js'][229]++; + if ((! notNofity)) { + _$jscoverage['ui/popup.js'][230]++; + this.fireEvent("hide"); + } + } +}), queryAutoHide: (function (el) { + _$jscoverage['ui/popup.js'][235]++; + return ((! el) || (! uiUtils.contains(this.getDom(), el))); +})}; + _$jscoverage['ui/popup.js'][238]++; + utils.inherits(Popup, UIBase); + _$jscoverage['ui/popup.js'][240]++; + domUtils.on(document, "mousedown", (function (evt) { + _$jscoverage['ui/popup.js'][241]++; + var el = (evt.target || evt.srcElement); + _$jscoverage['ui/popup.js'][242]++; + closeAllPopup(evt, el); +})); + _$jscoverage['ui/popup.js'][244]++; + domUtils.on(window, "scroll", (function (evt, el) { + _$jscoverage['ui/popup.js'][245]++; + closeAllPopup(evt, el); +})); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/separator.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/separator.js new file mode 100644 index 000000000..1ea7a8980 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/separator.js @@ -0,0 +1,71 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/separator.js']) { + _$jscoverage['ui/separator.js'] = []; + _$jscoverage['ui/separator.js'][1] = 0; + _$jscoverage['ui/separator.js'][2] = 0; + _$jscoverage['ui/separator.js'][5] = 0; + _$jscoverage['ui/separator.js'][6] = 0; + _$jscoverage['ui/separator.js'][8] = 0; + _$jscoverage['ui/separator.js'][11] = 0; + _$jscoverage['ui/separator.js'][14] = 0; + _$jscoverage['ui/separator.js'][17] = 0; +} +_$jscoverage['ui/separator.js'].source = ["(function (){"," var utils = baidu.editor.utils,"," UIBase = baidu.editor.ui.UIBase,"," Separator = baidu.editor.ui.Separator = function (options){"," this.initOptions(options);"," this.initSeparator();"," };"," Separator.prototype = {"," uiName: 'separator',"," initSeparator: function (){"," this.initUIBase();"," },"," getHtmlTpl: function (){"," return '<div id=\"##\" class=\"edui-box %%\"></div>';"," }"," };"," utils.inherits(Separator, UIBase);","","})();"]; +_$jscoverage['ui/separator.js'][1]++; +(function () { + _$jscoverage['ui/separator.js'][2]++; + var utils = baidu.editor.utils, UIBase = baidu.editor.ui.UIBase, Separator = (baidu.editor.ui.Separator = (function (options) { + _$jscoverage['ui/separator.js'][5]++; + this.initOptions(options); + _$jscoverage['ui/separator.js'][6]++; + this.initSeparator(); +})); + _$jscoverage['ui/separator.js'][8]++; + Separator.prototype = {uiName: "separator", initSeparator: (function () { + _$jscoverage['ui/separator.js'][11]++; + this.initUIBase(); +}), getHtmlTpl: (function () { + _$jscoverage['ui/separator.js'][14]++; + return "
    "; +})}; + _$jscoverage['ui/separator.js'][17]++; + utils.inherits(Separator, UIBase); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/shortcutmenu.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/shortcutmenu.js new file mode 100644 index 000000000..a15b2d07a --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/shortcutmenu.js @@ -0,0 +1,462 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/shortcutmenu.js']) { + _$jscoverage['ui/shortcutmenu.js'] = []; + _$jscoverage['ui/shortcutmenu.js'][1] = 0; + _$jscoverage['ui/shortcutmenu.js'][2] = 0; + _$jscoverage['ui/shortcutmenu.js'][8] = 0; + _$jscoverage['ui/shortcutmenu.js'][12] = 0; + _$jscoverage['ui/shortcutmenu.js'][13] = 0; + _$jscoverage['ui/shortcutmenu.js'][14] = 0; + _$jscoverage['ui/shortcutmenu.js'][17] = 0; + _$jscoverage['ui/shortcutmenu.js'][19] = 0; + _$jscoverage['ui/shortcutmenu.js'][23] = 0; + _$jscoverage['ui/shortcutmenu.js'][24] = 0; + _$jscoverage['ui/shortcutmenu.js'][25] = 0; + _$jscoverage['ui/shortcutmenu.js'][26] = 0; + _$jscoverage['ui/shortcutmenu.js'][27] = 0; + _$jscoverage['ui/shortcutmenu.js'][30] = 0; + _$jscoverage['ui/shortcutmenu.js'][33] = 0; + _$jscoverage['ui/shortcutmenu.js'][34] = 0; + _$jscoverage['ui/shortcutmenu.js'][36] = 0; + _$jscoverage['ui/shortcutmenu.js'][39] = 0; + _$jscoverage['ui/shortcutmenu.js'][48] = 0; + _$jscoverage['ui/shortcutmenu.js'][49] = 0; + _$jscoverage['ui/shortcutmenu.js'][50] = 0; + _$jscoverage['ui/shortcutmenu.js'][51] = 0; + _$jscoverage['ui/shortcutmenu.js'][52] = 0; + _$jscoverage['ui/shortcutmenu.js'][53] = 0; + _$jscoverage['ui/shortcutmenu.js'][54] = 0; + _$jscoverage['ui/shortcutmenu.js'][55] = 0; + _$jscoverage['ui/shortcutmenu.js'][56] = 0; + _$jscoverage['ui/shortcutmenu.js'][59] = 0; + _$jscoverage['ui/shortcutmenu.js'][60] = 0; + _$jscoverage['ui/shortcutmenu.js'][61] = 0; + _$jscoverage['ui/shortcutmenu.js'][62] = 0; + _$jscoverage['ui/shortcutmenu.js'][63] = 0; + _$jscoverage['ui/shortcutmenu.js'][64] = 0; + _$jscoverage['ui/shortcutmenu.js'][71] = 0; + _$jscoverage['ui/shortcutmenu.js'][72] = 0; + _$jscoverage['ui/shortcutmenu.js'][73] = 0; + _$jscoverage['ui/shortcutmenu.js'][75] = 0; + _$jscoverage['ui/shortcutmenu.js'][76] = 0; + _$jscoverage['ui/shortcutmenu.js'][81] = 0; + _$jscoverage['ui/shortcutmenu.js'][82] = 0; + _$jscoverage['ui/shortcutmenu.js'][83] = 0; + _$jscoverage['ui/shortcutmenu.js'][89] = 0; + _$jscoverage['ui/shortcutmenu.js'][90] = 0; + _$jscoverage['ui/shortcutmenu.js'][91] = 0; + _$jscoverage['ui/shortcutmenu.js'][93] = 0; + _$jscoverage['ui/shortcutmenu.js'][94] = 0; + _$jscoverage['ui/shortcutmenu.js'][95] = 0; + _$jscoverage['ui/shortcutmenu.js'][101] = 0; + _$jscoverage['ui/shortcutmenu.js'][102] = 0; + _$jscoverage['ui/shortcutmenu.js'][104] = 0; + _$jscoverage['ui/shortcutmenu.js'][108] = 0; + _$jscoverage['ui/shortcutmenu.js'][109] = 0; + _$jscoverage['ui/shortcutmenu.js'][110] = 0; + _$jscoverage['ui/shortcutmenu.js'][111] = 0; + _$jscoverage['ui/shortcutmenu.js'][114] = 0; + _$jscoverage['ui/shortcutmenu.js'][115] = 0; + _$jscoverage['ui/shortcutmenu.js'][116] = 0; + _$jscoverage['ui/shortcutmenu.js'][119] = 0; + _$jscoverage['ui/shortcutmenu.js'][122] = 0; + _$jscoverage['ui/shortcutmenu.js'][127] = 0; + _$jscoverage['ui/shortcutmenu.js'][128] = 0; + _$jscoverage['ui/shortcutmenu.js'][129] = 0; + _$jscoverage['ui/shortcutmenu.js'][131] = 0; + _$jscoverage['ui/shortcutmenu.js'][132] = 0; + _$jscoverage['ui/shortcutmenu.js'][134] = 0; + _$jscoverage['ui/shortcutmenu.js'][137] = 0; + _$jscoverage['ui/shortcutmenu.js'][138] = 0; + _$jscoverage['ui/shortcutmenu.js'][139] = 0; + _$jscoverage['ui/shortcutmenu.js'][141] = 0; + _$jscoverage['ui/shortcutmenu.js'][142] = 0; + _$jscoverage['ui/shortcutmenu.js'][143] = 0; + _$jscoverage['ui/shortcutmenu.js'][144] = 0; + _$jscoverage['ui/shortcutmenu.js'][148] = 0; + _$jscoverage['ui/shortcutmenu.js'][149] = 0; + _$jscoverage['ui/shortcutmenu.js'][151] = 0; + _$jscoverage['ui/shortcutmenu.js'][152] = 0; + _$jscoverage['ui/shortcutmenu.js'][153] = 0; + _$jscoverage['ui/shortcutmenu.js'][154] = 0; + _$jscoverage['ui/shortcutmenu.js'][156] = 0; + _$jscoverage['ui/shortcutmenu.js'][157] = 0; + _$jscoverage['ui/shortcutmenu.js'][161] = 0; + _$jscoverage['ui/shortcutmenu.js'][162] = 0; + _$jscoverage['ui/shortcutmenu.js'][163] = 0; + _$jscoverage['ui/shortcutmenu.js'][164] = 0; + _$jscoverage['ui/shortcutmenu.js'][165] = 0; + _$jscoverage['ui/shortcutmenu.js'][169] = 0; + _$jscoverage['ui/shortcutmenu.js'][170] = 0; + _$jscoverage['ui/shortcutmenu.js'][171] = 0; + _$jscoverage['ui/shortcutmenu.js'][173] = 0; + _$jscoverage['ui/shortcutmenu.js'][174] = 0; + _$jscoverage['ui/shortcutmenu.js'][175] = 0; + _$jscoverage['ui/shortcutmenu.js'][179] = 0; + _$jscoverage['ui/shortcutmenu.js'][180] = 0; + _$jscoverage['ui/shortcutmenu.js'][182] = 0; + _$jscoverage['ui/shortcutmenu.js'][185] = 0; + _$jscoverage['ui/shortcutmenu.js'][186] = 0; + _$jscoverage['ui/shortcutmenu.js'][187] = 0; + _$jscoverage['ui/shortcutmenu.js'][192] = 0; + _$jscoverage['ui/shortcutmenu.js'][193] = 0; + _$jscoverage['ui/shortcutmenu.js'][194] = 0; + _$jscoverage['ui/shortcutmenu.js'][195] = 0; + _$jscoverage['ui/shortcutmenu.js'][196] = 0; + _$jscoverage['ui/shortcutmenu.js'][198] = 0; + _$jscoverage['ui/shortcutmenu.js'][200] = 0; + _$jscoverage['ui/shortcutmenu.js'][203] = 0; + _$jscoverage['ui/shortcutmenu.js'][209] = 0; + _$jscoverage['ui/shortcutmenu.js'][211] = 0; + _$jscoverage['ui/shortcutmenu.js'][212] = 0; + _$jscoverage['ui/shortcutmenu.js'][214] = 0; + _$jscoverage['ui/shortcutmenu.js'][217] = 0; + _$jscoverage['ui/shortcutmenu.js'][218] = 0; + _$jscoverage['ui/shortcutmenu.js'][219] = 0; + _$jscoverage['ui/shortcutmenu.js'][224] = 0; + _$jscoverage['ui/shortcutmenu.js'][225] = 0; + _$jscoverage['ui/shortcutmenu.js'][228] = 0; + _$jscoverage['ui/shortcutmenu.js'][229] = 0; +} +_$jscoverage['ui/shortcutmenu.js'].source = ["(function () {"," var UI = baidu.editor.ui,"," UIBase = UI.UIBase,"," uiUtils = UI.uiUtils,"," utils = baidu.editor.utils,"," domUtils = baidu.editor.dom.domUtils;",""," var allMenus = [],//存储所有快捷菜单"," timeID,"," isSubMenuShow = false;//是否有子pop显示",""," var ShortCutMenu = UI.ShortCutMenu = function (options) {"," this.initOptions (options);"," this.initShortCutMenu ();"," };",""," ShortCutMenu.postHide = hideAllMenu;",""," ShortCutMenu.prototype = {"," isHidden : true ,"," SPACE : 5 ,"," initShortCutMenu : function () {"," this.items = this.items || [];"," this.initUIBase ();"," this.initItems ();"," this.initEvent ();"," allMenus.push (this);"," } ,"," initEvent : function () {"," var me = this,"," doc = me.editor.document;",""," domUtils.on (doc , \"mousemove\" , function (e) {"," if (me.isHidden === false) {"," //有pop显示就不隐藏快捷菜单"," if (me.getSubMenuMark () || me.eventType == \"contextmenu\") return;","",""," var flag = true,"," el = me.getDom (),"," wt = el.offsetWidth,"," ht = el.offsetHeight,"," distanceX = wt / 2 + me.SPACE,//距离中心X标准"," distanceY = ht / 2,//距离中心Y标准"," x = Math.abs (e.screenX - me.left),//离中心距离横坐标"," y = Math.abs (e.screenY - me.top);//离中心距离纵坐标",""," clearTimeout (timeID);"," timeID = setTimeout (function () {"," if (y > 0 && y < distanceY) {"," me.setOpacity (el , \"1\");"," } else if (y > distanceY && y < distanceY + 70) {"," me.setOpacity (el , \"0.5\");"," flag = false;"," } else if (y > distanceY + 70 && y < distanceY + 140) {"," me.hide ();"," }",""," if (flag && x > 0 && x < distanceX) {"," me.setOpacity (el , \"1\")"," } else if (x > distanceX && x < distanceX + 70) {"," me.setOpacity (el , \"0.5\")"," } else if (x > distanceX + 70 && x < distanceX + 140) {"," me.hide ();"," }"," });"," }"," });",""," //ie\\ff下 mouseout不准"," if (browser.chrome) {"," domUtils.on (doc , \"mouseout\" , function (e) {"," var relatedTgt = e.relatedTarget || e.toElement;",""," if (relatedTgt == null || relatedTgt.tagName == \"HTML\") {"," me.hide ();"," }"," });"," }",""," me.editor.addListener (\"afterhidepop\" , function () {"," if (!me.isHidden) {"," isSubMenuShow = true;"," }"," });",""," } ,"," initItems : function () {"," if (utils.isArray (this.items)) {"," for (var i = 0, len = this.items.length ; i < len ; i++) {"," var item = this.items[i].toLowerCase ();",""," if (UI[item]) {"," this.items[i] = new UI[item] (this.editor);"," this.items[i].className += \" edui-shortcutsubmenu \";"," }"," }"," }"," } ,"," setOpacity : function (el , value) {"," if (browser.ie && browser.version < 9) {"," el.style.filter = \"alpha(opacity = \" + parseFloat (value) * 100 + \");\""," } else {"," el.style.opacity = value;"," }"," } ,"," getSubMenuMark : function () {"," isSubMenuShow = false;"," var layerEle = uiUtils.getFixedLayer ();"," var list = domUtils.getElementsByTagName (layerEle , \"div\" , function (node) {"," return domUtils.hasClass (node , \"edui-shortcutsubmenu edui-popup\")"," });",""," for (var i = 0, node ; node = list[i++] ;) {"," if (node.style.display != \"none\") {"," isSubMenuShow = true;"," }"," }"," return isSubMenuShow;"," } ,"," show : function (e , hasContextmenu) {"," var me = this,"," offset = {},"," el = this.getDom (),"," fixedlayer = uiUtils.getFixedLayer ();",""," function setPos (offset) {"," if (offset.left < 0) {"," offset.left = 0;"," }"," if (offset.top < 0) {"," offset.top = 0;"," }"," el.style.cssText = \"position:absolute;left:\" + offset.left + \"px;top:\" + offset.top + \"px;\";"," }",""," function setPosByCxtMenu (menu) {"," if (!menu.tagName) {"," menu = menu.getDom ();"," }"," offset.left = parseInt (menu.style.left);"," offset.top = parseInt (menu.style.top);"," offset.top -= el.offsetHeight + 15;"," setPos (offset);"," }","",""," me.eventType = e.type;"," el.style.cssText = \"display:block;left:-9999px\";",""," if (e.type == \"contextmenu\" && hasContextmenu) {"," var menu = domUtils.getElementsByTagName (fixedlayer , \"div\" , \"edui-contextmenu\")[0];"," if (menu) {"," setPosByCxtMenu (menu)"," } else {"," me.editor.addListener (\"aftershowcontextmenu\" , function (type , menu) {"," setPosByCxtMenu (menu);"," });"," }"," } else {"," offset = uiUtils.getViewportOffsetByEvent (e);"," offset.top -= el.offsetHeight + me.SPACE;"," offset.left += me.SPACE + 20;"," setPos (offset);"," me.setOpacity (el , 0.2);"," }","",""," me.isHidden = false;"," me.left = e.screenX + el.offsetWidth / 2 - me.SPACE;"," me.top = e.screenY - (el.offsetHeight / 2) - me.SPACE;",""," if (me.editor) {"," el.style.zIndex = me.editor.container.style.zIndex * 1 + 10;"," fixedlayer.style.zIndex = el.style.zIndex - 1;"," }"," } ,"," hide : function () {"," if (this.getDom ()) {"," this.getDom ().style.display = \"none\";"," }"," this.isHidden = true;"," } ,"," postRender : function () {"," if (utils.isArray (this.items)) {"," for (var i = 0, item ; item = this.items[i++] ;) {"," item.postRender ();"," }"," }"," } ,"," getHtmlTpl : function () {"," var buff;"," if (utils.isArray (this.items)) {"," buff = [];"," for (var i = 0 ; i < this.items.length ; i++) {"," buff[i] = this.items[i].renderHtml ();"," }"," buff = buff.join (\"\");"," } else {"," buff = this.items;"," }",""," return '<div id=\"##\" class=\"%% edui-toolbar\" data-src=\"shortcutmenu\" onmousedown=\"return false;\" onselectstart=\"return false;\" >' +"," buff +"," '</div>';"," }"," };",""," utils.inherits (ShortCutMenu , UIBase);",""," function hideAllMenu (e) {"," var tgt = e.target || e.srcElement,"," cur = domUtils.findParent (tgt , function (node) {"," return domUtils.hasClass (node , \"edui-shortcutmenu\") || domUtils.hasClass (node , \"edui-popup\");"," } , true);",""," if (!cur) {"," for (var i = 0, menu ; menu = allMenus[i++] ;) {"," menu.hide ()"," }"," }"," }",""," domUtils.on (document , 'mousedown' , function (e) {"," hideAllMenu (e);"," });",""," domUtils.on (window , 'scroll' , function (e) {"," hideAllMenu (e);"," });","","}) ();"]; +_$jscoverage['ui/shortcutmenu.js'][1]++; +(function () { + _$jscoverage['ui/shortcutmenu.js'][2]++; + var UI = baidu.editor.ui, UIBase = UI.UIBase, uiUtils = UI.uiUtils, utils = baidu.editor.utils, domUtils = baidu.editor.dom.domUtils; + _$jscoverage['ui/shortcutmenu.js'][8]++; + var allMenus = [], timeID, isSubMenuShow = false; + _$jscoverage['ui/shortcutmenu.js'][12]++; + var ShortCutMenu = (UI.ShortCutMenu = (function (options) { + _$jscoverage['ui/shortcutmenu.js'][13]++; + this.initOptions(options); + _$jscoverage['ui/shortcutmenu.js'][14]++; + this.initShortCutMenu(); +})); + _$jscoverage['ui/shortcutmenu.js'][17]++; + ShortCutMenu.postHide = hideAllMenu; + _$jscoverage['ui/shortcutmenu.js'][19]++; + ShortCutMenu.prototype = {isHidden: true, SPACE: 5, initShortCutMenu: (function () { + _$jscoverage['ui/shortcutmenu.js'][23]++; + this.items = (this.items || []); + _$jscoverage['ui/shortcutmenu.js'][24]++; + this.initUIBase(); + _$jscoverage['ui/shortcutmenu.js'][25]++; + this.initItems(); + _$jscoverage['ui/shortcutmenu.js'][26]++; + this.initEvent(); + _$jscoverage['ui/shortcutmenu.js'][27]++; + allMenus.push(this); +}), initEvent: (function () { + _$jscoverage['ui/shortcutmenu.js'][30]++; + var me = this, doc = me.editor.document; + _$jscoverage['ui/shortcutmenu.js'][33]++; + domUtils.on(doc, "mousemove", (function (e) { + _$jscoverage['ui/shortcutmenu.js'][34]++; + if ((me.isHidden === false)) { + _$jscoverage['ui/shortcutmenu.js'][36]++; + if ((me.getSubMenuMark() || (me.eventType == "contextmenu"))) { + _$jscoverage['ui/shortcutmenu.js'][36]++; + return; + } + _$jscoverage['ui/shortcutmenu.js'][39]++; + var flag = true, el = me.getDom(), wt = el.offsetWidth, ht = el.offsetHeight, distanceX = ((wt / 2) + me.SPACE), distanceY = (ht / 2), x = Math.abs((e.screenX - me.left)), y = Math.abs((e.screenY - me.top)); + _$jscoverage['ui/shortcutmenu.js'][48]++; + clearTimeout(timeID); + _$jscoverage['ui/shortcutmenu.js'][49]++; + timeID = setTimeout((function () { + _$jscoverage['ui/shortcutmenu.js'][50]++; + if (((y > 0) && (y < distanceY))) { + _$jscoverage['ui/shortcutmenu.js'][51]++; + me.setOpacity(el, "1"); + } + else { + _$jscoverage['ui/shortcutmenu.js'][52]++; + if (((y > distanceY) && (y < (distanceY + 70)))) { + _$jscoverage['ui/shortcutmenu.js'][53]++; + me.setOpacity(el, "0.5"); + _$jscoverage['ui/shortcutmenu.js'][54]++; + flag = false; + } + else { + _$jscoverage['ui/shortcutmenu.js'][55]++; + if (((y > (distanceY + 70)) && (y < (distanceY + 140)))) { + _$jscoverage['ui/shortcutmenu.js'][56]++; + me.hide(); + } + } + } + _$jscoverage['ui/shortcutmenu.js'][59]++; + if ((flag && (x > 0) && (x < distanceX))) { + _$jscoverage['ui/shortcutmenu.js'][60]++; + me.setOpacity(el, "1"); + } + else { + _$jscoverage['ui/shortcutmenu.js'][61]++; + if (((x > distanceX) && (x < (distanceX + 70)))) { + _$jscoverage['ui/shortcutmenu.js'][62]++; + me.setOpacity(el, "0.5"); + } + else { + _$jscoverage['ui/shortcutmenu.js'][63]++; + if (((x > (distanceX + 70)) && (x < (distanceX + 140)))) { + _$jscoverage['ui/shortcutmenu.js'][64]++; + me.hide(); + } + } + } +})); + } +})); + _$jscoverage['ui/shortcutmenu.js'][71]++; + if (browser.chrome) { + _$jscoverage['ui/shortcutmenu.js'][72]++; + domUtils.on(doc, "mouseout", (function (e) { + _$jscoverage['ui/shortcutmenu.js'][73]++; + var relatedTgt = (e.relatedTarget || e.toElement); + _$jscoverage['ui/shortcutmenu.js'][75]++; + if (((relatedTgt == null) || (relatedTgt.tagName == "HTML"))) { + _$jscoverage['ui/shortcutmenu.js'][76]++; + me.hide(); + } +})); + } + _$jscoverage['ui/shortcutmenu.js'][81]++; + me.editor.addListener("afterhidepop", (function () { + _$jscoverage['ui/shortcutmenu.js'][82]++; + if ((! me.isHidden)) { + _$jscoverage['ui/shortcutmenu.js'][83]++; + isSubMenuShow = true; + } +})); +}), initItems: (function () { + _$jscoverage['ui/shortcutmenu.js'][89]++; + if (utils.isArray(this.items)) { + _$jscoverage['ui/shortcutmenu.js'][90]++; + for (var i = 0, len = this.items.length; (i < len); (i++)) { + _$jscoverage['ui/shortcutmenu.js'][91]++; + var item = this.items[i].toLowerCase(); + _$jscoverage['ui/shortcutmenu.js'][93]++; + if (UI[item]) { + _$jscoverage['ui/shortcutmenu.js'][94]++; + this.items[i] = new (UI[item])(this.editor); + _$jscoverage['ui/shortcutmenu.js'][95]++; + this.items[i].className += " edui-shortcutsubmenu "; + } +} + } +}), setOpacity: (function (el, value) { + _$jscoverage['ui/shortcutmenu.js'][101]++; + if ((browser.ie && (browser.version < 9))) { + _$jscoverage['ui/shortcutmenu.js'][102]++; + el.style.filter = ("alpha(opacity = " + (parseFloat(value) * 100) + ");"); + } + else { + _$jscoverage['ui/shortcutmenu.js'][104]++; + el.style.opacity = value; + } +}), getSubMenuMark: (function () { + _$jscoverage['ui/shortcutmenu.js'][108]++; + isSubMenuShow = false; + _$jscoverage['ui/shortcutmenu.js'][109]++; + var layerEle = uiUtils.getFixedLayer(); + _$jscoverage['ui/shortcutmenu.js'][110]++; + var list = domUtils.getElementsByTagName(layerEle, "div", (function (node) { + _$jscoverage['ui/shortcutmenu.js'][111]++; + return domUtils.hasClass(node, "edui-shortcutsubmenu edui-popup"); +})); + _$jscoverage['ui/shortcutmenu.js'][114]++; + for (var i = 0, node; (node = list[(i++)]);) { + _$jscoverage['ui/shortcutmenu.js'][115]++; + if ((node.style.display != "none")) { + _$jscoverage['ui/shortcutmenu.js'][116]++; + isSubMenuShow = true; + } +} + _$jscoverage['ui/shortcutmenu.js'][119]++; + return isSubMenuShow; +}), show: (function (e, hasContextmenu) { + _$jscoverage['ui/shortcutmenu.js'][122]++; + var me = this, offset = {}, el = this.getDom(), fixedlayer = uiUtils.getFixedLayer(); + _$jscoverage['ui/shortcutmenu.js'][127]++; + function setPos(offset) { + _$jscoverage['ui/shortcutmenu.js'][128]++; + if ((offset.left < 0)) { + _$jscoverage['ui/shortcutmenu.js'][129]++; + offset.left = 0; + } + _$jscoverage['ui/shortcutmenu.js'][131]++; + if ((offset.top < 0)) { + _$jscoverage['ui/shortcutmenu.js'][132]++; + offset.top = 0; + } + _$jscoverage['ui/shortcutmenu.js'][134]++; + el.style.cssText = ("position:absolute;left:" + offset.left + "px;top:" + offset.top + "px;"); +} + _$jscoverage['ui/shortcutmenu.js'][137]++; + function setPosByCxtMenu(menu) { + _$jscoverage['ui/shortcutmenu.js'][138]++; + if ((! menu.tagName)) { + _$jscoverage['ui/shortcutmenu.js'][139]++; + menu = menu.getDom(); + } + _$jscoverage['ui/shortcutmenu.js'][141]++; + offset.left = parseInt(menu.style.left); + _$jscoverage['ui/shortcutmenu.js'][142]++; + offset.top = parseInt(menu.style.top); + _$jscoverage['ui/shortcutmenu.js'][143]++; + offset.top -= (el.offsetHeight + 15); + _$jscoverage['ui/shortcutmenu.js'][144]++; + setPos(offset); +} + _$jscoverage['ui/shortcutmenu.js'][148]++; + me.eventType = e.type; + _$jscoverage['ui/shortcutmenu.js'][149]++; + el.style.cssText = "display:block;left:-9999px"; + _$jscoverage['ui/shortcutmenu.js'][151]++; + if (((e.type == "contextmenu") && hasContextmenu)) { + _$jscoverage['ui/shortcutmenu.js'][152]++; + var menu = domUtils.getElementsByTagName(fixedlayer, "div", "edui-contextmenu")[0]; + _$jscoverage['ui/shortcutmenu.js'][153]++; + if (menu) { + _$jscoverage['ui/shortcutmenu.js'][154]++; + setPosByCxtMenu(menu); + } + else { + _$jscoverage['ui/shortcutmenu.js'][156]++; + me.editor.addListener("aftershowcontextmenu", (function (type, menu) { + _$jscoverage['ui/shortcutmenu.js'][157]++; + setPosByCxtMenu(menu); +})); + } + } + else { + _$jscoverage['ui/shortcutmenu.js'][161]++; + offset = uiUtils.getViewportOffsetByEvent(e); + _$jscoverage['ui/shortcutmenu.js'][162]++; + offset.top -= (el.offsetHeight + me.SPACE); + _$jscoverage['ui/shortcutmenu.js'][163]++; + offset.left += (me.SPACE + 20); + _$jscoverage['ui/shortcutmenu.js'][164]++; + setPos(offset); + _$jscoverage['ui/shortcutmenu.js'][165]++; + me.setOpacity(el, 0.20000000000000001); + } + _$jscoverage['ui/shortcutmenu.js'][169]++; + me.isHidden = false; + _$jscoverage['ui/shortcutmenu.js'][170]++; + me.left = ((e.screenX + (el.offsetWidth / 2)) - me.SPACE); + _$jscoverage['ui/shortcutmenu.js'][171]++; + me.top = (e.screenY - (el.offsetHeight / 2) - me.SPACE); + _$jscoverage['ui/shortcutmenu.js'][173]++; + if (me.editor) { + _$jscoverage['ui/shortcutmenu.js'][174]++; + el.style.zIndex = ((me.editor.container.style.zIndex * 1) + 10); + _$jscoverage['ui/shortcutmenu.js'][175]++; + fixedlayer.style.zIndex = (el.style.zIndex - 1); + } +}), hide: (function () { + _$jscoverage['ui/shortcutmenu.js'][179]++; + if (this.getDom()) { + _$jscoverage['ui/shortcutmenu.js'][180]++; + this.getDom().style.display = "none"; + } + _$jscoverage['ui/shortcutmenu.js'][182]++; + this.isHidden = true; +}), postRender: (function () { + _$jscoverage['ui/shortcutmenu.js'][185]++; + if (utils.isArray(this.items)) { + _$jscoverage['ui/shortcutmenu.js'][186]++; + for (var i = 0, item; (item = this.items[(i++)]);) { + _$jscoverage['ui/shortcutmenu.js'][187]++; + item.postRender(); +} + } +}), getHtmlTpl: (function () { + _$jscoverage['ui/shortcutmenu.js'][192]++; + var buff; + _$jscoverage['ui/shortcutmenu.js'][193]++; + if (utils.isArray(this.items)) { + _$jscoverage['ui/shortcutmenu.js'][194]++; + buff = []; + _$jscoverage['ui/shortcutmenu.js'][195]++; + for (var i = 0; (i < this.items.length); (i++)) { + _$jscoverage['ui/shortcutmenu.js'][196]++; + buff[i] = this.items[i].renderHtml(); +} + _$jscoverage['ui/shortcutmenu.js'][198]++; + buff = buff.join(""); + } + else { + _$jscoverage['ui/shortcutmenu.js'][200]++; + buff = this.items; + } + _$jscoverage['ui/shortcutmenu.js'][203]++; + return ("
    " + buff + "
    "); +})}; + _$jscoverage['ui/shortcutmenu.js'][209]++; + utils.inherits(ShortCutMenu, UIBase); + _$jscoverage['ui/shortcutmenu.js'][211]++; + function hideAllMenu(e) { + _$jscoverage['ui/shortcutmenu.js'][212]++; + var tgt = (e.target || e.srcElement), cur = domUtils.findParent(tgt, (function (node) { + _$jscoverage['ui/shortcutmenu.js'][214]++; + return (domUtils.hasClass(node, "edui-shortcutmenu") || domUtils.hasClass(node, "edui-popup")); +}), true); + _$jscoverage['ui/shortcutmenu.js'][217]++; + if ((! cur)) { + _$jscoverage['ui/shortcutmenu.js'][218]++; + for (var i = 0, menu; (menu = allMenus[(i++)]);) { + _$jscoverage['ui/shortcutmenu.js'][219]++; + menu.hide(); +} + } +} + _$jscoverage['ui/shortcutmenu.js'][224]++; + domUtils.on(document, "mousedown", (function (e) { + _$jscoverage['ui/shortcutmenu.js'][225]++; + hideAllMenu(e); +})); + _$jscoverage['ui/shortcutmenu.js'][228]++; + domUtils.on(window, "scroll", (function (e) { + _$jscoverage['ui/shortcutmenu.js'][229]++; + hideAllMenu(e); +})); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/splitbutton.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/splitbutton.js new file mode 100644 index 000000000..9d7b95a5d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/splitbutton.js @@ -0,0 +1,170 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/splitbutton.js']) { + _$jscoverage['ui/splitbutton.js'] = []; + _$jscoverage['ui/splitbutton.js'][4] = 0; + _$jscoverage['ui/splitbutton.js'][5] = 0; + _$jscoverage['ui/splitbutton.js'][11] = 0; + _$jscoverage['ui/splitbutton.js'][12] = 0; + _$jscoverage['ui/splitbutton.js'][14] = 0; + _$jscoverage['ui/splitbutton.js'][19] = 0; + _$jscoverage['ui/splitbutton.js'][20] = 0; + _$jscoverage['ui/splitbutton.js'][21] = 0; + _$jscoverage['ui/splitbutton.js'][22] = 0; + _$jscoverage['ui/splitbutton.js'][23] = 0; + _$jscoverage['ui/splitbutton.js'][24] = 0; + _$jscoverage['ui/splitbutton.js'][25] = 0; + _$jscoverage['ui/splitbutton.js'][30] = 0; + _$jscoverage['ui/splitbutton.js'][31] = 0; + _$jscoverage['ui/splitbutton.js'][34] = 0; + _$jscoverage['ui/splitbutton.js'][35] = 0; + _$jscoverage['ui/splitbutton.js'][36] = 0; + _$jscoverage['ui/splitbutton.js'][38] = 0; + _$jscoverage['ui/splitbutton.js'][39] = 0; + _$jscoverage['ui/splitbutton.js'][40] = 0; + _$jscoverage['ui/splitbutton.js'][41] = 0; + _$jscoverage['ui/splitbutton.js'][46] = 0; + _$jscoverage['ui/splitbutton.js'][48] = 0; + _$jscoverage['ui/splitbutton.js'][51] = 0; + _$jscoverage['ui/splitbutton.js'][54] = 0; + _$jscoverage['ui/splitbutton.js'][57] = 0; + _$jscoverage['ui/splitbutton.js'][68] = 0; + _$jscoverage['ui/splitbutton.js'][69] = 0; + _$jscoverage['ui/splitbutton.js'][70] = 0; + _$jscoverage['ui/splitbutton.js'][71] = 0; + _$jscoverage['ui/splitbutton.js'][74] = 0; + _$jscoverage['ui/splitbutton.js'][75] = 0; + _$jscoverage['ui/splitbutton.js'][79] = 0; + _$jscoverage['ui/splitbutton.js'][80] = 0; + _$jscoverage['ui/splitbutton.js'][84] = 0; + _$jscoverage['ui/splitbutton.js'][85] = 0; +} +_$jscoverage['ui/splitbutton.js'].source = ["///import core","///import uicore","///import ui/stateful.js","(function (){"," var utils = baidu.editor.utils,"," uiUtils = baidu.editor.ui.uiUtils,"," domUtils = baidu.editor.dom.domUtils,"," UIBase = baidu.editor.ui.UIBase,"," Stateful = baidu.editor.ui.Stateful,"," SplitButton = baidu.editor.ui.SplitButton = function (options){"," this.initOptions(options);"," this.initSplitButton();"," };"," SplitButton.prototype = {"," popup: null,"," uiName: 'splitbutton',"," title: '',"," initSplitButton: function (){"," this.initUIBase();"," this.Stateful_init();"," var me = this;"," if (this.popup != null) {"," var popup = this.popup;"," this.popup = null;"," this.setPopup(popup);"," }"," },"," _UIBase_postRender: UIBase.prototype.postRender,"," postRender: function (){"," this.Stateful_postRender();"," this._UIBase_postRender();"," },"," setPopup: function (popup){"," if (this.popup === popup) return;"," if (this.popup != null) {"," this.popup.dispose();"," }"," popup.addListener('show', utils.bind(this._onPopupShow, this));"," popup.addListener('hide', utils.bind(this._onPopupHide, this));"," popup.addListener('postrender', utils.bind(function (){"," popup.getDom('body').appendChild("," uiUtils.createElementByHtml('<div id=\"' +"," this.popup.id + '_bordereraser\" class=\"edui-bordereraser edui-background\" style=\"width:' +"," (uiUtils.getClientRect(this.getDom()).width + 20) + 'px\"></div>')"," );"," popup.getDom().className += ' ' + this.className;"," }, this));"," this.popup = popup;"," },"," _onPopupShow: function (){"," this.addState('opened');"," },"," _onPopupHide: function (){"," this.removeState('opened');"," },"," getHtmlTpl: function (){"," return '<div id=\"##\" class=\"edui-box %%\">' +"," '<div '+ (this.title ? 'title=\"' + this.title + '\"' : '') +' id=\"##_state\" stateful><div class=\"%%-body\">' +"," '<div id=\"##_button_body\" class=\"edui-box edui-button-body\" onclick=\"$$._onButtonClick(event, this);\">' +"," '<div class=\"edui-box edui-icon\"></div>' +"," '</div>' +"," '<div class=\"edui-box edui-splitborder\"></div>' +"," '<div class=\"edui-box edui-arrow\" onclick=\"$$._onArrowClick();\"></div>' +"," '</div></div></div>';"," },"," showPopup: function (){"," // 当popup往上弹出的时候,做特殊处理"," var rect = uiUtils.getClientRect(this.getDom());"," rect.top -= this.popup.SHADOW_RADIUS;"," rect.height += this.popup.SHADOW_RADIUS;"," this.popup.showAnchorRect(rect);"," },"," _onArrowClick: function (event, el){"," if (!this.isDisabled()) {"," this.showPopup();"," }"," },"," _onButtonClick: function (){"," if (!this.isDisabled()) {"," this.fireEvent('buttonclick');"," }"," }"," };"," utils.inherits(SplitButton, UIBase);"," utils.extend(SplitButton.prototype, Stateful, true);","","})();"]; +_$jscoverage['ui/splitbutton.js'][4]++; +(function () { + _$jscoverage['ui/splitbutton.js'][5]++; + var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, domUtils = baidu.editor.dom.domUtils, UIBase = baidu.editor.ui.UIBase, Stateful = baidu.editor.ui.Stateful, SplitButton = (baidu.editor.ui.SplitButton = (function (options) { + _$jscoverage['ui/splitbutton.js'][11]++; + this.initOptions(options); + _$jscoverage['ui/splitbutton.js'][12]++; + this.initSplitButton(); +})); + _$jscoverage['ui/splitbutton.js'][14]++; + SplitButton.prototype = {popup: null, uiName: "splitbutton", title: "", initSplitButton: (function () { + _$jscoverage['ui/splitbutton.js'][19]++; + this.initUIBase(); + _$jscoverage['ui/splitbutton.js'][20]++; + this.Stateful_init(); + _$jscoverage['ui/splitbutton.js'][21]++; + var me = this; + _$jscoverage['ui/splitbutton.js'][22]++; + if ((this.popup != null)) { + _$jscoverage['ui/splitbutton.js'][23]++; + var popup = this.popup; + _$jscoverage['ui/splitbutton.js'][24]++; + this.popup = null; + _$jscoverage['ui/splitbutton.js'][25]++; + this.setPopup(popup); + } +}), _UIBase_postRender: UIBase.prototype.postRender, postRender: (function () { + _$jscoverage['ui/splitbutton.js'][30]++; + this.Stateful_postRender(); + _$jscoverage['ui/splitbutton.js'][31]++; + this._UIBase_postRender(); +}), setPopup: (function (popup) { + _$jscoverage['ui/splitbutton.js'][34]++; + if ((this.popup === popup)) { + _$jscoverage['ui/splitbutton.js'][34]++; + return; + } + _$jscoverage['ui/splitbutton.js'][35]++; + if ((this.popup != null)) { + _$jscoverage['ui/splitbutton.js'][36]++; + this.popup.dispose(); + } + _$jscoverage['ui/splitbutton.js'][38]++; + popup.addListener("show", utils.bind(this._onPopupShow, this)); + _$jscoverage['ui/splitbutton.js'][39]++; + popup.addListener("hide", utils.bind(this._onPopupHide, this)); + _$jscoverage['ui/splitbutton.js'][40]++; + popup.addListener("postrender", utils.bind((function () { + _$jscoverage['ui/splitbutton.js'][41]++; + popup.getDom("body").appendChild(uiUtils.createElementByHtml(("
    "))); + _$jscoverage['ui/splitbutton.js'][46]++; + popup.getDom().className += (" " + this.className); +}), this)); + _$jscoverage['ui/splitbutton.js'][48]++; + this.popup = popup; +}), _onPopupShow: (function () { + _$jscoverage['ui/splitbutton.js'][51]++; + this.addState("opened"); +}), _onPopupHide: (function () { + _$jscoverage['ui/splitbutton.js'][54]++; + this.removeState("opened"); +}), getHtmlTpl: (function () { + _$jscoverage['ui/splitbutton.js'][57]++; + return ("
    " + "
    " + "
    " + "
    " + "
    " + "
    " + "
    " + "
    "); +}), showPopup: (function () { + _$jscoverage['ui/splitbutton.js'][68]++; + var rect = uiUtils.getClientRect(this.getDom()); + _$jscoverage['ui/splitbutton.js'][69]++; + rect.top -= this.popup.SHADOW_RADIUS; + _$jscoverage['ui/splitbutton.js'][70]++; + rect.height += this.popup.SHADOW_RADIUS; + _$jscoverage['ui/splitbutton.js'][71]++; + this.popup.showAnchorRect(rect); +}), _onArrowClick: (function (event, el) { + _$jscoverage['ui/splitbutton.js'][74]++; + if ((! this.isDisabled())) { + _$jscoverage['ui/splitbutton.js'][75]++; + this.showPopup(); + } +}), _onButtonClick: (function () { + _$jscoverage['ui/splitbutton.js'][79]++; + if ((! this.isDisabled())) { + _$jscoverage['ui/splitbutton.js'][80]++; + this.fireEvent("buttonclick"); + } +})}; + _$jscoverage['ui/splitbutton.js'][84]++; + utils.inherits(SplitButton, UIBase); + _$jscoverage['ui/splitbutton.js'][85]++; + utils.extend(SplitButton.prototype, Stateful, true); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/stateful.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/stateful.js new file mode 100644 index 000000000..61621e327 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/stateful.js @@ -0,0 +1,214 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/stateful.js']) { + _$jscoverage['ui/stateful.js'] = []; + _$jscoverage['ui/stateful.js'][1] = 0; + _$jscoverage['ui/stateful.js'][2] = 0; + _$jscoverage['ui/stateful.js'][6] = 0; + _$jscoverage['ui/stateful.js'][15] = 0; + _$jscoverage['ui/stateful.js'][19] = 0; + _$jscoverage['ui/stateful.js'][20] = 0; + _$jscoverage['ui/stateful.js'][23] = 0; + _$jscoverage['ui/stateful.js'][25] = 0; + _$jscoverage['ui/stateful.js'][28] = 0; + _$jscoverage['ui/stateful.js'][29] = 0; + _$jscoverage['ui/stateful.js'][30] = 0; + _$jscoverage['ui/stateful.js'][31] = 0; + _$jscoverage['ui/stateful.js'][35] = 0; + _$jscoverage['ui/stateful.js'][36] = 0; + _$jscoverage['ui/stateful.js'][37] = 0; + _$jscoverage['ui/stateful.js'][38] = 0; + _$jscoverage['ui/stateful.js'][42] = 0; + _$jscoverage['ui/stateful.js'][43] = 0; + _$jscoverage['ui/stateful.js'][44] = 0; + _$jscoverage['ui/stateful.js'][48] = 0; + _$jscoverage['ui/stateful.js'][49] = 0; + _$jscoverage['ui/stateful.js'][50] = 0; + _$jscoverage['ui/stateful.js'][54] = 0; + _$jscoverage['ui/stateful.js'][55] = 0; + _$jscoverage['ui/stateful.js'][59] = 0; + _$jscoverage['ui/stateful.js'][60] = 0; + _$jscoverage['ui/stateful.js'][64] = 0; + _$jscoverage['ui/stateful.js'][65] = 0; + _$jscoverage['ui/stateful.js'][69] = 0; + _$jscoverage['ui/stateful.js'][72] = 0; + _$jscoverage['ui/stateful.js'][73] = 0; + _$jscoverage['ui/stateful.js'][77] = 0; + _$jscoverage['ui/stateful.js'][78] = 0; + _$jscoverage['ui/stateful.js'][82] = 0; + _$jscoverage['ui/stateful.js'][85] = 0; + _$jscoverage['ui/stateful.js'][88] = 0; + _$jscoverage['ui/stateful.js'][89] = 0; + _$jscoverage['ui/stateful.js'][91] = 0; + _$jscoverage['ui/stateful.js'][95] = 0; + _$jscoverage['ui/stateful.js'][98] = 0; + _$jscoverage['ui/stateful.js'][99] = 0; + _$jscoverage['ui/stateful.js'][100] = 0; + _$jscoverage['ui/stateful.js'][101] = 0; + _$jscoverage['ui/stateful.js'][102] = 0; + _$jscoverage['ui/stateful.js'][104] = 0; +} +_$jscoverage['ui/stateful.js'].source = ["(function (){"," var browser = baidu.editor.browser,"," domUtils = baidu.editor.dom.domUtils,"," uiUtils = baidu.editor.ui.uiUtils;"," "," var TPL_STATEFUL = 'onmousedown=\"$$.Stateful_onMouseDown(event, this);\"' +"," ' onmouseup=\"$$.Stateful_onMouseUp(event, this);\"' +"," ( browser.ie ? ("," ' onmouseenter=\"$$.Stateful_onMouseEnter(event, this);\"' +"," ' onmouseleave=\"$$.Stateful_onMouseLeave(event, this);\"' )"," : ("," ' onmouseover=\"$$.Stateful_onMouseOver(event, this);\"' +"," ' onmouseout=\"$$.Stateful_onMouseOut(event, this);\"' ));"," "," baidu.editor.ui.Stateful = {"," alwalysHoverable: false,"," target:null,//目标元素和this指向dom不一样"," Stateful_init: function (){"," this._Stateful_dGetHtmlTpl = this.getHtmlTpl;"," this.getHtmlTpl = this.Stateful_getHtmlTpl;"," },"," Stateful_getHtmlTpl: function (){"," var tpl = this._Stateful_dGetHtmlTpl();"," // 使用function避免$转义"," return tpl.replace(/stateful/g, function (){ return TPL_STATEFUL; });"," },"," Stateful_onMouseEnter: function (evt, el){"," this.target=el;"," if (!this.isDisabled() || this.alwalysHoverable) {"," this.addState('hover');"," this.fireEvent('over');"," }"," },"," Stateful_onMouseLeave: function (evt, el){"," if (!this.isDisabled() || this.alwalysHoverable) {"," this.removeState('hover');"," this.removeState('active');"," this.fireEvent('out');"," }"," },"," Stateful_onMouseOver: function (evt, el){"," var rel = evt.relatedTarget;"," if (!uiUtils.contains(el, rel) && el !== rel) {"," this.Stateful_onMouseEnter(evt, el);"," }"," },"," Stateful_onMouseOut: function (evt, el){"," var rel = evt.relatedTarget;"," if (!uiUtils.contains(el, rel) && el !== rel) {"," this.Stateful_onMouseLeave(evt, el);"," }"," },"," Stateful_onMouseDown: function (evt, el){"," if (!this.isDisabled()) {"," this.addState('active');"," }"," },"," Stateful_onMouseUp: function (evt, el){"," if (!this.isDisabled()) {"," this.removeState('active');"," }"," },"," Stateful_postRender: function (){"," if (this.disabled && !this.hasState('disabled')) {"," this.addState('disabled');"," }"," },"," hasState: function (state){"," return domUtils.hasClass(this.getStateDom(), 'edui-state-' + state);"," },"," addState: function (state){"," if (!this.hasState(state)) {"," this.getStateDom().className += ' edui-state-' + state;"," }"," },"," removeState: function (state){"," if (this.hasState(state)) {"," domUtils.removeClasses(this.getStateDom(), ['edui-state-' + state]);"," }"," },"," getStateDom: function (){"," return this.getDom('state');"," },"," isChecked: function (){"," return this.hasState('checked');"," },"," setChecked: function (checked){"," if (!this.isDisabled() && checked) {"," this.addState('checked');"," } else {"," this.removeState('checked');"," }"," },"," isDisabled: function (){"," return this.hasState('disabled');"," },"," setDisabled: function (disabled){"," if (disabled) {"," this.removeState('hover');"," this.removeState('checked');"," this.removeState('active');"," this.addState('disabled');"," } else {"," this.removeState('disabled');"," }"," }"," };","})();"]; +_$jscoverage['ui/stateful.js'][1]++; +(function () { + _$jscoverage['ui/stateful.js'][2]++; + var browser = baidu.editor.browser, domUtils = baidu.editor.dom.domUtils, uiUtils = baidu.editor.ui.uiUtils; + _$jscoverage['ui/stateful.js'][6]++; + var TPL_STATEFUL = ("onmousedown=\"$$.Stateful_onMouseDown(event, this);\"" + " onmouseup=\"$$.Stateful_onMouseUp(event, this);\"" + (browser.ie? " onmouseenter=\"$$.Stateful_onMouseEnter(event, this);\" onmouseleave=\"$$.Stateful_onMouseLeave(event, this);\"": " onmouseover=\"$$.Stateful_onMouseOver(event, this);\" onmouseout=\"$$.Stateful_onMouseOut(event, this);\"")); + _$jscoverage['ui/stateful.js'][15]++; + baidu.editor.ui.Stateful = {alwalysHoverable: false, target: null, Stateful_init: (function () { + _$jscoverage['ui/stateful.js'][19]++; + this._Stateful_dGetHtmlTpl = this.getHtmlTpl; + _$jscoverage['ui/stateful.js'][20]++; + this.getHtmlTpl = this.Stateful_getHtmlTpl; +}), Stateful_getHtmlTpl: (function () { + _$jscoverage['ui/stateful.js'][23]++; + var tpl = this._Stateful_dGetHtmlTpl(); + _$jscoverage['ui/stateful.js'][25]++; + return tpl.replace(/stateful/g, (function () { + _$jscoverage['ui/stateful.js'][25]++; + return TPL_STATEFUL; +})); +}), Stateful_onMouseEnter: (function (evt, el) { + _$jscoverage['ui/stateful.js'][28]++; + this.target = el; + _$jscoverage['ui/stateful.js'][29]++; + if (((! this.isDisabled()) || this.alwalysHoverable)) { + _$jscoverage['ui/stateful.js'][30]++; + this.addState("hover"); + _$jscoverage['ui/stateful.js'][31]++; + this.fireEvent("over"); + } +}), Stateful_onMouseLeave: (function (evt, el) { + _$jscoverage['ui/stateful.js'][35]++; + if (((! this.isDisabled()) || this.alwalysHoverable)) { + _$jscoverage['ui/stateful.js'][36]++; + this.removeState("hover"); + _$jscoverage['ui/stateful.js'][37]++; + this.removeState("active"); + _$jscoverage['ui/stateful.js'][38]++; + this.fireEvent("out"); + } +}), Stateful_onMouseOver: (function (evt, el) { + _$jscoverage['ui/stateful.js'][42]++; + var rel = evt.relatedTarget; + _$jscoverage['ui/stateful.js'][43]++; + if (((! uiUtils.contains(el, rel)) && (el !== rel))) { + _$jscoverage['ui/stateful.js'][44]++; + this.Stateful_onMouseEnter(evt, el); + } +}), Stateful_onMouseOut: (function (evt, el) { + _$jscoverage['ui/stateful.js'][48]++; + var rel = evt.relatedTarget; + _$jscoverage['ui/stateful.js'][49]++; + if (((! uiUtils.contains(el, rel)) && (el !== rel))) { + _$jscoverage['ui/stateful.js'][50]++; + this.Stateful_onMouseLeave(evt, el); + } +}), Stateful_onMouseDown: (function (evt, el) { + _$jscoverage['ui/stateful.js'][54]++; + if ((! this.isDisabled())) { + _$jscoverage['ui/stateful.js'][55]++; + this.addState("active"); + } +}), Stateful_onMouseUp: (function (evt, el) { + _$jscoverage['ui/stateful.js'][59]++; + if ((! this.isDisabled())) { + _$jscoverage['ui/stateful.js'][60]++; + this.removeState("active"); + } +}), Stateful_postRender: (function () { + _$jscoverage['ui/stateful.js'][64]++; + if ((this.disabled && (! this.hasState("disabled")))) { + _$jscoverage['ui/stateful.js'][65]++; + this.addState("disabled"); + } +}), hasState: (function (state) { + _$jscoverage['ui/stateful.js'][69]++; + return domUtils.hasClass(this.getStateDom(), ("edui-state-" + state)); +}), addState: (function (state) { + _$jscoverage['ui/stateful.js'][72]++; + if ((! this.hasState(state))) { + _$jscoverage['ui/stateful.js'][73]++; + this.getStateDom().className += (" edui-state-" + state); + } +}), removeState: (function (state) { + _$jscoverage['ui/stateful.js'][77]++; + if (this.hasState(state)) { + _$jscoverage['ui/stateful.js'][78]++; + domUtils.removeClasses(this.getStateDom(), [("edui-state-" + state)]); + } +}), getStateDom: (function () { + _$jscoverage['ui/stateful.js'][82]++; + return this.getDom("state"); +}), isChecked: (function () { + _$jscoverage['ui/stateful.js'][85]++; + return this.hasState("checked"); +}), setChecked: (function (checked) { + _$jscoverage['ui/stateful.js'][88]++; + if (((! this.isDisabled()) && checked)) { + _$jscoverage['ui/stateful.js'][89]++; + this.addState("checked"); + } + else { + _$jscoverage['ui/stateful.js'][91]++; + this.removeState("checked"); + } +}), isDisabled: (function () { + _$jscoverage['ui/stateful.js'][95]++; + return this.hasState("disabled"); +}), setDisabled: (function (disabled) { + _$jscoverage['ui/stateful.js'][98]++; + if (disabled) { + _$jscoverage['ui/stateful.js'][99]++; + this.removeState("hover"); + _$jscoverage['ui/stateful.js'][100]++; + this.removeState("checked"); + _$jscoverage['ui/stateful.js'][101]++; + this.removeState("active"); + _$jscoverage['ui/stateful.js'][102]++; + this.addState("disabled"); + } + else { + _$jscoverage['ui/stateful.js'][104]++; + this.removeState("disabled"); + } +})}; +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/tablebutton.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/tablebutton.js new file mode 100644 index 000000000..1460e41de --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/tablebutton.js @@ -0,0 +1,85 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/tablebutton.js']) { + _$jscoverage['ui/tablebutton.js'] = []; + _$jscoverage['ui/tablebutton.js'][6] = 0; + _$jscoverage['ui/tablebutton.js'][7] = 0; + _$jscoverage['ui/tablebutton.js'][12] = 0; + _$jscoverage['ui/tablebutton.js'][13] = 0; + _$jscoverage['ui/tablebutton.js'][15] = 0; + _$jscoverage['ui/tablebutton.js'][17] = 0; + _$jscoverage['ui/tablebutton.js'][18] = 0; + _$jscoverage['ui/tablebutton.js'][22] = 0; + _$jscoverage['ui/tablebutton.js'][27] = 0; + _$jscoverage['ui/tablebutton.js'][30] = 0; + _$jscoverage['ui/tablebutton.js'][31] = 0; + _$jscoverage['ui/tablebutton.js'][35] = 0; +} +_$jscoverage['ui/tablebutton.js'].source = ["///import core","///import uicore","///import ui/popup.js","///import ui/tablepicker.js","///import ui/splitbutton.js","(function (){"," var utils = baidu.editor.utils,"," Popup = baidu.editor.ui.Popup,"," TablePicker = baidu.editor.ui.TablePicker,"," SplitButton = baidu.editor.ui.SplitButton,"," TableButton = baidu.editor.ui.TableButton = function (options){"," this.initOptions(options);"," this.initTableButton();"," };"," TableButton.prototype = {"," initTableButton: function (){"," var me = this;"," this.popup = new Popup({"," content: new TablePicker({"," editor:me.editor,"," onpicktable: function (t, numCols, numRows){"," me._onPickTable(numCols, numRows);"," }"," }),"," 'editor':me.editor"," });"," this.initSplitButton();"," },"," _onPickTable: function (numCols, numRows){"," if (this.fireEvent('picktable', numCols, numRows) !== false) {"," this.popup.hide();"," }"," }"," };"," utils.inherits(TableButton, SplitButton);","","})();"]; +_$jscoverage['ui/tablebutton.js'][6]++; +(function () { + _$jscoverage['ui/tablebutton.js'][7]++; + var utils = baidu.editor.utils, Popup = baidu.editor.ui.Popup, TablePicker = baidu.editor.ui.TablePicker, SplitButton = baidu.editor.ui.SplitButton, TableButton = (baidu.editor.ui.TableButton = (function (options) { + _$jscoverage['ui/tablebutton.js'][12]++; + this.initOptions(options); + _$jscoverage['ui/tablebutton.js'][13]++; + this.initTableButton(); +})); + _$jscoverage['ui/tablebutton.js'][15]++; + TableButton.prototype = {initTableButton: (function () { + _$jscoverage['ui/tablebutton.js'][17]++; + var me = this; + _$jscoverage['ui/tablebutton.js'][18]++; + this.popup = new Popup({content: new TablePicker({editor: me.editor, onpicktable: (function (t, numCols, numRows) { + _$jscoverage['ui/tablebutton.js'][22]++; + me._onPickTable(numCols, numRows); +})}), "editor": me.editor}); + _$jscoverage['ui/tablebutton.js'][27]++; + this.initSplitButton(); +}), _onPickTable: (function (numCols, numRows) { + _$jscoverage['ui/tablebutton.js'][30]++; + if ((this.fireEvent("picktable", numCols, numRows) !== false)) { + _$jscoverage['ui/tablebutton.js'][31]++; + this.popup.hide(); + } +})}; + _$jscoverage['ui/tablebutton.js'][35]++; + utils.inherits(TableButton, SplitButton); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/tablepicker.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/tablepicker.js new file mode 100644 index 000000000..255faa362 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/tablepicker.js @@ -0,0 +1,160 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/tablepicker.js']) { + _$jscoverage['ui/tablepicker.js'] = []; + _$jscoverage['ui/tablepicker.js'][3] = 0; + _$jscoverage['ui/tablepicker.js'][4] = 0; + _$jscoverage['ui/tablepicker.js'][8] = 0; + _$jscoverage['ui/tablepicker.js'][9] = 0; + _$jscoverage['ui/tablepicker.js'][10] = 0; + _$jscoverage['ui/tablepicker.js'][12] = 0; + _$jscoverage['ui/tablepicker.js'][21] = 0; + _$jscoverage['ui/tablepicker.js'][24] = 0; + _$jscoverage['ui/tablepicker.js'][25] = 0; + _$jscoverage['ui/tablepicker.js'][43] = 0; + _$jscoverage['ui/tablepicker.js'][44] = 0; + _$jscoverage['ui/tablepicker.js'][47] = 0; + _$jscoverage['ui/tablepicker.js'][48] = 0; + _$jscoverage['ui/tablepicker.js'][49] = 0; + _$jscoverage['ui/tablepicker.js'][50] = 0; + _$jscoverage['ui/tablepicker.js'][51] = 0; + _$jscoverage['ui/tablepicker.js'][52] = 0; + _$jscoverage['ui/tablepicker.js'][53] = 0; + _$jscoverage['ui/tablepicker.js'][54] = 0; + _$jscoverage['ui/tablepicker.js'][57] = 0; + _$jscoverage['ui/tablepicker.js'][58] = 0; + _$jscoverage['ui/tablepicker.js'][59] = 0; + _$jscoverage['ui/tablepicker.js'][60] = 0; + _$jscoverage['ui/tablepicker.js'][64] = 0; + _$jscoverage['ui/tablepicker.js'][65] = 0; + _$jscoverage['ui/tablepicker.js'][66] = 0; + _$jscoverage['ui/tablepicker.js'][67] = 0; + _$jscoverage['ui/tablepicker.js'][71] = 0; + _$jscoverage['ui/tablepicker.js'][72] = 0; + _$jscoverage['ui/tablepicker.js'][73] = 0; + _$jscoverage['ui/tablepicker.js'][74] = 0; + _$jscoverage['ui/tablepicker.js'][75] = 0; + _$jscoverage['ui/tablepicker.js'][76] = 0; + _$jscoverage['ui/tablepicker.js'][79] = 0; + _$jscoverage['ui/tablepicker.js'][82] = 0; +} +_$jscoverage['ui/tablepicker.js'].source = ["///import core","///import uicore","(function (){"," var utils = baidu.editor.utils,"," uiUtils = baidu.editor.ui.uiUtils,"," UIBase = baidu.editor.ui.UIBase;"," "," var TablePicker = baidu.editor.ui.TablePicker = function (options){"," this.initOptions(options);"," this.initTablePicker();"," };"," TablePicker.prototype = {"," defaultNumRows: 10,"," defaultNumCols: 10,"," maxNumRows: 20,"," maxNumCols: 20,"," numRows: 10,"," numCols: 10,"," lengthOfCellSide: 22,"," initTablePicker: function (){"," this.initUIBase();"," },"," getHtmlTpl: function (){"," var me = this;"," return '<div id=\"##\" class=\"edui-tablepicker %%\">' +"," '<div class=\"edui-tablepicker-body\">' +"," '<div class=\"edui-infoarea\">' +"," '<span id=\"##_label\" class=\"edui-label\"></span>' +"," '</div>' +"," '<div class=\"edui-pickarea\"' +"," ' onmousemove=\"$$._onMouseMove(event, this);\"' +"," ' onmouseover=\"$$._onMouseOver(event, this);\"' +"," ' onmouseout=\"$$._onMouseOut(event, this);\"' +"," ' onclick=\"$$._onClick(event, this);\"' +"," '>' +"," '<div id=\"##_overlay\" class=\"edui-overlay\"></div>' +"," '</div>' +"," '</div>' +"," '</div>';"," },"," _UIBase_render: UIBase.prototype.render,"," render: function (holder){"," this._UIBase_render(holder);"," this.getDom('label').innerHTML = '0'+this.editor.getLang(\"t_row\")+' x 0'+this.editor.getLang(\"t_col\");"," },"," _track: function (numCols, numRows){"," var style = this.getDom('overlay').style;"," var sideLen = this.lengthOfCellSide;"," style.width = numCols * sideLen + 'px';"," style.height = numRows * sideLen + 'px';"," var label = this.getDom('label');"," label.innerHTML = numCols +this.editor.getLang(\"t_col\")+' x ' + numRows + this.editor.getLang(\"t_row\");"," this.numCols = numCols;"," this.numRows = numRows;"," },"," _onMouseOver: function (evt, el){"," var rel = evt.relatedTarget || evt.fromElement;"," if (!uiUtils.contains(el, rel) && el !== rel) {"," this.getDom('label').innerHTML = '0'+this.editor.getLang(\"t_col\")+' x 0'+this.editor.getLang(\"t_row\");"," this.getDom('overlay').style.visibility = '';"," }"," },"," _onMouseOut: function (evt, el){"," var rel = evt.relatedTarget || evt.toElement;"," if (!uiUtils.contains(el, rel) && el !== rel) {"," this.getDom('label').innerHTML = '0'+this.editor.getLang(\"t_col\")+' x 0'+this.editor.getLang(\"t_row\");"," this.getDom('overlay').style.visibility = 'hidden';"," }"," },"," _onMouseMove: function (evt, el){"," var style = this.getDom('overlay').style;"," var offset = uiUtils.getEventOffset(evt);"," var sideLen = this.lengthOfCellSide;"," var numCols = Math.ceil(offset.left / sideLen);"," var numRows = Math.ceil(offset.top / sideLen);"," this._track(numCols, numRows);"," },"," _onClick: function (){"," this.fireEvent('picktable', this.numCols, this.numRows);"," }"," };"," utils.inherits(TablePicker, UIBase);","})();"]; +_$jscoverage['ui/tablepicker.js'][3]++; +(function () { + _$jscoverage['ui/tablepicker.js'][4]++; + var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, UIBase = baidu.editor.ui.UIBase; + _$jscoverage['ui/tablepicker.js'][8]++; + var TablePicker = (baidu.editor.ui.TablePicker = (function (options) { + _$jscoverage['ui/tablepicker.js'][9]++; + this.initOptions(options); + _$jscoverage['ui/tablepicker.js'][10]++; + this.initTablePicker(); +})); + _$jscoverage['ui/tablepicker.js'][12]++; + TablePicker.prototype = {defaultNumRows: 10, defaultNumCols: 10, maxNumRows: 20, maxNumCols: 20, numRows: 10, numCols: 10, lengthOfCellSide: 22, initTablePicker: (function () { + _$jscoverage['ui/tablepicker.js'][21]++; + this.initUIBase(); +}), getHtmlTpl: (function () { + _$jscoverage['ui/tablepicker.js'][24]++; + var me = this; + _$jscoverage['ui/tablepicker.js'][25]++; + return "
    "; +}), _UIBase_render: UIBase.prototype.render, render: (function (holder) { + _$jscoverage['ui/tablepicker.js'][43]++; + this._UIBase_render(holder); + _$jscoverage['ui/tablepicker.js'][44]++; + this.getDom("label").innerHTML = ("0" + this.editor.getLang("t_row") + " x 0" + this.editor.getLang("t_col")); +}), _track: (function (numCols, numRows) { + _$jscoverage['ui/tablepicker.js'][47]++; + var style = this.getDom("overlay").style; + _$jscoverage['ui/tablepicker.js'][48]++; + var sideLen = this.lengthOfCellSide; + _$jscoverage['ui/tablepicker.js'][49]++; + style.width = ((numCols * sideLen) + "px"); + _$jscoverage['ui/tablepicker.js'][50]++; + style.height = ((numRows * sideLen) + "px"); + _$jscoverage['ui/tablepicker.js'][51]++; + var label = this.getDom("label"); + _$jscoverage['ui/tablepicker.js'][52]++; + label.innerHTML = (numCols + this.editor.getLang("t_col") + " x " + numRows + this.editor.getLang("t_row")); + _$jscoverage['ui/tablepicker.js'][53]++; + this.numCols = numCols; + _$jscoverage['ui/tablepicker.js'][54]++; + this.numRows = numRows; +}), _onMouseOver: (function (evt, el) { + _$jscoverage['ui/tablepicker.js'][57]++; + var rel = (evt.relatedTarget || evt.fromElement); + _$jscoverage['ui/tablepicker.js'][58]++; + if (((! uiUtils.contains(el, rel)) && (el !== rel))) { + _$jscoverage['ui/tablepicker.js'][59]++; + this.getDom("label").innerHTML = ("0" + this.editor.getLang("t_col") + " x 0" + this.editor.getLang("t_row")); + _$jscoverage['ui/tablepicker.js'][60]++; + this.getDom("overlay").style.visibility = ""; + } +}), _onMouseOut: (function (evt, el) { + _$jscoverage['ui/tablepicker.js'][64]++; + var rel = (evt.relatedTarget || evt.toElement); + _$jscoverage['ui/tablepicker.js'][65]++; + if (((! uiUtils.contains(el, rel)) && (el !== rel))) { + _$jscoverage['ui/tablepicker.js'][66]++; + this.getDom("label").innerHTML = ("0" + this.editor.getLang("t_col") + " x 0" + this.editor.getLang("t_row")); + _$jscoverage['ui/tablepicker.js'][67]++; + this.getDom("overlay").style.visibility = "hidden"; + } +}), _onMouseMove: (function (evt, el) { + _$jscoverage['ui/tablepicker.js'][71]++; + var style = this.getDom("overlay").style; + _$jscoverage['ui/tablepicker.js'][72]++; + var offset = uiUtils.getEventOffset(evt); + _$jscoverage['ui/tablepicker.js'][73]++; + var sideLen = this.lengthOfCellSide; + _$jscoverage['ui/tablepicker.js'][74]++; + var numCols = Math.ceil((offset.left / sideLen)); + _$jscoverage['ui/tablepicker.js'][75]++; + var numRows = Math.ceil((offset.top / sideLen)); + _$jscoverage['ui/tablepicker.js'][76]++; + this._track(numCols, numRows); +}), _onClick: (function () { + _$jscoverage['ui/tablepicker.js'][79]++; + this.fireEvent("picktable", this.numCols, this.numRows); +})}; + _$jscoverage['ui/tablepicker.js'][82]++; + utils.inherits(TablePicker, UIBase); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/toolbar.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/toolbar.js new file mode 100644 index 000000000..7ec17ec85 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/toolbar.js @@ -0,0 +1,106 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/toolbar.js']) { + _$jscoverage['ui/toolbar.js'] = []; + _$jscoverage['ui/toolbar.js'][1] = 0; + _$jscoverage['ui/toolbar.js'][2] = 0; + _$jscoverage['ui/toolbar.js'][6] = 0; + _$jscoverage['ui/toolbar.js'][7] = 0; + _$jscoverage['ui/toolbar.js'][9] = 0; + _$jscoverage['ui/toolbar.js'][12] = 0; + _$jscoverage['ui/toolbar.js'][13] = 0; + _$jscoverage['ui/toolbar.js'][16] = 0; + _$jscoverage['ui/toolbar.js'][19] = 0; + _$jscoverage['ui/toolbar.js'][20] = 0; + _$jscoverage['ui/toolbar.js'][21] = 0; + _$jscoverage['ui/toolbar.js'][23] = 0; + _$jscoverage['ui/toolbar.js'][28] = 0; + _$jscoverage['ui/toolbar.js'][29] = 0; + _$jscoverage['ui/toolbar.js'][30] = 0; + _$jscoverage['ui/toolbar.js'][32] = 0; + _$jscoverage['ui/toolbar.js'][35] = 0; + _$jscoverage['ui/toolbar.js'][38] = 0; +} +_$jscoverage['ui/toolbar.js'].source = ["(function (){"," var utils = baidu.editor.utils,"," uiUtils = baidu.editor.ui.uiUtils,"," UIBase = baidu.editor.ui.UIBase,"," Toolbar = baidu.editor.ui.Toolbar = function (options){"," this.initOptions(options);"," this.initToolbar();"," };"," Toolbar.prototype = {"," items: null,"," initToolbar: function (){"," this.items = this.items || [];"," this.initUIBase();"," },"," add: function (item){"," this.items.push(item);"," },"," getHtmlTpl: function (){"," var buff = [];"," for (var i=0; i<this.items.length; i++) {"," buff[i] = this.items[i].renderHtml();"," }"," return '<div id=\"##\" class=\"edui-toolbar %%\" onselectstart=\"return false;\" onmousedown=\"return $$._onMouseDown(event, this);\">' +"," buff.join('') +"," '</div>'"," },"," postRender: function (){"," var box = this.getDom();"," for (var i=0; i<this.items.length; i++) {"," this.items[i].postRender();"," }"," uiUtils.makeUnselectable(box);"," },"," _onMouseDown: function (){"," return false;"," }"," };"," utils.inherits(Toolbar, UIBase);","","})();"]; +_$jscoverage['ui/toolbar.js'][1]++; +(function () { + _$jscoverage['ui/toolbar.js'][2]++; + var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, UIBase = baidu.editor.ui.UIBase, Toolbar = (baidu.editor.ui.Toolbar = (function (options) { + _$jscoverage['ui/toolbar.js'][6]++; + this.initOptions(options); + _$jscoverage['ui/toolbar.js'][7]++; + this.initToolbar(); +})); + _$jscoverage['ui/toolbar.js'][9]++; + Toolbar.prototype = {items: null, initToolbar: (function () { + _$jscoverage['ui/toolbar.js'][12]++; + this.items = (this.items || []); + _$jscoverage['ui/toolbar.js'][13]++; + this.initUIBase(); +}), add: (function (item) { + _$jscoverage['ui/toolbar.js'][16]++; + this.items.push(item); +}), getHtmlTpl: (function () { + _$jscoverage['ui/toolbar.js'][19]++; + var buff = []; + _$jscoverage['ui/toolbar.js'][20]++; + for (var i = 0; (i < this.items.length); (i++)) { + _$jscoverage['ui/toolbar.js'][21]++; + buff[i] = this.items[i].renderHtml(); +} + _$jscoverage['ui/toolbar.js'][23]++; + return ("
    " + buff.join("") + "
    "); +}), postRender: (function () { + _$jscoverage['ui/toolbar.js'][28]++; + var box = this.getDom(); + _$jscoverage['ui/toolbar.js'][29]++; + for (var i = 0; (i < this.items.length); (i++)) { + _$jscoverage['ui/toolbar.js'][30]++; + this.items[i].postRender(); +} + _$jscoverage['ui/toolbar.js'][32]++; + uiUtils.makeUnselectable(box); +}), _onMouseDown: (function () { + _$jscoverage['ui/toolbar.js'][35]++; + return false; +})}; + _$jscoverage['ui/toolbar.js'][38]++; + utils.inherits(Toolbar, UIBase); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/ui.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/ui.js new file mode 100644 index 000000000..0f59b2cef --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/ui.js @@ -0,0 +1,52 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/ui.js']) { + _$jscoverage['ui/ui.js'] = []; + _$jscoverage['ui/ui.js'][1] = 0; + _$jscoverage['ui/ui.js'][2] = 0; + _$jscoverage['ui/ui.js'][3] = 0; +} +_$jscoverage['ui/ui.js'].source = ["var baidu = baidu || {};","baidu.editor = baidu.editor || {};","baidu.editor.ui = {};"]; +_$jscoverage['ui/ui.js'][1]++; +var baidu = (baidu || {}); +_$jscoverage['ui/ui.js'][2]++; +baidu.editor = (baidu.editor || {}); +_$jscoverage['ui/ui.js'][3]++; +baidu.editor.ui = {}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/uibase.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/uibase.js new file mode 100644 index 000000000..cd2583fd7 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/uibase.js @@ -0,0 +1,190 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/uibase.js']) { + _$jscoverage['ui/uibase.js'] = []; + _$jscoverage['ui/uibase.js'][1] = 0; + _$jscoverage['ui/uibase.js'][2] = 0; + _$jscoverage['ui/uibase.js'][8] = 0; + _$jscoverage['ui/uibase.js'][12] = 0; + _$jscoverage['ui/uibase.js'][13] = 0; + _$jscoverage['ui/uibase.js'][14] = 0; + _$jscoverage['ui/uibase.js'][16] = 0; + _$jscoverage['ui/uibase.js'][19] = 0; + _$jscoverage['ui/uibase.js'][22] = 0; + _$jscoverage['ui/uibase.js'][23] = 0; + _$jscoverage['ui/uibase.js'][26] = 0; + _$jscoverage['ui/uibase.js'][27] = 0; + _$jscoverage['ui/uibase.js'][28] = 0; + _$jscoverage['ui/uibase.js'][29] = 0; + _$jscoverage['ui/uibase.js'][30] = 0; + _$jscoverage['ui/uibase.js'][32] = 0; + _$jscoverage['ui/uibase.js'][33] = 0; + _$jscoverage['ui/uibase.js'][34] = 0; + _$jscoverage['ui/uibase.js'][35] = 0; + _$jscoverage['ui/uibase.js'][38] = 0; + _$jscoverage['ui/uibase.js'][39] = 0; + _$jscoverage['ui/uibase.js'][40] = 0; + _$jscoverage['ui/uibase.js'][41] = 0; + _$jscoverage['ui/uibase.js'][43] = 0; + _$jscoverage['ui/uibase.js'][44] = 0; + _$jscoverage['ui/uibase.js'][46] = 0; + _$jscoverage['ui/uibase.js'][47] = 0; + _$jscoverage['ui/uibase.js'][48] = 0; + _$jscoverage['ui/uibase.js'][50] = 0; + _$jscoverage['ui/uibase.js'][53] = 0; + _$jscoverage['ui/uibase.js'][54] = 0; + _$jscoverage['ui/uibase.js'][56] = 0; + _$jscoverage['ui/uibase.js'][60] = 0; + _$jscoverage['ui/uibase.js'][63] = 0; + _$jscoverage['ui/uibase.js'][66] = 0; + _$jscoverage['ui/uibase.js'][67] = 0; + _$jscoverage['ui/uibase.js'][74] = 0; + _$jscoverage['ui/uibase.js'][77] = 0; + _$jscoverage['ui/uibase.js'][78] = 0; + _$jscoverage['ui/uibase.js'][79] = 0; + _$jscoverage['ui/uibase.js'][82] = 0; +} +_$jscoverage['ui/uibase.js'].source = ["(function () {"," var utils = baidu.editor.utils,"," uiUtils = baidu.editor.ui.uiUtils,"," EventBase = baidu.editor.EventBase,"," UIBase = baidu.editor.ui.UIBase = function () {"," };",""," UIBase.prototype = {"," className:'',"," uiName:'',"," initOptions:function (options) {"," var me = this;"," for (var k in options) {"," me[k] = options[k];"," }"," this.id = this.id || 'edui' + uiUtils.uid();"," },"," initUIBase:function () {"," this._globalKey = utils.unhtml(uiUtils.setGlobal(this.id, this));"," },"," render:function (holder) {"," var html = this.renderHtml();"," var el = uiUtils.createElementByHtml(html);",""," //by xuheng 给每个node添加class"," var list = domUtils.getElementsByTagName(el, \"*\");"," var theme = \"edui-\" + (this.theme || this.editor.options.theme);"," var layer = document.getElementById('edui_fixedlayer');"," for (var i = 0, node; node = list[i++];) {"," domUtils.addClass(node, theme);"," }"," domUtils.addClass(el, theme);"," if(layer){"," layer.className=\"\";"," domUtils.addClass(layer,theme);"," }",""," var seatEl = this.getDom();"," if (seatEl != null) {"," seatEl.parentNode.replaceChild(el, seatEl);"," uiUtils.copyAttributes(el, seatEl);"," } else {"," if (typeof holder == 'string') {"," holder = document.getElementById(holder);"," }"," holder = holder || uiUtils.getFixedLayer();"," domUtils.addClass(holder, theme);"," holder.appendChild(el);"," }"," this.postRender();"," },"," getDom:function (name) {"," if (!name) {"," return document.getElementById(this.id);"," } else {"," return document.getElementById(this.id + '_' + name);"," }"," },"," postRender:function () {"," this.fireEvent('postrender');"," },"," getHtmlTpl:function () {"," return '';"," },"," formatHtml:function (tpl) {"," var prefix = 'edui-' + this.uiName;"," return (tpl"," .replace(/##/g, this.id)"," .replace(/%%-/g, this.uiName ? prefix + '-' : '')"," .replace(/%%/g, (this.uiName ? prefix : '') + ' ' + this.className)"," .replace(/\\$\\$/g, this._globalKey));"," },"," renderHtml:function () {"," return this.formatHtml(this.getHtmlTpl());"," },"," dispose:function () {"," var box = this.getDom();"," if (box) baidu.editor.dom.domUtils.remove(box);"," uiUtils.unsetGlobal(this.id);"," }"," };"," utils.inherits(UIBase, EventBase);","})();"]; +_$jscoverage['ui/uibase.js'][1]++; +(function () { + _$jscoverage['ui/uibase.js'][2]++; + var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, EventBase = baidu.editor.EventBase, UIBase = (baidu.editor.ui.UIBase = (function () { +})); + _$jscoverage['ui/uibase.js'][8]++; + UIBase.prototype = {className: "", uiName: "", initOptions: (function (options) { + _$jscoverage['ui/uibase.js'][12]++; + var me = this; + _$jscoverage['ui/uibase.js'][13]++; + for (var k in options) { + _$jscoverage['ui/uibase.js'][14]++; + me[k] = options[k]; +} + _$jscoverage['ui/uibase.js'][16]++; + this.id = (this.id || ("edui" + uiUtils.uid())); +}), initUIBase: (function () { + _$jscoverage['ui/uibase.js'][19]++; + this._globalKey = utils.unhtml(uiUtils.setGlobal(this.id, this)); +}), render: (function (holder) { + _$jscoverage['ui/uibase.js'][22]++; + var html = this.renderHtml(); + _$jscoverage['ui/uibase.js'][23]++; + var el = uiUtils.createElementByHtml(html); + _$jscoverage['ui/uibase.js'][26]++; + var list = domUtils.getElementsByTagName(el, "*"); + _$jscoverage['ui/uibase.js'][27]++; + var theme = ("edui-" + (this.theme || this.editor.options.theme)); + _$jscoverage['ui/uibase.js'][28]++; + var layer = document.getElementById("edui_fixedlayer"); + _$jscoverage['ui/uibase.js'][29]++; + for (var i = 0, node; (node = list[(i++)]);) { + _$jscoverage['ui/uibase.js'][30]++; + domUtils.addClass(node, theme); +} + _$jscoverage['ui/uibase.js'][32]++; + domUtils.addClass(el, theme); + _$jscoverage['ui/uibase.js'][33]++; + if (layer) { + _$jscoverage['ui/uibase.js'][34]++; + layer.className = ""; + _$jscoverage['ui/uibase.js'][35]++; + domUtils.addClass(layer, theme); + } + _$jscoverage['ui/uibase.js'][38]++; + var seatEl = this.getDom(); + _$jscoverage['ui/uibase.js'][39]++; + if ((seatEl != null)) { + _$jscoverage['ui/uibase.js'][40]++; + seatEl.parentNode.replaceChild(el, seatEl); + _$jscoverage['ui/uibase.js'][41]++; + uiUtils.copyAttributes(el, seatEl); + } + else { + _$jscoverage['ui/uibase.js'][43]++; + if (((typeof holder) == "string")) { + _$jscoverage['ui/uibase.js'][44]++; + holder = document.getElementById(holder); + } + _$jscoverage['ui/uibase.js'][46]++; + holder = (holder || uiUtils.getFixedLayer()); + _$jscoverage['ui/uibase.js'][47]++; + domUtils.addClass(holder, theme); + _$jscoverage['ui/uibase.js'][48]++; + holder.appendChild(el); + } + _$jscoverage['ui/uibase.js'][50]++; + this.postRender(); +}), getDom: (function (name) { + _$jscoverage['ui/uibase.js'][53]++; + if ((! name)) { + _$jscoverage['ui/uibase.js'][54]++; + return document.getElementById(this.id); + } + else { + _$jscoverage['ui/uibase.js'][56]++; + return document.getElementById((this.id + "_" + name)); + } +}), postRender: (function () { + _$jscoverage['ui/uibase.js'][60]++; + this.fireEvent("postrender"); +}), getHtmlTpl: (function () { + _$jscoverage['ui/uibase.js'][63]++; + return ""; +}), formatHtml: (function (tpl) { + _$jscoverage['ui/uibase.js'][66]++; + var prefix = ("edui-" + this.uiName); + _$jscoverage['ui/uibase.js'][67]++; + return tpl.replace(/##/g, this.id).replace(/%%-/g, (this.uiName? (prefix + "-"): "")).replace(/%%/g, ((this.uiName? prefix: "") + " " + this.className)).replace(/\$\$/g, this._globalKey); +}), renderHtml: (function () { + _$jscoverage['ui/uibase.js'][74]++; + return this.formatHtml(this.getHtmlTpl()); +}), dispose: (function () { + _$jscoverage['ui/uibase.js'][77]++; + var box = this.getDom(); + _$jscoverage['ui/uibase.js'][78]++; + if (box) { + _$jscoverage['ui/uibase.js'][78]++; + baidu.editor.dom.domUtils.remove(box); + } + _$jscoverage['ui/uibase.js'][79]++; + uiUtils.unsetGlobal(this.id); +})}; + _$jscoverage['ui/uibase.js'][82]++; + utils.inherits(UIBase, EventBase); +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/uiutils.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/uiutils.js new file mode 100644 index 000000000..bd974add5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/coverage/ui/uiutils.js @@ -0,0 +1,567 @@ +/* automatically generated by JSCoverage - do not edit */ +try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } +} +catch (e) {} + +try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } +} +catch (e) {} +if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; +} +if (! _$jscoverage['ui/uiutils.js']) { + _$jscoverage['ui/uiutils.js'] = []; + _$jscoverage['ui/uiutils.js'][1] = 0; + _$jscoverage['ui/uiutils.js'][2] = 0; + _$jscoverage['ui/uiutils.js'][5] = 0; + _$jscoverage['ui/uiutils.js'][6] = 0; + _$jscoverage['ui/uiutils.js'][7] = 0; + _$jscoverage['ui/uiutils.js'][8] = 0; + _$jscoverage['ui/uiutils.js'][10] = 0; + _$jscoverage['ui/uiutils.js'][12] = 0; + _$jscoverage['ui/uiutils.js'][15] = 0; + _$jscoverage['ui/uiutils.js'][16] = 0; + _$jscoverage['ui/uiutils.js'][17] = 0; + _$jscoverage['ui/uiutils.js'][19] = 0; + _$jscoverage['ui/uiutils.js'][20] = 0; + _$jscoverage['ui/uiutils.js'][21] = 0; + _$jscoverage['ui/uiutils.js'][22] = 0; + _$jscoverage['ui/uiutils.js'][24] = 0; + _$jscoverage['ui/uiutils.js'][25] = 0; + _$jscoverage['ui/uiutils.js'][26] = 0; + _$jscoverage['ui/uiutils.js'][27] = 0; + _$jscoverage['ui/uiutils.js'][28] = 0; + _$jscoverage['ui/uiutils.js'][29] = 0; + _$jscoverage['ui/uiutils.js'][32] = 0; + _$jscoverage['ui/uiutils.js'][34] = 0; + _$jscoverage['ui/uiutils.js'][36] = 0; + _$jscoverage['ui/uiutils.js'][37] = 0; + _$jscoverage['ui/uiutils.js'][40] = 0; + _$jscoverage['ui/uiutils.js'][41] = 0; + _$jscoverage['ui/uiutils.js'][42] = 0; + _$jscoverage['ui/uiutils.js'][43] = 0; + _$jscoverage['ui/uiutils.js'][44] = 0; + _$jscoverage['ui/uiutils.js'][47] = 0; + _$jscoverage['ui/uiutils.js'][51] = 0; + _$jscoverage['ui/uiutils.js'][53] = 0; + _$jscoverage['ui/uiutils.js'][54] = 0; + _$jscoverage['ui/uiutils.js'][56] = 0; + _$jscoverage['ui/uiutils.js'][58] = 0; + _$jscoverage['ui/uiutils.js'][64] = 0; + _$jscoverage['ui/uiutils.js'][65] = 0; + _$jscoverage['ui/uiutils.js'][67] = 0; + _$jscoverage['ui/uiutils.js'][68] = 0; + _$jscoverage['ui/uiutils.js'][69] = 0; + _$jscoverage['ui/uiutils.js'][71] = 0; + _$jscoverage['ui/uiutils.js'][72] = 0; + _$jscoverage['ui/uiutils.js'][73] = 0; + _$jscoverage['ui/uiutils.js'][76] = 0; + _$jscoverage['ui/uiutils.js'][77] = 0; + _$jscoverage['ui/uiutils.js'][78] = 0; + _$jscoverage['ui/uiutils.js'][79] = 0; + _$jscoverage['ui/uiutils.js'][89] = 0; + _$jscoverage['ui/uiutils.js'][90] = 0; + _$jscoverage['ui/uiutils.js'][91] = 0; + _$jscoverage['ui/uiutils.js'][92] = 0; + _$jscoverage['ui/uiutils.js'][93] = 0; + _$jscoverage['ui/uiutils.js'][95] = 0; + _$jscoverage['ui/uiutils.js'][99] = 0; + _$jscoverage['ui/uiutils.js'][100] = 0; + _$jscoverage['ui/uiutils.js'][101] = 0; + _$jscoverage['ui/uiutils.js'][102] = 0; + _$jscoverage['ui/uiutils.js'][108] = 0; + _$jscoverage['ui/uiutils.js'][109] = 0; + _$jscoverage['ui/uiutils.js'][110] = 0; + _$jscoverage['ui/uiutils.js'][114] = 0; + _$jscoverage['ui/uiutils.js'][115] = 0; + _$jscoverage['ui/uiutils.js'][116] = 0; + _$jscoverage['ui/uiutils.js'][117] = 0; + _$jscoverage['ui/uiutils.js'][119] = 0; + _$jscoverage['ui/uiutils.js'][122] = 0; + _$jscoverage['ui/uiutils.js'][123] = 0; + _$jscoverage['ui/uiutils.js'][126] = 0; + _$jscoverage['ui/uiutils.js'][129] = 0; + _$jscoverage['ui/uiutils.js'][130] = 0; + _$jscoverage['ui/uiutils.js'][131] = 0; + _$jscoverage['ui/uiutils.js'][132] = 0; + _$jscoverage['ui/uiutils.js'][133] = 0; + _$jscoverage['ui/uiutils.js'][134] = 0; + _$jscoverage['ui/uiutils.js'][137] = 0; + _$jscoverage['ui/uiutils.js'][138] = 0; + _$jscoverage['ui/uiutils.js'][140] = 0; + _$jscoverage['ui/uiutils.js'][141] = 0; + _$jscoverage['ui/uiutils.js'][145] = 0; + _$jscoverage['ui/uiutils.js'][146] = 0; + _$jscoverage['ui/uiutils.js'][147] = 0; + _$jscoverage['ui/uiutils.js'][148] = 0; + _$jscoverage['ui/uiutils.js'][149] = 0; + _$jscoverage['ui/uiutils.js'][152] = 0; + _$jscoverage['ui/uiutils.js'][158] = 0; + _$jscoverage['ui/uiutils.js'][159] = 0; + _$jscoverage['ui/uiutils.js'][160] = 0; + _$jscoverage['ui/uiutils.js'][161] = 0; + _$jscoverage['ui/uiutils.js'][162] = 0; + _$jscoverage['ui/uiutils.js'][163] = 0; + _$jscoverage['ui/uiutils.js'][164] = 0; + _$jscoverage['ui/uiutils.js'][165] = 0; + _$jscoverage['ui/uiutils.js'][166] = 0; + _$jscoverage['ui/uiutils.js'][168] = 0; + _$jscoverage['ui/uiutils.js'][171] = 0; + _$jscoverage['ui/uiutils.js'][172] = 0; + _$jscoverage['ui/uiutils.js'][173] = 0; + _$jscoverage['ui/uiutils.js'][174] = 0; + _$jscoverage['ui/uiutils.js'][175] = 0; + _$jscoverage['ui/uiutils.js'][176] = 0; + _$jscoverage['ui/uiutils.js'][178] = 0; + _$jscoverage['ui/uiutils.js'][179] = 0; + _$jscoverage['ui/uiutils.js'][180] = 0; + _$jscoverage['ui/uiutils.js'][182] = 0; + _$jscoverage['ui/uiutils.js'][184] = 0; + _$jscoverage['ui/uiutils.js'][185] = 0; + _$jscoverage['ui/uiutils.js'][186] = 0; + _$jscoverage['ui/uiutils.js'][187] = 0; + _$jscoverage['ui/uiutils.js'][188] = 0; + _$jscoverage['ui/uiutils.js'][189] = 0; + _$jscoverage['ui/uiutils.js'][190] = 0; + _$jscoverage['ui/uiutils.js'][191] = 0; + _$jscoverage['ui/uiutils.js'][193] = 0; + _$jscoverage['ui/uiutils.js'][194] = 0; + _$jscoverage['ui/uiutils.js'][195] = 0; + _$jscoverage['ui/uiutils.js'][196] = 0; + _$jscoverage['ui/uiutils.js'][198] = 0; + _$jscoverage['ui/uiutils.js'][201] = 0; + _$jscoverage['ui/uiutils.js'][202] = 0; + _$jscoverage['ui/uiutils.js'][203] = 0; + _$jscoverage['ui/uiutils.js'][204] = 0; + _$jscoverage['ui/uiutils.js'][205] = 0; + _$jscoverage['ui/uiutils.js'][206] = 0; + _$jscoverage['ui/uiutils.js'][207] = 0; + _$jscoverage['ui/uiutils.js'][208] = 0; + _$jscoverage['ui/uiutils.js'][209] = 0; + _$jscoverage['ui/uiutils.js'][211] = 0; + _$jscoverage['ui/uiutils.js'][213] = 0; + _$jscoverage['ui/uiutils.js'][214] = 0; + _$jscoverage['ui/uiutils.js'][215] = 0; + _$jscoverage['ui/uiutils.js'][216] = 0; + _$jscoverage['ui/uiutils.js'][218] = 0; + _$jscoverage['ui/uiutils.js'][221] = 0; + _$jscoverage['ui/uiutils.js'][222] = 0; + _$jscoverage['ui/uiutils.js'][223] = 0; + _$jscoverage['ui/uiutils.js'][224] = 0; + _$jscoverage['ui/uiutils.js'][225] = 0; + _$jscoverage['ui/uiutils.js'][226] = 0; + _$jscoverage['ui/uiutils.js'][231] = 0; + _$jscoverage['ui/uiutils.js'][232] = 0; + _$jscoverage['ui/uiutils.js'][233] = 0; + _$jscoverage['ui/uiutils.js'][234] = 0; + _$jscoverage['ui/uiutils.js'][235] = 0; + _$jscoverage['ui/uiutils.js'][236] = 0; + _$jscoverage['ui/uiutils.js'][241] = 0; + _$jscoverage['ui/uiutils.js'][242] = 0; + _$jscoverage['ui/uiutils.js'][243] = 0; + _$jscoverage['ui/uiutils.js'][253] = 0; + _$jscoverage['ui/uiutils.js'][254] = 0; + _$jscoverage['ui/uiutils.js'][255] = 0; +} +_$jscoverage['ui/uiutils.js'].source = ["(function (){"," var browser = baidu.editor.browser,"," domUtils = baidu.editor.dom.domUtils;",""," var magic = '$EDITORUI';"," var root = window[magic] = {};"," var uidMagic = 'ID' + magic;"," var uidCount = 0;",""," var uiUtils = baidu.editor.ui.uiUtils = {"," uid: function (obj){"," return (obj ? obj[uidMagic] || (obj[uidMagic] = ++ uidCount) : ++ uidCount);"," },"," hook: function ( fn, callback ) {"," var dg;"," if (fn && fn._callbacks) {"," dg = fn;"," } else {"," dg = function (){"," var q;"," if (fn) {"," q = fn.apply(this, arguments);"," }"," var callbacks = dg._callbacks;"," var k = callbacks.length;"," while (k --) {"," var r = callbacks[k].apply(this, arguments);"," if (q === undefined) {"," q = r;"," }"," }"," return q;"," };"," dg._callbacks = [];"," }"," dg._callbacks.push(callback);"," return dg;"," },"," createElementByHtml: function (html){"," var el = document.createElement('div');"," el.innerHTML = html;"," el = el.firstChild;"," el.parentNode.removeChild(el);"," return el;"," },"," getViewportElement: function (){"," return (browser.ie && browser.quirks) ?"," document.body : document.documentElement;"," },"," getClientRect: function (element){"," var bcr;"," //trace IE6下在控制编辑器显隐时可能会报错,catch一下"," try{"," bcr = element.getBoundingClientRect();"," }catch(e){"," bcr={left:0,top:0,height:0,width:0}"," }"," var rect = {"," left: Math.round(bcr.left),"," top: Math.round(bcr.top),"," height: Math.round(bcr.bottom - bcr.top),"," width: Math.round(bcr.right - bcr.left)"," };"," var doc;"," while ((doc = element.ownerDocument) !== document &&"," (element = domUtils.getWindow(doc).frameElement)) {"," bcr = element.getBoundingClientRect();"," rect.left += bcr.left;"," rect.top += bcr.top;"," }"," rect.bottom = rect.top + rect.height;"," rect.right = rect.left + rect.width;"," return rect;"," },"," getViewportRect: function (){"," var viewportEl = uiUtils.getViewportElement();"," var width = (window.innerWidth || viewportEl.clientWidth) | 0;"," var height = (window.innerHeight ||viewportEl.clientHeight) | 0;"," return {"," left: 0,"," top: 0,"," height: height,"," width: width,"," bottom: height,"," right: width"," };"," },"," setViewportOffset: function (element, offset){"," var rect;"," var fixedLayer = uiUtils.getFixedLayer();"," if (element.parentNode === fixedLayer) {"," element.style.left = offset.left + 'px';"," element.style.top = offset.top + 'px';"," } else {"," domUtils.setViewportOffset(element, offset);"," }"," },"," getEventOffset: function (evt){"," var el = evt.target || evt.srcElement;"," var rect = uiUtils.getClientRect(el);"," var offset = uiUtils.getViewportOffsetByEvent(evt);"," return {"," left: offset.left - rect.left,"," top: offset.top - rect.top"," };"," },"," getViewportOffsetByEvent: function (evt){"," var el = evt.target || evt.srcElement;"," var frameEl = domUtils.getWindow(el).frameElement;"," var offset = {"," left: evt.clientX,"," top: evt.clientY"," };"," if (frameEl && el.ownerDocument !== document) {"," var rect = uiUtils.getClientRect(frameEl);"," offset.left += rect.left;"," offset.top += rect.top;"," }"," return offset;"," },"," setGlobal: function (id, obj){"," root[id] = obj;"," return magic + '[\"' + id + '\"]';"," },"," unsetGlobal: function (id){"," delete root[id];"," },"," copyAttributes: function (tgt, src){"," var attributes = src.attributes;"," var k = attributes.length;"," while (k --) {"," var attrNode = attributes[k];"," if ( attrNode.nodeName != 'style' && attrNode.nodeName != 'class' && (!browser.ie || attrNode.specified) ) {"," tgt.setAttribute(attrNode.nodeName, attrNode.nodeValue);"," }"," }"," if (src.className) {"," domUtils.addClass(tgt,src.className);"," }"," if (src.style.cssText) {"," tgt.style.cssText += ';' + src.style.cssText;"," }"," },"," removeStyle: function (el, styleName){"," if (el.style.removeProperty) {"," el.style.removeProperty(styleName);"," } else if (el.style.removeAttribute) {"," el.style.removeAttribute(styleName);"," } else throw '';"," },"," contains: function (elA, elB){"," return elA && elB && (elA === elB ? false : ("," elA.contains ? elA.contains(elB) :"," elA.compareDocumentPosition(elB) & 16"," ));"," },"," startDrag: function (evt, callbacks,doc){"," var doc = doc || document;"," var startX = evt.clientX;"," var startY = evt.clientY;"," function handleMouseMove(evt){"," var x = evt.clientX - startX;"," var y = evt.clientY - startY;"," callbacks.ondragmove(x, y,evt);"," if (evt.stopPropagation) {"," evt.stopPropagation();"," } else {"," evt.cancelBubble = true;"," }"," }"," if (doc.addEventListener) {"," function handleMouseUp(evt){"," doc.removeEventListener('mousemove', handleMouseMove, true);"," doc.removeEventListener('mouseup', handleMouseUp, true);"," window.removeEventListener('mouseup', handleMouseUp, true);"," callbacks.ondragstop();"," }"," doc.addEventListener('mousemove', handleMouseMove, true);"," doc.addEventListener('mouseup', handleMouseUp, true);"," window.addEventListener('mouseup', handleMouseUp, true);",""," evt.preventDefault();"," } else {"," var elm = evt.srcElement;"," elm.setCapture();"," function releaseCaptrue(){"," elm.releaseCapture();"," elm.detachEvent('onmousemove', handleMouseMove);"," elm.detachEvent('onmouseup', releaseCaptrue);"," elm.detachEvent('onlosecaptrue', releaseCaptrue);"," callbacks.ondragstop();"," }"," elm.attachEvent('onmousemove', handleMouseMove);"," elm.attachEvent('onmouseup', releaseCaptrue);"," elm.attachEvent('onlosecaptrue', releaseCaptrue);"," evt.returnValue = false;"," }"," callbacks.ondragstart();"," },"," getFixedLayer: function (){"," var layer = document.getElementById('edui_fixedlayer');"," if (layer == null) {"," layer = document.createElement('div');"," layer.id = 'edui_fixedlayer';"," document.body.appendChild(layer);"," if (browser.ie && browser.version <= 8) {"," layer.style.position = 'absolute';"," bindFixedLayer();"," setTimeout(updateFixedOffset);"," } else {"," layer.style.position = 'fixed';"," }"," layer.style.left = '0';"," layer.style.top = '0';"," layer.style.width = '0';"," layer.style.height = '0';"," }"," return layer;"," },"," makeUnselectable: function (element){"," if (browser.opera || (browser.ie && browser.version < 9)) {"," element.unselectable = 'on';"," if (element.hasChildNodes()) {"," for (var i=0; i<element.childNodes.length; i++) {"," if (element.childNodes[i].nodeType == 1) {"," uiUtils.makeUnselectable(element.childNodes[i]);"," }"," }"," }"," } else {"," if (element.style.MozUserSelect !== undefined) {"," element.style.MozUserSelect = 'none';"," } else if (element.style.WebkitUserSelect !== undefined) {"," element.style.WebkitUserSelect = 'none';"," } else if (element.style.KhtmlUserSelect !== undefined) {"," element.style.KhtmlUserSelect = 'none';"," }"," }"," }"," };"," function updateFixedOffset(){"," var layer = document.getElementById('edui_fixedlayer');"," uiUtils.setViewportOffset(layer, {"," left: 0,"," top: 0"," });","// layer.style.display = 'none';","// layer.style.display = 'block';",""," //#trace: 1354","// setTimeout(updateFixedOffset);"," }"," function bindFixedLayer(adjOffset){"," domUtils.on(window, 'scroll', updateFixedOffset);"," domUtils.on(window, 'resize', baidu.editor.utils.defer(updateFixedOffset, 0, true));"," }","})();"]; +_$jscoverage['ui/uiutils.js'][1]++; +(function () { + _$jscoverage['ui/uiutils.js'][2]++; + var browser = baidu.editor.browser, domUtils = baidu.editor.dom.domUtils; + _$jscoverage['ui/uiutils.js'][5]++; + var magic = "$EDITORUI"; + _$jscoverage['ui/uiutils.js'][6]++; + var root = (window[magic] = {}); + _$jscoverage['ui/uiutils.js'][7]++; + var uidMagic = ("ID" + magic); + _$jscoverage['ui/uiutils.js'][8]++; + var uidCount = 0; + _$jscoverage['ui/uiutils.js'][10]++; + var uiUtils = (baidu.editor.ui.uiUtils = {uid: (function (obj) { + _$jscoverage['ui/uiutils.js'][12]++; + return (obj? (obj[uidMagic] || (obj[uidMagic] = (++uidCount))): (++uidCount)); +}), hook: (function (fn, callback) { + _$jscoverage['ui/uiutils.js'][15]++; + var dg; + _$jscoverage['ui/uiutils.js'][16]++; + if ((fn && fn._callbacks)) { + _$jscoverage['ui/uiutils.js'][17]++; + dg = fn; + } + else { + _$jscoverage['ui/uiutils.js'][19]++; + dg = (function () { + _$jscoverage['ui/uiutils.js'][20]++; + var q; + _$jscoverage['ui/uiutils.js'][21]++; + if (fn) { + _$jscoverage['ui/uiutils.js'][22]++; + q = fn.apply(this, arguments); + } + _$jscoverage['ui/uiutils.js'][24]++; + var callbacks = dg._callbacks; + _$jscoverage['ui/uiutils.js'][25]++; + var k = callbacks.length; + _$jscoverage['ui/uiutils.js'][26]++; + while ((k--)) { + _$jscoverage['ui/uiutils.js'][27]++; + var r = callbacks[k].apply(this, arguments); + _$jscoverage['ui/uiutils.js'][28]++; + if ((q === undefined)) { + _$jscoverage['ui/uiutils.js'][29]++; + q = r; + } +} + _$jscoverage['ui/uiutils.js'][32]++; + return q; +}); + _$jscoverage['ui/uiutils.js'][34]++; + dg._callbacks = []; + } + _$jscoverage['ui/uiutils.js'][36]++; + dg._callbacks.push(callback); + _$jscoverage['ui/uiutils.js'][37]++; + return dg; +}), createElementByHtml: (function (html) { + _$jscoverage['ui/uiutils.js'][40]++; + var el = document.createElement("div"); + _$jscoverage['ui/uiutils.js'][41]++; + el.innerHTML = html; + _$jscoverage['ui/uiutils.js'][42]++; + el = el.firstChild; + _$jscoverage['ui/uiutils.js'][43]++; + el.parentNode.removeChild(el); + _$jscoverage['ui/uiutils.js'][44]++; + return el; +}), getViewportElement: (function () { + _$jscoverage['ui/uiutils.js'][47]++; + return ((browser.ie && browser.quirks)? document.body: document.documentElement); +}), getClientRect: (function (element) { + _$jscoverage['ui/uiutils.js'][51]++; + var bcr; + _$jscoverage['ui/uiutils.js'][53]++; + try { + _$jscoverage['ui/uiutils.js'][54]++; + bcr = element.getBoundingClientRect(); + } + catch (e) { + _$jscoverage['ui/uiutils.js'][56]++; + bcr = {left: 0, top: 0, height: 0, width: 0}; + } + _$jscoverage['ui/uiutils.js'][58]++; + var rect = {left: Math.round(bcr.left), top: Math.round(bcr.top), height: Math.round((bcr.bottom - bcr.top)), width: Math.round((bcr.right - bcr.left))}; + _$jscoverage['ui/uiutils.js'][64]++; + var doc; + _$jscoverage['ui/uiutils.js'][65]++; + while ((((doc = element.ownerDocument) !== document) && (element = domUtils.getWindow(doc).frameElement))) { + _$jscoverage['ui/uiutils.js'][67]++; + bcr = element.getBoundingClientRect(); + _$jscoverage['ui/uiutils.js'][68]++; + rect.left += bcr.left; + _$jscoverage['ui/uiutils.js'][69]++; + rect.top += bcr.top; +} + _$jscoverage['ui/uiutils.js'][71]++; + rect.bottom = (rect.top + rect.height); + _$jscoverage['ui/uiutils.js'][72]++; + rect.right = (rect.left + rect.width); + _$jscoverage['ui/uiutils.js'][73]++; + return rect; +}), getViewportRect: (function () { + _$jscoverage['ui/uiutils.js'][76]++; + var viewportEl = uiUtils.getViewportElement(); + _$jscoverage['ui/uiutils.js'][77]++; + var width = ((window.innerWidth || viewportEl.clientWidth) | 0); + _$jscoverage['ui/uiutils.js'][78]++; + var height = ((window.innerHeight || viewportEl.clientHeight) | 0); + _$jscoverage['ui/uiutils.js'][79]++; + return ({left: 0, top: 0, height: height, width: width, bottom: height, right: width}); +}), setViewportOffset: (function (element, offset) { + _$jscoverage['ui/uiutils.js'][89]++; + var rect; + _$jscoverage['ui/uiutils.js'][90]++; + var fixedLayer = uiUtils.getFixedLayer(); + _$jscoverage['ui/uiutils.js'][91]++; + if ((element.parentNode === fixedLayer)) { + _$jscoverage['ui/uiutils.js'][92]++; + element.style.left = (offset.left + "px"); + _$jscoverage['ui/uiutils.js'][93]++; + element.style.top = (offset.top + "px"); + } + else { + _$jscoverage['ui/uiutils.js'][95]++; + domUtils.setViewportOffset(element, offset); + } +}), getEventOffset: (function (evt) { + _$jscoverage['ui/uiutils.js'][99]++; + var el = (evt.target || evt.srcElement); + _$jscoverage['ui/uiutils.js'][100]++; + var rect = uiUtils.getClientRect(el); + _$jscoverage['ui/uiutils.js'][101]++; + var offset = uiUtils.getViewportOffsetByEvent(evt); + _$jscoverage['ui/uiutils.js'][102]++; + return ({left: (offset.left - rect.left), top: (offset.top - rect.top)}); +}), getViewportOffsetByEvent: (function (evt) { + _$jscoverage['ui/uiutils.js'][108]++; + var el = (evt.target || evt.srcElement); + _$jscoverage['ui/uiutils.js'][109]++; + var frameEl = domUtils.getWindow(el).frameElement; + _$jscoverage['ui/uiutils.js'][110]++; + var offset = {left: evt.clientX, top: evt.clientY}; + _$jscoverage['ui/uiutils.js'][114]++; + if ((frameEl && (el.ownerDocument !== document))) { + _$jscoverage['ui/uiutils.js'][115]++; + var rect = uiUtils.getClientRect(frameEl); + _$jscoverage['ui/uiutils.js'][116]++; + offset.left += rect.left; + _$jscoverage['ui/uiutils.js'][117]++; + offset.top += rect.top; + } + _$jscoverage['ui/uiutils.js'][119]++; + return offset; +}), setGlobal: (function (id, obj) { + _$jscoverage['ui/uiutils.js'][122]++; + root[id] = obj; + _$jscoverage['ui/uiutils.js'][123]++; + return (magic + "[\"" + id + "\"]"); +}), unsetGlobal: (function (id) { + _$jscoverage['ui/uiutils.js'][126]++; + (delete root[id]); +}), copyAttributes: (function (tgt, src) { + _$jscoverage['ui/uiutils.js'][129]++; + var attributes = src.attributes; + _$jscoverage['ui/uiutils.js'][130]++; + var k = attributes.length; + _$jscoverage['ui/uiutils.js'][131]++; + while ((k--)) { + _$jscoverage['ui/uiutils.js'][132]++; + var attrNode = attributes[k]; + _$jscoverage['ui/uiutils.js'][133]++; + if (((attrNode.nodeName != "style") && (attrNode.nodeName != "class") && ((! browser.ie) || attrNode.specified))) { + _$jscoverage['ui/uiutils.js'][134]++; + tgt.setAttribute(attrNode.nodeName, attrNode.nodeValue); + } +} + _$jscoverage['ui/uiutils.js'][137]++; + if (src.className) { + _$jscoverage['ui/uiutils.js'][138]++; + domUtils.addClass(tgt, src.className); + } + _$jscoverage['ui/uiutils.js'][140]++; + if (src.style.cssText) { + _$jscoverage['ui/uiutils.js'][141]++; + tgt.style.cssText += (";" + src.style.cssText); + } +}), removeStyle: (function (el, styleName) { + _$jscoverage['ui/uiutils.js'][145]++; + if (el.style.removeProperty) { + _$jscoverage['ui/uiutils.js'][146]++; + el.style.removeProperty(styleName); + } + else { + _$jscoverage['ui/uiutils.js'][147]++; + if (el.style.removeAttribute) { + _$jscoverage['ui/uiutils.js'][148]++; + el.style.removeAttribute(styleName); + } + else { + _$jscoverage['ui/uiutils.js'][149]++; + throw ""; + } + } +}), contains: (function (elA, elB) { + _$jscoverage['ui/uiutils.js'][152]++; + return (elA && elB && ((elA === elB)? false: (elA.contains? elA.contains(elB): (elA.compareDocumentPosition(elB) & 16)))); +}), startDrag: (function (evt, callbacks, doc) { + _$jscoverage['ui/uiutils.js'][158]++; + var doc = (doc || document); + _$jscoverage['ui/uiutils.js'][159]++; + var startX = evt.clientX; + _$jscoverage['ui/uiutils.js'][160]++; + var startY = evt.clientY; + _$jscoverage['ui/uiutils.js'][161]++; + function handleMouseMove(evt) { + _$jscoverage['ui/uiutils.js'][162]++; + var x = (evt.clientX - startX); + _$jscoverage['ui/uiutils.js'][163]++; + var y = (evt.clientY - startY); + _$jscoverage['ui/uiutils.js'][164]++; + callbacks.ondragmove(x, y, evt); + _$jscoverage['ui/uiutils.js'][165]++; + if (evt.stopPropagation) { + _$jscoverage['ui/uiutils.js'][166]++; + evt.stopPropagation(); + } + else { + _$jscoverage['ui/uiutils.js'][168]++; + evt.cancelBubble = true; + } +} + _$jscoverage['ui/uiutils.js'][171]++; + if (doc.addEventListener) { + _$jscoverage['ui/uiutils.js'][172]++; + function handleMouseUp(evt) { + _$jscoverage['ui/uiutils.js'][173]++; + doc.removeEventListener("mousemove", handleMouseMove, true); + _$jscoverage['ui/uiutils.js'][174]++; + doc.removeEventListener("mouseup", handleMouseUp, true); + _$jscoverage['ui/uiutils.js'][175]++; + window.removeEventListener("mouseup", handleMouseUp, true); + _$jscoverage['ui/uiutils.js'][176]++; + callbacks.ondragstop(); +} + _$jscoverage['ui/uiutils.js'][178]++; + doc.addEventListener("mousemove", handleMouseMove, true); + _$jscoverage['ui/uiutils.js'][179]++; + doc.addEventListener("mouseup", handleMouseUp, true); + _$jscoverage['ui/uiutils.js'][180]++; + window.addEventListener("mouseup", handleMouseUp, true); + _$jscoverage['ui/uiutils.js'][182]++; + evt.preventDefault(); + } + else { + _$jscoverage['ui/uiutils.js'][184]++; + var elm = evt.srcElement; + _$jscoverage['ui/uiutils.js'][185]++; + elm.setCapture(); + _$jscoverage['ui/uiutils.js'][186]++; + function releaseCaptrue() { + _$jscoverage['ui/uiutils.js'][187]++; + elm.releaseCapture(); + _$jscoverage['ui/uiutils.js'][188]++; + elm.detachEvent("onmousemove", handleMouseMove); + _$jscoverage['ui/uiutils.js'][189]++; + elm.detachEvent("onmouseup", releaseCaptrue); + _$jscoverage['ui/uiutils.js'][190]++; + elm.detachEvent("onlosecaptrue", releaseCaptrue); + _$jscoverage['ui/uiutils.js'][191]++; + callbacks.ondragstop(); +} + _$jscoverage['ui/uiutils.js'][193]++; + elm.attachEvent("onmousemove", handleMouseMove); + _$jscoverage['ui/uiutils.js'][194]++; + elm.attachEvent("onmouseup", releaseCaptrue); + _$jscoverage['ui/uiutils.js'][195]++; + elm.attachEvent("onlosecaptrue", releaseCaptrue); + _$jscoverage['ui/uiutils.js'][196]++; + evt.returnValue = false; + } + _$jscoverage['ui/uiutils.js'][198]++; + callbacks.ondragstart(); +}), getFixedLayer: (function () { + _$jscoverage['ui/uiutils.js'][201]++; + var layer = document.getElementById("edui_fixedlayer"); + _$jscoverage['ui/uiutils.js'][202]++; + if ((layer == null)) { + _$jscoverage['ui/uiutils.js'][203]++; + layer = document.createElement("div"); + _$jscoverage['ui/uiutils.js'][204]++; + layer.id = "edui_fixedlayer"; + _$jscoverage['ui/uiutils.js'][205]++; + document.body.appendChild(layer); + _$jscoverage['ui/uiutils.js'][206]++; + if ((browser.ie && (browser.version <= 8))) { + _$jscoverage['ui/uiutils.js'][207]++; + layer.style.position = "absolute"; + _$jscoverage['ui/uiutils.js'][208]++; + bindFixedLayer(); + _$jscoverage['ui/uiutils.js'][209]++; + setTimeout(updateFixedOffset); + } + else { + _$jscoverage['ui/uiutils.js'][211]++; + layer.style.position = "fixed"; + } + _$jscoverage['ui/uiutils.js'][213]++; + layer.style.left = "0"; + _$jscoverage['ui/uiutils.js'][214]++; + layer.style.top = "0"; + _$jscoverage['ui/uiutils.js'][215]++; + layer.style.width = "0"; + _$jscoverage['ui/uiutils.js'][216]++; + layer.style.height = "0"; + } + _$jscoverage['ui/uiutils.js'][218]++; + return layer; +}), makeUnselectable: (function (element) { + _$jscoverage['ui/uiutils.js'][221]++; + if ((browser.opera || (browser.ie && (browser.version < 9)))) { + _$jscoverage['ui/uiutils.js'][222]++; + element.unselectable = "on"; + _$jscoverage['ui/uiutils.js'][223]++; + if (element.hasChildNodes()) { + _$jscoverage['ui/uiutils.js'][224]++; + for (var i = 0; (i < element.childNodes.length); (i++)) { + _$jscoverage['ui/uiutils.js'][225]++; + if ((element.childNodes[i].nodeType == 1)) { + _$jscoverage['ui/uiutils.js'][226]++; + uiUtils.makeUnselectable(element.childNodes[i]); + } +} + } + } + else { + _$jscoverage['ui/uiutils.js'][231]++; + if ((element.style.MozUserSelect !== undefined)) { + _$jscoverage['ui/uiutils.js'][232]++; + element.style.MozUserSelect = "none"; + } + else { + _$jscoverage['ui/uiutils.js'][233]++; + if ((element.style.WebkitUserSelect !== undefined)) { + _$jscoverage['ui/uiutils.js'][234]++; + element.style.WebkitUserSelect = "none"; + } + else { + _$jscoverage['ui/uiutils.js'][235]++; + if ((element.style.KhtmlUserSelect !== undefined)) { + _$jscoverage['ui/uiutils.js'][236]++; + element.style.KhtmlUserSelect = "none"; + } + } + } + } +})}); + _$jscoverage['ui/uiutils.js'][241]++; + function updateFixedOffset() { + _$jscoverage['ui/uiutils.js'][242]++; + var layer = document.getElementById("edui_fixedlayer"); + _$jscoverage['ui/uiutils.js'][243]++; + uiUtils.setViewportOffset(layer, {left: 0, top: 0}); +} + _$jscoverage['ui/uiutils.js'][253]++; + function bindFixedLayer(adjOffset) { + _$jscoverage['ui/uiutils.js'][254]++; + domUtils.on(window, "scroll", updateFixedOffset); + _$jscoverage['ui/uiutils.js'][255]++; + domUtils.on(window, "resize", baidu.editor.utils.defer(updateFixedOffset, 0, true)); +} +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/editor_config.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/editor_config.js new file mode 100644 index 000000000..6d2b02936 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/editor_config.js @@ -0,0 +1,276 @@ +/** + * ueditor完整配置项 + * 可以在这里配置整个编辑器的特性 + */ +var UEDITOR_CONFIG2 = { + UEDITOR_HOME_URL: '../../../', //这里你可以配置成ueditor目录在您网站的绝对路径 + toolbars: [ + ['FullScreen','Source','|','Undo','Redo','|', + 'Bold','Italic','Underline','StrikeThrough','Superscript','Subscript','RemoveFormat','FormatMatch','|', + 'BlockQuote','|', + 'PastePlain','|', + 'ForeColor','BackColor','InsertOrderedList','InsertUnorderedList','|', + 'Paragraph','RowSpacing','FontFamily','FontSize','|', + 'DirectionalityLtr','DirectionalityRtl','|','','Indent','Outdent','|', + 'JustifyLeft','JustifyCenter','JustifyRight','JustifyJustify','|', + 'Link','Unlink','Anchor','Image','MultiMenu','Video','Map','GMap','Code', '|', + 'Horizontal','Date','Time','Spechars','|', + 'InsertTable','DeleteTable','InsertParagraphBeforeTable','InsertRow','DeleteRow','InsertCol','DeleteCol','MergeCells','MergeRight','MergeDown','SplittoCells','SplittoRows','SplittoCols','|', + 'SelectAll','ClearDoc','SearchReplace','Print','Preview','PageBreak','Help'] + ],autoFloatEnabled:false, + labelMap: { + 'anchor':'锚点', + 'undo': '撤销', + 'redo': '重做', + 'bold': '加粗', + 'indent':'首行缩进', + 'outdent':'取消缩进', + 'italic': '斜体', + 'underline': '下划线', + 'strikethrough': '删除线', + 'subscript': '下标', + 'superscript': '上标', + 'formatmatch': '格式刷', + 'source': '源代码', + 'blockquote': '引用', + 'pasteplain': '纯文本粘贴模式', + 'selectall': '全选', + 'print': '打印', + 'preview': '预览', + 'horizontal': '分隔线', + 'removeformat': '清除格式', + 'time': '时间', + 'date': '日期', + 'unlink': '取消链接', + 'insertrow': '前插入行', + 'insertcol': '前插入列', + 'mergeright': '右合并单元格', + 'mergedown': '下合并单元格', + 'deleterow': '删除行', + 'deletecol': '删除列', + 'splittorows': '拆分成行', + 'splittocols': '拆分成列', + 'splittocells': '完全拆分单元格', + 'mergecells': '合并多个单元格', + 'deletetable': '删除表格', +// 'tablesuper': '表格高级设置', + 'insertparagraphbeforetable': '表格前插行', + 'cleardoc': '清空文档', + 'fontfamily': '字体', + 'fontsize': '字号', + 'paragraph': '格式', + 'image': '图片', + 'inserttable': '表格', + 'link': '超链接', + 'emoticon': '表情', + 'spechars': '特殊字符', + 'searchreplace': '查询替换', + 'map': 'Baidu地图', + 'gmap': 'Google地图', + 'video': '视频', + 'help': '帮助', + 'justifyleft':'居左对齐', + 'justifyright':'居右对齐', + 'justifycenter':'居中对齐', + 'justifyjustify':'两端对齐', + 'forecolor' : '字体颜色', + 'backcolor' : '背景色', + 'insertorderedlist' : '有序列表', + 'insertunorderedlist' : '无序列表', + 'fullscreen' : '全屏', + 'directionalityltr' : '从左向右输入', + 'directionalityrtl' : '从右向左输入', + 'rowspacing' : '行间距', + 'code' : '插入代码', + 'pagebreak':'分页' + }, + iframeUrlMap: { + 'anchor': '~/dialogs/anchor/anchor.html', + 'image': '~/dialogs/image/image.html', + 'inserttable': '~/dialogs/table/table.html', + 'link': '~/dialogs/link/link.html', + 'emoticon': '~/dialogs/emoticon/emoticon.html', + 'spechars': '~/dialogs/spechars/spechars.html', + 'searchreplace': '~/dialogs/searchreplace/searchreplace.html', + 'map': '~/dialogs/map/map.html', + 'gmap': '~/dialogs/gmap/gmap.html', + 'video': '~/dialogs/video/video.html', + 'help': '~/dialogs/help/help.html', + 'code' : '~/dialogs/code/code.html', + 'multimenu': '~/dialogs/menu-emoticon/emoticon.html' + }, + listMap: { + 'fontfamily': ['宋体', '楷体', '隶书', '黑体','andale mono','arial','arial black','comic sans ms','impact','times new roman'], + 'fontsize': [10, 11, 12, 14, 16, 18, 20, 24, 36], + 'underline':['none','overline','line-through','underline'], + 'paragraph': ['p:Paragraph', 'h1:Heading 1', 'h2:Heading 2', 'h3:Heading 3', 'h4:Heading 4', 'h5:Heading 5', 'h6:Heading 6'], + 'rowspacing' : ['1.0:0','1.5:15','2.0:20','2.5:25','3.0:30'] + }, + fontMap: { + '宋体': ['宋体', 'SimSun'], + '楷体': ['楷体', '楷体_GB2312', 'SimKai'], + '黑体': ['黑体', 'SimHei'], + '隶书': ['隶书', 'SimLi'], + 'andale mono' : ['andale mono'], + 'arial' : ['arial','helvetica','sans-serif'], + 'arial black' : ['arial black','avant garde'], + 'comic sans ms' : ['comic sans ms'], + 'impact' : ['impact','chicago'], + 'times new roman' : ['times new roman'] + }, + contextMenu: [ + { + label : '删除', + cmdName : 'delete' + + }, + { + label : '全选', + cmdName : 'selectall' + + },{ + label : '清空文档', + cmdName : 'cleardoc', + exec : function(){ + if(confirm('确定清空文档吗?')){ + this.execCommand('cleardoc'); + } + } + },'-',{ + label : '取消链接', + cmdName : 'unlink' + },'-',{ + group : '段落格式', + icon : 'justifyjustify', + subMenu : [ + { + label: '居左对齐', + cmdName : 'justify', + value : 'left' + }, + { + label: '居右对齐', + cmdName : 'justify', + value : 'right' + },{ + label: '居中对齐', + cmdName : 'justify', + value : 'center' + },{ + label: '两端对齐', + cmdName : 'justify', + value : 'justify' + } + ] + },'-',{ + group : '表格', + icon : 'table', + subMenu : [ + { + label: '删除表格', + cmdName : 'deletetable' + }, + { + label: '表格前插行', + cmdName : 'insertparagraphbeforetable' + }, + '-', + { + label: '删除行', + cmdName : 'deleterow' + }, + { + label: '删除列', + cmdName : 'deletecol' + }, + '-', + { + label: '前插入行', + cmdName : 'insertrow' + }, + { + label: '前插入列', + cmdName : 'insertcol' + }, + '-', + { + label: '右合并单元格', + cmdName : 'mergeright' + }, + { + label: '下合并单元格', + cmdName : 'mergedown' + }, + '-', + { + label: '拆分成行', + cmdName : 'splittorows' + }, + { + label: '拆分成列', + cmdName : 'splittocols' + }, + { + label: '合并多个单元格', + cmdName : 'mergecells' + }, + { + label: '完全拆分单元格', + cmdName : 'splittocells' + } + ] + } + ], + theme:'default', + initialStyle: '', //编辑器内部样式 + initialContent: '欢迎光临编辑器', //初始化编辑器的内容 + autoClearinitialContent :true, //是否自动清除编辑器初始内容 + iframeCssUrl :'../../../themes/iframe.css', //要引入css的url + removeFormatTags : 'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var', //配置格式刷删除的标签 + removeFormatAttributes : 'class,style,lang,width,height,align,hspace,valign', //配置格式刷删除的属性 + enterTag : 'br', //编辑器回车标签。p或br + maxUndoCount : 20, //最多可以回退的次数 + maxInputCount : 20, //当输入的字符数超过该值时,保存一次现场 + selectedTdClass : 'selectTdClass', //设定选中td的样式名称 + pasteplain : 0, //是否纯文本粘贴。false为不使用纯文本粘贴,true为使用纯文本粘贴 + textarea : 'editorValue', //提交表单时,服务器端接收编辑器内容的名字 + focus : false, //初始化时,是否让编辑器获得焦点true或false + indentValue : '2em', //初始化时,首行缩进距离 + pageBreakTag : '_baidu_page_break_tag_', //分页符 + initialFrameHeight: 400, //最小高度 + autoHeightEnabled: true, //是否自动长高 + elementPathEnabled : false, //是否启用elementPath + serialize : function(){ //配置过滤标签 + function X( t, s, b ) { + var o = {}; + for(var i=0,ai;ai=arguments[i++];){ + for(var k in ai){ + o[k] = ai[k] + } + } + + return o; + } + var inline = {strong:1,em:1,b:1,i:1,u:1,span:1,a:1,img:1}; + var block = X(inline, {p:1,div:1,blockquote:1,$:{style:1,dir:1}}); + return { + blackList: {style:1,script:1,form:1,input:1,textarea:1,iframe:1,"#comment":1} +// , +// whiteList: { +// br: {$:{}}, +// span: X(inline, {$:{style:1,id:1}}), +// strong: inline, +// em:inline, +// b: inline, +// a: X(inline,{$:{href:1,'target':1,title:1}}), +// u: inline, +// div: block, +// p: block, +// ul: {li:1,$:{style:1}}, +// ol: {li:1,$:{style:1}}, +// li: block, +// img: {$:{style:1,width:1,height:1,src:1,alt:1,title:1}} +// } + }; + }() +}; \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/editor_config_src.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/editor_config_src.js new file mode 100644 index 000000000..855d259aa --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/editor_config_src.js @@ -0,0 +1,285 @@ +/** + * ueditor完整配置项 + * 可以在这里配置整个编辑器的特性 + */ +var UEDITOR_CONFIG = { + UEDITOR_HOME_URL: '../', //这里你可以配置成ueditor目录在您网站的绝对路径 + toolbars: [ + ['FullScreen','Source','|','Undo','Redo','|', + 'Bold','Italic','Underline','StrikeThrough','Superscript','Subscript','RemoveFormat','FormatMatch','|', + 'BlockQuote','|', + 'PastePlain','|', + 'ForeColor','BackColor','InsertOrderedList','InsertUnorderedList','|', + 'Paragraph','RowSpacing','FontFamily','FontSize','|', + 'DirectionalityLtr','DirectionalityRtl','|','','Indent','Outdent','|', + 'JustifyLeft','JustifyCenter','JustifyRight','JustifyJustify','|', + 'Link','Unlink','Anchor','Image','MultiMenu','Video','Map','GMap','Code', '|', + 'Horizontal','Date','Time','Spechars','|', + 'InsertTable','DeleteTable','InsertParagraphBeforeTable','InsertRow','DeleteRow','InsertCol','DeleteCol','MergeCells','MergeRight','MergeDown','SplittoCells','SplittoRows','SplittoCols','|', + 'SelectAll','ClearDoc','SearchReplace','Print','Preview','PageBreak','Help','AutoSave','InsertFrame'] + ], + labelMap: { + 'anchor':'锚点', + 'undo': '撤销', + 'redo': '重做', + 'bold': '加粗', + 'indent':'首行缩进', + 'outdent':'取消缩进', + 'italic': '斜体', + 'underline': '下划线', + 'strikethrough': '删除线', + 'subscript': '下标', + 'superscript': '上标', + 'formatmatch': '格式刷', + 'source': '源代码', + 'blockquote': '引用', + 'pasteplain': '纯文本粘贴模式', + 'selectall': '全选', + 'print': '打印', + 'preview': '预览', + 'horizontal': '分隔线', + 'removeformat': '清除格式', + 'time': '时间', + 'date': '日期', + 'unlink': '取消链接', + 'insertrow': '前插入行', + 'insertcol': '前插入列', + 'mergeright': '右合并单元格', + 'mergedown': '下合并单元格', + 'deleterow': '删除行', + 'deletecol': '删除列', + 'splittorows': '拆分成行', + 'splittocols': '拆分成列', + 'splittocells': '完全拆分单元格', + 'mergecells': '合并多个单元格', + 'deletetable': '删除表格', +// 'tablesuper': '表格高级设置', + 'insertparagraphbeforetable': '表格前插行', + 'cleardoc': '清空文档', + 'fontfamily': '字体', + 'fontsize': '字号', + 'paragraph': '格式', + 'image': '图片', + 'inserttable': '表格', + 'link': '超链接', + 'emoticon': '表情', + 'spechars': '特殊字符', + 'searchreplace': '查询替换', + 'map': 'Baidu地图', + 'gmap': 'Google地图', + 'video': '视频', + 'help': '帮助', + 'justifyleft':'居左对齐', + 'justifyright':'居右对齐', + 'justifycenter':'居中对齐', + 'justifyjustify':'两端对齐', + 'forecolor' : '字体颜色', + 'backcolor' : '背景色', + 'insertorderedlist' : '有序列表', + 'insertunorderedlist' : '无序列表', + 'fullscreen' : '全屏', + 'directionalityltr' : '从左向右输入', + 'directionalityrtl' : '从右向左输入', + 'rowspacing' : '行间距', + 'code' : '插入代码', + 'pagebreak':'分页', + 'insertframe':'插入Iframe' + }, + iframeUrlMap: { + 'anchor': '../../../dialogs/anchor/anchor.html', + 'image': '../../../dialogs/image/image.html', + 'inserttable': '../../../dialogs/table/table.html', + 'link': '../../../dialogs/link/link.html', + 'emoticon': '../../../dialogs/emoticon/emoticon.html', + 'spechars': '../../../dialogs/spechars/spechars.html', + 'searchreplace': '../../../dialogs/searchreplace/searchreplace.html', + 'map': '../../../dialogs/map/map.html', + 'gmap': '../../../dialogs/gmap/gmap.html', + 'video': '../../../dialogs/video/video.html', + 'help': '../../../dialogs/help/help.html', + 'code' : '../../../dialogs/code/code.html', + 'multimenu': '../../../dialogs/menu-emoticon/emoticon.html', + 'insertframe': '../../../dialogs/insertframe/insertframe.html' + }, + listMap: { + 'fontfamily': ['宋体', '楷体', '隶书', '黑体','andale mono','arial','arial black','comic sans ms','impact','times new roman'], + 'fontsize': [10, 11, 12, 14, 16, 18, 20, 24, 36], + 'underline':['none','overline','line-through','underline'], + 'paragraph': ['p:Paragraph', 'h1:Heading 1', 'h2:Heading 2', 'h3:Heading 3', 'h4:Heading 4', 'h5:Heading 5', 'h6:Heading 6'], + 'rowspacing' : ['1.0:0','1.5:15','2.0:20','2.5:25','3.0:30'] + }, + fontMap: { + '宋体': ['宋体', 'SimSun'], + '楷体': ['楷体', '楷体_GB2312', 'SimKai'], + '黑体': ['黑体', 'SimHei'], + '隶书': ['隶书', 'SimLi'], + 'andale mono' : ['andale mono'], + 'arial' : ['arial','helvetica','sans-serif'], + 'arial black' : ['arial black','avant garde'], + 'comic sans ms' : ['comic sans ms'], + 'impact' : ['impact','chicago'], + 'times new roman' : ['times new roman'] + }, + contextMenu: [ + { + label : '删除', + cmdName : 'delete' + + }, + { + label : '全选', + cmdName : 'selectall' + + },{ + label : '删除代码', + cmdName : 'highlightcode' + + },{ + label : '清空文档', + cmdName : 'cleardoc', + exec : function(){ + if(confirm('确定清空文档吗?')){ + this.execCommand('cleardoc'); + } + } + },'-',{ + label : '取消链接', + cmdName : 'unlink' + },'-',{ + group : '段落格式', + icon : 'justifyjustify', + subMenu : [ + { + label: '居左对齐', + cmdName : 'justify', + value : 'left' + }, + { + label: '居右对齐', + cmdName : 'justify', + value : 'right' + },{ + label: '居中对齐', + cmdName : 'justify', + value : 'center' + },{ + label: '两端对齐', + cmdName : 'justify', + value : 'justify' + } + ] + },'-',{ + group : '表格', + icon : 'table', + subMenu : [ + { + label: '删除表格', + cmdName : 'deletetable' + }, + { + label: '表格前插行', + cmdName : 'insertparagraphbeforetable' + }, + '-', + { + label: '删除行', + cmdName : 'deleterow' + }, + { + label: '删除列', + cmdName : 'deletecol' + }, + '-', + { + label: '前插入行', + cmdName : 'insertrow' + }, + { + label: '前插入列', + cmdName : 'insertcol' + }, + '-', + { + label: '右合并单元格', + cmdName : 'mergeright' + }, + { + label: '下合并单元格', + cmdName : 'mergedown' + }, + '-', + { + label: '拆分成行', + cmdName : 'splittorows' + }, + { + label: '拆分成列', + cmdName : 'splittocols' + }, + { + label: '合并多个单元格', + cmdName : 'mergecells' + }, + { + label: '完全拆分单元格', + cmdName : 'splittocells' + } + ] + } + ], + initialStyle: '', //编辑器内部样式 + initialContent: 'hello', //初始化编辑器的内容 + autoClearinitialContent :true, //是否自动清除编辑器初始内容 + iframeCssUrl :'../../../themes/iframe.css', //要引入css的url + removeFormatTags : 'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var', //配置格式刷删除的标签 + removeFormatAttributes : 'class,style,lang,width,height,align,hspace,valign', //配置格式刷删除的属性 + enterTag : 'p', //编辑器回车标签。p或br + maxUndoCount : 20, //最多可以回退的次数 + maxInputCount : 20, //当输入的字符数超过该值时,保存一次现场 + selectedTdClass : 'selectTdClass', //设定选中td的样式名称 + pasteplain : 0, //是否纯文本粘贴。false为不使用纯文本粘贴,true为使用纯文本粘贴 + textarea : 'editorValue', //提交表单时,服务器端接收编辑器内容的名字 + focus : false, //初始化时,是否让编辑器获得焦点true或false + indentValue : '2em', //初始化时,首行缩进距离 + pageBreakTag : '_baidu_page_break_tag_', //分页符 + autoSave:true, //是否开启自动保存 + autoSavePath:this.UEDITOR_HOME_URL+'auto-save.php', //自动保存的地址 + autoSaveFrequency:5, //自动保存频率 + minFrameHeight: 320, //最小高度 + autoHeightEnabled: true, //是否自动长高 + autoFloatEnabled: true, //是否保持toolbar的位置不动 + elementPathEnabled : true, //是否启用elementPath + serialize : function(){ //配置过滤标签 + function X( t, s, b ) { + var o = {}; + for(var i=0,ai;ai=arguments[i++];){ + for(var k in ai){ + o[k] = ai[k] + } + } + + return o; + } + var inline = {strong:1,em:1,b:1,i:1,u:1,span:1,a:1,img:1}; + var block = X(inline, {p:1,div:1,blockquote:1,$:{style:1,dir:1}}); + return { + blackList: {style:1,script:1,form:1,input:1,textarea:1,"#comment":1} +// , +// whiteList: { +// br: {$:{}}, +// span: X(inline, {$:{style:1,id:1}}), +// strong: inline, +// em:inline, +// b: inline, +// a: X(inline,{$:{href:1,'target':1,title:1}}), +// u: inline, +// div: block, +// p: block, +// ul: {li:1,$:{style:1}}, +// ol: {li:1,$:{style:1}}, +// li: block, +// img: {$:{style:1,width:1,height:1,src:1,alt:1,title:1}} +// } + }; + }() +}; \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/import.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/import.js new file mode 100644 index 000000000..84a404095 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/import.js @@ -0,0 +1,119 @@ + +///import editor; +///import core/browser; +///import core/utils; +///import core/EventBase; +///import core/dtd; +///import core/domUtils; +///import core/Range; +///import core/Selection; +///import core/Editor; +///import core/Editor.defaultoptions; +///import core/loadconfig; +///import core/ajax; +///import core/filterword; +///import core/node; +///import core/htmlparser; +///import core/filternode; +///import core/plugin; +///import core/keymap; +///import core/localstorage; +///import plugins/defaultfilter; +///import plugins/inserthtml; +///import plugins/autotypeset; +///import plugins/background; +///import plugins/image; +///import plugins/justify; +///import plugins/font; +///import plugins/link; +///import plugins/iframe; +///import plugins/scrawl; +///import plugins/removeformat; +///import plugins/blockquote; +///import plugins/convertcase; +///import plugins/indent; +///import plugins/preview; +///import plugins/selectall; +///import plugins/paragraph; +///import plugins/directionality; +///import plugins/horizontal; +///import plugins/time; +///import plugins/rowspacing; +///import plugins/lineheight; +///import plugins/insertcode; +///import plugins/cleardoc; +///import plugins/anchor; +///import plugins/wordcount; +///import plugins/pagebreak; +///import plugins/wordimage; +///import plugins/dragdrop; +///import plugins/undo; +///import plugins/copy; +///import plugins/paste; +///import plugins/puretxtpaste; +///import plugins/list; +///import plugins/source; +///import plugins/enterkey; +///import plugins/keystrokes; +///import plugins/fiximgclick; +///import plugins/autolink; +///import plugins/autoheight; +///import plugins/autofloat; +///import plugins/video; +///import plugins/table.core; +///import plugins/table.cmds; +///import plugins/table.action; +///import plugins/table.sort; +///import plugins/contextmenu; +///import plugins/shortcutmenu; +///import plugins/basestyle; +///import plugins/elementpath; +///import plugins/formatmatch; +///import plugins/searchreplace; +///import plugins/customstyle; +///import plugins/catchremoteimage; +///import plugins/snapscreen; +///import plugins/insertparagraph; +///import plugins/webapp; +///import plugins/template; +///import plugins/music; +///import plugins/autoupload; +///import plugins/autosave; +///import plugins/charts; +///import plugins/section; +///import plugins/serverparam; + + +///import ui/ui; +///import ui/uiutils; +///import ui/uibase; +///import ui/toolbar; +///import ui/editor; +///import ui/editorui; +///import ui/stateful; +///import ui/button; +///import ui/splitbutton; +///import ui/popup; +///import ui/colorpicker; +///import ui/colorbutton; +///import ui/cellalignpicker; +///import ui/pastepicker; +///import ui/menu; +///import ui/menubutton; +///import ui/multiMenu; +///import ui/combox; +///import ui/colorpicker; +///import ui/mask; +///import ui/dialog; +///import ui/separator; +///import ui/tablepicker; +///import ui/tablebutton; +///import ui/autotypesetpicker; +///import ui/autotypesetbutton; +///import ui/shortcutmenu; +///import ui/message; + +///import adapter/editor; +///import adapter/editorui; +///import adapter/message; +///import adapter/autosave; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/index.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/index.php new file mode 100644 index 000000000..8dc8f7d47 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/index.php @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/anchor.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/anchor.js new file mode 100644 index 000000000..87666d488 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/anchor.js @@ -0,0 +1,91 @@ +module( 'plugins.anchor' ); + +test( '插入锚点后切换源码', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + stop(); + var br = baidu.editor.browser.ie ? ' ' : '
    '; //1.2版本,ie中‘’-〉' ' + setTimeout( function() { + editor.setContent( '

    ' + br + '

    ' ); + range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); + editor.execCommand( 'anchor', 'hello' ); + ua.checkHTMLSameStyle( '' + br, editor.document, body.firstChild, '检查锚点html' ); //1.2版本后,在img前有的不可见字符没有删去,这里改成之比较img内的内容 + ok(body.getElementsByTagName('img')[0].attributes['anchorname'].nodeValue=="hello"&&body.getElementsByTagName('img')[0].attributes['class'].nodeValue=="anchorclass",'检查锚点'); + editor.execCommand( 'source' ); /*切到源码模式下会有一个超时*/ + setTimeout( function() { + var tas = editor.iframe.parentNode.getElementsByTagName( 'textarea' ); + if(ua.browser.webkit){ + ok( editor.iframe.nextSibling.textContent.indexOf( '

    ')||(tas[0].value=='

    '),'检查源码');*/ + editor.execCommand( 'source' ); + ua.checkHTMLSameStyle( '' + br, editor.document, body.firstChild, '检查锚点html' ); + setTimeout( function() { + start(); + }, 500 ); + }, 200); + }, 20 ); +} ); + +test( '在源码模式设置超链接的name属性,切换到编辑器模式检查超链接是否变为锚点', function() { + var editor = te.obj[0]; + var body = editor.body; + stop(); + setTimeout(function(){ + editor.setContent( '' ); + setTimeout( function() { + editor.execCommand( 'source' ); + setTimeout( function() { + var ta = editor.iframe.parentNode.getElementsByTagName( 'textarea' )[0]; + ta.value = '

    '; /*这种情况认为是锚点*/ + setTimeout( function() { + editor.execCommand( 'source' ); + ua.checkHTMLSameStyle( '', editor.document, body.firstChild, '检查锚点html' ); + start(); + }, 100 ); + }, 100 ); + }, 100 ); + },100); +} ); + +test( '在源码模式设置超链接没有name属性,切换到编辑器模式检查超链接不变为锚点', function() { + var editor = te.obj[0]; + editor.setContent( '' ); + var body = editor.body; + stop(); + setTimeout( function() { + editor.execCommand( 'source' ); + setTimeout( function() { + var ta = editor.iframe.parentNode.getElementsByTagName( 'textarea' )[0]; + ta.value = '

    你好

    '; + setTimeout( function() { + editor.execCommand( 'source' ); + ua.manualDeleteFillData(editor.body); +// equal( body.firstChild.firstChild.tagName.toLowerCase(), 'a', 'a标签不会转化' ); + equal( body.firstChild.lastChild.tagName.toLowerCase(), 'a', 'a标签不会转化' ); //兼容opera + start(); + }, 50 ); + }, 10 ); + }, 20 ); +} ); + +test( '已存在锚点', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + var br = baidu.editor.browser.ie ? ' ' : '
    '; + editor.setContent( '

    ' ); + range.selectNode(body.firstChild).select(); + editor.execCommand( 'anchor', 'hello' ); + var name=body.firstChild.firstChild.getAttribute('anchorname'); + equal(name, 'hello', '更改name'); + editor.setContent( '

    ' ); + range.selectNode(body.firstChild).select(); + editor.execCommand( 'anchor'); + equal(ua.getChildHTML(editor.body),'

    ','去掉锚点'); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/auto.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/auto.js new file mode 100644 index 000000000..eeba5ac8c --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/auto.js @@ -0,0 +1,21 @@ +/** + * Created by JetBrains PhpStorm. + * User: lisisi01 + * Date: 12-11-8 + * Time: 下午3:37 + * To change this template use File | Settings | File Templates. + */ +module( 'plugins.autosubmit' ); + +//这个插件是针对非ie的,单测用例同样只针对非ie,仍需手动测试检验ie与非ie下效果是否一致 +test( '输入超链接后回车', function() { + var form = document.body.appendChild( document.createElement( 'form' ) ); + var editor = new baidu.editor.Editor({'initialContent':'

    欢迎使用ueditor

    ','autoFloatEnabled':false}); + editor.render(form); +// form.body.appendChild(editor); + editor.focus(); + var range = new baidu.editor.dom.Range( editor.document ); + range.setStart(editor.body.firstChild.firstChild,1).collapse(true).select(); + editor.execCommand('autosubmit'); + equal(editor.textarea.value,'

    欢迎使用ueditor

    ',''); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autofloat.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autofloat.js new file mode 100644 index 000000000..3cb4d89bb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autofloat.js @@ -0,0 +1,47 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-9-18 + * Time: 下午4:33 + * To change this template use File | Settings | File Templates. + */ +module( 'plugins.autofloat' ); +test( '检查toolbar是否浮动在页面顶端', function() { + te.dom[0].parentNode.removeChild(te.dom[0]); + var sc = document.createElement("script"); + sc.id="sc"; + sc.type = "text/plain"; + sc.style.height = "100px"; + document.body.appendChild(sc); + var me = UE.getEditor('sc',{'autoFloatEnabled':true,'topOffset':60,'autoHeightEnabled':true,'scaleEnabled':false}); + stop(); + me.ready(function(){ + setTimeout(function () { + me.setContent('














































    sdf

    '); + var screenX = window.screenX ? window.screenX : window.screenLeft;//不同浏览器兼容 + var screenY = window.screenY ? window.screenY : window.screenTop; + setTimeout(function () { + var range = new baidu.editor.dom.Range(me.document); + range.setStart(me.body.firstChild, 1).collapse(1).select(); + me.focus(); + setTimeout(function () { + window.scrollBy(screenX, screenY + $(document.body).height()); + setTimeout(function () { + var scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;//不同浏览器兼容 +//// //ie6下,工具栏浮动不到正确位置 + if (ua.browser.ie != 6&&!ua.browser.gecko) + equal(scrollTop, $(me.ui.getDom('toolbarbox')).offset().top - 60, '检查toolbar是否在页面顶端'); + window.scrollTo(screenX, screenY - $(document.body).height()); + setTimeout(function () { + equal(me.ui.getDom().childNodes[0].id, me.ui.getDom('toolbarbox').id, 'toolbar是第一个元素'); + document.getElementById('sc').parentNode.removeChild(document.getElementById('sc')); + start(); + }, 500); + }, 500); + }, 1000); + }, 200); + }, 800); + }); + +}); + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autoheight.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autoheight.js new file mode 100644 index 000000000..11de0b8cc --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autoheight.js @@ -0,0 +1,28 @@ +module('plugins.autoheight'); + +test('自动长高',function(){ + var sc = document.createElement("script"); + sc.id="sc"; + sc.type = "text/plain"; + document.body.appendChild(sc); + var editor = new UE.ui.Editor({'autoFloatEnabled':true,'topOffset':60,'autoHeightEnabled':true,'scaleEnabled':false}); + editor.render('sc'); + te.dom[0].parentNode.removeChild(te.dom[0]); + stop(); + setTimeout(function(){ + var height=editor.body.style.height; + editor.setContent('
    nmnmknmm,






















    '); + setTimeout(function(){ + ok(height!=editor.body.style.height,'自动长高'); + editor.disableAutoHeight(); + editor.body.style.height=height; + editor.setContent('
























    '); + stop(); + setTimeout(function(){ + ok(height==editor.body.style.height,'不长高'); + + start(); + },200); + },200); + },800); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autolink.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autolink.js new file mode 100644 index 000000000..b13f5a735 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autolink.js @@ -0,0 +1,364 @@ +module('plugins.autolink'); + + +//test('', function () { +// stop() +//}); +//自动添加的功能是针对非ie的,单测用例同样只针对非ie,仍需手动测试检验ie与非ie下效果是否一致 +test('输入超链接后回车', function () { + if (!ua.browser.ie) { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    http://www.baidu.com

    '); + stop(); + setTimeout(function () { + range.setStart(body.firstChild.firstChild, body.firstChild.firstChild.length).collapse(1).select(); + setTimeout(function () { + ua.keydown(editor.body, {'keyCode': 13}); + ua.keyup(editor.body, {'keyCode': 13}); + var a = body.firstChild.getElementsByTagName('a')[0]; + if(a){ + equal(ua.getChildHTML(a), 'http://www.baidu.com', '检查a的内容'); + ok(a && $(a).attr('href').indexOf('http://www.baidu.com') != -1, '检查a的href'); + ok(a && $(a).attr('_src').indexOf('http://www.baidu.com') != -1, '检查a的_src'); + }else{ + var text = editor.getContent(); + equal(text, '

    http://www.baidu.com

    ', '检查p的内容'); + } + start(); + }, 20); + }, 20); + } +}); + +test('输入超链接后按空格', function () { + if (!ua.browser.ie) { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + setTimeout(function () { + editor.setContent('

    http://www.baidu.com

    '); + range.setStart(body.firstChild, 1).collapse(1).select(); + ua.keydown(editor.body, {'keyCode': 32}); + setTimeout(function () { + var a = body.firstChild.getElementsByTagName('a')[0]; + if(a){ + equal(ua.getChildHTML(a), 'http://www.baidu.com', '检查a的内容'); + ok(a && $(a).attr('href').indexOf('http://www.baidu.com') != -1, '检查a的href'); + ok(a && $(a).attr('_src').indexOf('http://www.baidu.com') != -1, '检查a的_src'); + }else{ + var text = editor.getContent(); + equal(text, '

    http://www.baidu.com

    ', '检查p的内容'); + } + start(); + }, 20); + }, 20); + stop(); + } +}); + +test('字符前面有内容', function () { + if (!ua.browser.ie) { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    http://www.baidu.com

    '); + range.setStart(body.firstChild, 2).collapse(1).select(); + stop(); + setTimeout(function () { + ua.keydown(editor.body, {'keyCode': 32}); + setTimeout(function () { + var a = body.firstChild.getElementsByTagName('a')[0]; + if(a){ + ok(a && $(a).attr('href').indexOf('http://www.baidu.com') != -1, '检查a的href'); + var html = 'http://www.baidu.com'; + equal(ua.getChildHTML(a), 'http://www.baidu.com', '检查a的内容'); + }else{ + var x= body.firstChild.firstChild.nextSibling.innerHTML; + equal(x, 'http://www.baidu.com', '检查a的内容'); + } + start(); + }, 20); + }, 20); + } +}); + +test('在p后面回车', function () { + if (!UE.browser.ie) { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    www.baidu.com

    '); + setTimeout(function () { + range.setStart(body.firstChild, 1).collapse(1).select(); + ua.keydown(editor.body, {'keyCode': 13}); + setTimeout(function () { + var a = body.firstChild.getElementsByTagName('a')[0]; + if(a){ + ok(a && $(a).attr('href').indexOf('http://www.baidu.com') != -1, '检查a的href'); + equal(ua.getChildHTML(a), 'www.baidu.com', '检查a的内容'); + }else{ + var p =body.firstChild.innerHTML; + equal(p,'www.baidu.com', '检查a的内容'); + } + start(); + }, 20); + }, 20); + stop(); + } +}); +///*trace 1709 在“你好http://www.baidu.com”后回车/空格,各浏览器表现不一致*/ +////这种情况,在ie中可以生成自动连接,非ie不可,现在以生成连接为期望结果 +test('trace 1709 在与其他文本相连的链接后空格', function () { + if (!UE.browser.ie) { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    你好http://www.baidu.com

    '); + setTimeout(function () { + range.setStart(body.firstChild, 1).collapse(1).select(); + ua.keydown(editor.body, {'keyCode': 32}); + setTimeout(function () { + var a = body.firstChild.getElementsByTagName('a')[0]; + if(a){ + equal(ua.getChildHTML(a), 'http://www.baidu.com', '检查a的内容'); + ok(a && $(a).attr('href').indexOf('http://www.baidu.com') != -1, '检查a的href'); + }else{ + var p =body.firstChild.innerHTML; + equal(p,'你好http://www.baidu.com', '检查a的内容'); + } + start(); + }, 20); + }, 20); + stop(); + } +}); +////修改:对P中的文字内容,原:

    你好htp://ww.baidu.com

    +test('你好htp://ww.baidu.com 后面回车', function () { + if (!UE.browser.ie) { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    你好http://www.baidu.com

    '); + setTimeout(function () { + range.setStart(body.firstChild, 1).collapse(1).select(); + ua.keydown(editor.body, {'keyCode': 32}); + setTimeout(function () { + equal(body.firstChild.firstChild.nodeValue, '你好', '你好http://www.baidu.com 转换成文字+超链接'); + var a = body.firstChild.getElementsByTagName('a')[0]; + if(a){ + equal(ua.getChildHTML(a), 'http://www.baidu.com', '检查a的内容'); + ok(a && $(a).attr('href').indexOf('http://www.baidu.com') != -1, '检查a的href'); + }else{ + var p =body.firstChild.innerHTML; + equal(p,'你好http://www.baidu.com', '检查a的内容'); + } + start(); + }, 20); + }, 20); + stop(); + } +}); +//

    欢迎使用ueditor!

    +test('trace 2121', function () { + if (!UE.browser.ie) { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    欢迎使用ueditor!www.baidu.com

    '); + stop(); + setTimeout(function () { + range.setStart(body.firstChild.lastChild, body.firstChild.lastChild.length).collapse(1).select(); + setTimeout(function () { + ua.keydown(editor.body, {'keyCode': 13}); + var a = body.firstChild.getElementsByTagName('a')[0]; + if(a){ + equal(ua.getChildHTML(a), 'www.baidu.com', '检查a的内容'); + ok(a && $(a).attr('href').indexOf('http://www.baidu.com') != -1, '检查a的href'); + ok(a && $(a).attr('_src').indexOf('http://www.baidu.com') != -1, '检查a的_src'); + }else{ + var p = body.firstChild.innerHTML; + equal(p,'欢迎使用ueditor!www.baidu.com','内容未改变'); + } + start(); + }, 20); + }, 20); + } +}); +test('autofloat:false 禁用IE中的自动加超链接功能', function () { + if(ua.browser.ie==8)return; + //在IE中回车/空格自动加连接,这里模拟加连接以后,测试keyup时把添加的链接去掉 + if (ua.browser.ie>8) {//这个用例中,ie8不好模拟startContainer.nodeName = p,用下面的用例测是一样的 + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor('ue', {autolink: false}); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + var body = editor.body; + editor.body.innerHTML = '

    www.baidu.com

     

    '; + setTimeout(function () { + range.selectNode(body.lastChild.firstChild).select(); + setTimeout(function () { + ua.keyup(editor.body, {'keyCode': 13}); + setTimeout(function () { + equal(body.firstChild.getElementsByTagName('a').length, 0, 'a 标签被去掉了'); + equal(body.childNodes.length, 2, '结果正确'); + equal(body.firstChild.tagName.toLowerCase(), 'p', '结果正确'); + equal(body.firstChild.innerHTML, 'www.baidu.com', '结果正确'); + UE.delEditor('ue'); + te.dom.push(document.getElementById('ue')); + start(); + }, 60); + }, 20); + }, 20); + }); + stop(); + } +}); +test('autofloat:false 禁用IE中的自动加超链接功能--回车', function () { + if(ua.browser.ie==8)return; + //在IE中回车/空格自动加连接,这里模拟加连接以后,测试keyup时把添加的链接去掉 + if (ua.browser.ie) { + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor('ue', {autolink: false}); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + var body = editor.body; + editor.body.innerHTML = '

    www.baidu.com

    '; + setTimeout(function () { + range.selectNode(body.lastChild.firstChild).select(); + setTimeout(function () { + ua.keyup(editor.body, {'keyCode': 13}); + setTimeout(function () { + equal(body.firstChild.getElementsByTagName('a').length, 0, 'a 标签被去掉了'); + equal(body.childNodes.length, 2, '结果正确'); + equal(body.firstChild.tagName.toLowerCase(), 'p', '结果正确'); + equal(body.firstChild.innerHTML, 'www.baidu.com', '结果正确'); + UE.delEditor('ue'); + te.dom.push(document.getElementById('ue')); + start(); + }, 60); + }, 20); + }, 20); + }); + stop(); + } +}); + +test('autofloat:false 禁用IE中的自动加超链接功能--空格', function () { + if(ua.browser.ie==8)return; + //在IE中回车/空格自动加连接,这里模拟加连接以后,测试keyup时把添加的链接去掉 + if (ua.browser.ie) { + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor('ue', {autolink: false}); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + var body = editor.body; + var space = ua.browser.ie>8?' ':' '; + editor.body.innerHTML = '

    www.baidu.com'+space+'

    '; + setTimeout(function () { +// if(ua.browser.ie>8){ +// range.setStart(body.firstChild.childNodes[1], 1).collapse(true).select(); +// } +// else{ + range.selectNode(body.firstChild.childNodes[1]).select(); +// } + setTimeout(function () { + ua.keyup(editor.body, {'keyCode': 32}); + equal(body.firstChild.getElementsByTagName('a').length, 0, 'a 标签被去掉了'); + equal(body.childNodes.length, 1, '结果正确'); + equal(body.firstChild.tagName.toLowerCase(), 'p', '结果正确'); + equal(body.firstChild.innerHTML.toLowerCase(), 'www.baidu.com'+space+'', '结果正确'); + setTimeout(function () { + UE.delEditor('ue'); + te.dom.push(document.getElementById('ue')); + start(); + }, 100); + }, 20); + }, 20); + }); + stop(); + } +}); +//对于手动添加的,不会误删 +test('autofloat:false 禁用IE中的自动加超链接功能--对于手动添加的,不会误删', function () { + //在IE中回车/空格自动加连接,这里模拟加连接以后,测试keyup时把添加的链接去掉 + if (ua.browser.ie) { + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor('ue', {autolink: false}); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + var body = editor.body; + var space = ua.browser.ie>8?' ':' '; + editor.setContent('

    www.baidu.com'+space+'

    '); + setTimeout(function () { + if(ua.browser.ie>8){ + range.setStart(body.firstChild.childNodes[1], 1).collapse(true).select(); + } + else{ + range.selectNode(body.firstChild.childNodes[1]).select(); + } + setTimeout(function () { + ua.keyup(editor.body, {'keyCode': 32}); + var a = body.firstChild.getElementsByTagName('a'); + ok(a&&a.length==1, 'a 标签没去掉'); + ok(a[0] && $(a[0]).attr('href').indexOf('http://www.baidu.com') != -1, '检查a的href'); + setTimeout(function () { + editor.execCommand('cleardoc'); + editor.setContent('

    www.baidu.com

    '); + setTimeout(function () { + range.selectNode(body.lastChild.firstChild).select(); + setTimeout(function () { + ua.keyup(editor.body, {'keyCode': 13}); + setTimeout(function () { + a = body.firstChild.getElementsByTagName('a'); + ok(a&&a.length==1, 'a 标签没去掉'); + ok(a[0] && $(a[0]).attr('href').indexOf('http://www.baidu.com') != -1, '检查a的href'); + UE.delEditor('ue'); + te.dom.push(document.getElementById('ue')); + start(); + }, 500); + }, 20); + }, 20); + }, 20); + }, 20); + }, 20); + }); + stop(); + } +}); +//test( '粘贴进来的http文本后回车', function() { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// setTimeout( function() { +// editor.setContent( '


    ' ); +// editor.focus(); +// range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); +// te.setClipData( "http://www.google.com" ); +// setTimeout( function() { +// editor.focus(); +// setTimeout( function() { +// editor.focus(); +// te.presskey( "ctrl", "v" ); +// editor.focus(); +// setTimeout( function() { +// te.presskey( "enter", "" ); +// editor.focus(); +// setTimeout( function() { +// var a = body.firstChild.getElementsByTagName( 'a' )[0]; +// equal( ua.getChildHTML( a ), 'http://www.google.com', '检查a的内容' ); +// start(); +// }, 100 ); +// +// }, 100 ); +// }, 100 ); +// }, 100 ); +// } ); +// stop(); +//} ); +// diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autosave.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autosave.js new file mode 100644 index 000000000..79b478aa6 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autosave.js @@ -0,0 +1,104 @@ +module('plugins.autosave'); + +test('自动保存', function () { + + expect(8); + + var container = te.obj[0].container, + editor = null, + count = 0; + + UE.delEditor(te.obj[0]); + container.parentNode.removeChild(container); + + container = document.createElement("div"); + container.id = "container"; + document.body.appendChild(container); + editor = UE.getEditor("container", { + initialContent: "", + //无限制 + saveInterval: 0 + }); + + + editor.addListener("beforeautosave", function (type, data) { + + data.content = data.content.toLowerCase(); + equal(true, true, "成功触发beforeautosave事件"); + equal(data.content === "

    http://www.baidu.com

    " || data.content === "

    disable

    ", true, "事件携带数据正确"); + }); + + editor.addListener("beforeautosave", function (type, data) { + + data.content = data.content.toLowerCase(); + if (data.content === "

    disable

    ") { + return false; + } + + count++; + + }); + + editor.addListener("afterautosave", function (type, data) { + + data.content = data.content.toLowerCase(); + equal(data.content, "

    http://www.baidu.com

    ", "成功触发afterautosave事件"); + + equal(editor.execCommand("getlocaldata") !== null, true, "getlocaldata命令正常"); + editor.execCommand("clearlocaldata"); + equal(editor.execCommand("getlocaldata") === "", true, "clearlocaldata命令正常"); + + }); + + stop(); + window.setTimeout(function () { + + editor.setContent('

    disable

    '); + + + window.setTimeout(function () { + + editor.setContent('

    http://www.baidu.com

    '); + + window.setTimeout(function () { + + equal(count, 1, "触发事件次数"); + + start(); + }, 500); + + UE.delEditor("container"); + container.parentNode.removeChild(container); + + }, 50); + + }, 500); + +}); +test('重建编辑器,加载草稿箱', function () { + UE.delEditor(te.obj[0]); + te.obj[0].container.parentNode.removeChild(te.obj[0].container); + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor('ue', {saveInterval: 0}); + setTimeout(function () { + var content = '

    内容

    '; + editor.setContent(content); + setTimeout(function () { + UE.delEditor('ue'); + document.getElementById('ue') && document.getElementById('ue').parentNode.removeChild(document.getElementById('ue')); + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor2 = UE.getEditor('ue'); + setTimeout(function () { + equal(editor2.queryCommandState('drafts'), 0, '草稿箱可用'); + editor2.execCommand('drafts'); + ua.checkSameHtml(editor2.body.innerHTML, content, '内容加载正确'); + UE.delEditor('ue'); + document.getElementById('ue') && document.getElementById('ue').parentNode.removeChild(document.getElementById('ue')); + start(); + }, 500); + }, 200); + }, 500); + stop(); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autotypeset.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autotypeset.js new file mode 100644 index 000000000..4d55c5085 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autotypeset.js @@ -0,0 +1,228 @@ +module('plugins.autotypeset'); + +test('全角半角转换',function(){ + window.localStorage.clear(); + var editor = te.obj[0]; + editor.setContent('

    Mayday123,.Mayday123,.

    '); + var text = editor.getContent(); + equal(text,'

    Mayday123,.Mayday123,.

    ','半角全角内容输入正确'); + editor.execCommand('autotypeset'); + var text2 = editor.body.firstChild.innerHTML; + equal(text2,'Mayday123,.Mayday123,.','半角全角内容输入正确2'); + editor.options.autotypeset.tobdc=true; + editor.execCommand('autotypeset'); + equal(editor.body.firstChild.innerHTML,'Mayday123,.Mayday123,.','内容转为全角:正确'); + editor.options.autotypeset.tobdc=false; + editor.setContent('

    Mayday123,.Mayday123,.

    '); + editor.options.autotypeset.bdc2sb=true; + editor.execCommand('autotypeset'); + equal(editor.body.firstChild.innerHTML,'Mayday123,.Mayday123,.','内容转为半角:正确'); + editor.options.autotypeset.bdc2sb=false; +}); +//todo +test('文本居中',function(){ + var editor = te.obj[0]; + editor.setContent('

    p文本

    '); + setTimeout(function(){ + editor.options.autotypeset.textAlign = 'center'; + editor.execCommand('autotypeset'); + equal($(editor.body.firstChild).css('text-align'),'center','文本居中'); + start(); + }, 100 ); + stop(); +}); + +test('trace:2183 h1标题居中',function(){ + var editor = te.obj[0]; + editor.setContent('

    h1标题

    '); + setTimeout(function(){ + editor.options.autotypeset.textAlign = 'center'; + editor.execCommand('autotypeset'); + equal($(editor.body.firstChild).css('text-align'),'center','h1标题居中'); + start(); + }, 50 ); + stop(); +}); + +test('合并空行',function(){ + var editor = te.obj[0]; + editor.setContent('

    欢迎使用



    ueditor!

    '); + setTimeout(function(){ + editor.options.autotypeset.mergeEmptyline = true; + delete editor.options.autotypeset.textAlign; + editor.execCommand('autotypeset'); + ua.manualDeleteFillData(editor.body); + var html =editor.body.innerHTML.toLowerCase().replace(/\r\n/ig,''); + equal(html,'

    欢迎使用


    ueditor!

    ','合并空行'); + start(); + }, 50 ); + stop(); +}); + +test('带有图片表情',function(){ + var editor = te.obj[0]; + editor.setContent('

    欢迎使用ueditor!

    '); + editor.execCommand('autotypeset'); + equal($(editor.body.lastChild).css('text-align'),'center','图片居中'); + editor.options.autotypeset.imageBlockLine = 'left'; + editor.execCommand('autotypeset'); + equal($(editor.body.lastChild).css('text-align'),'left','图片居左'); +}); + +test('删除空行',function(){ + var editor = te.obj[0]; + editor.setContent('

    欢迎使用



    ueditor!

    '); + setTimeout(function(){ + editor.options.autotypeset.mergeEmptyline = false;//removeEmptyline + editor.options.autotypeset.removeEmptyline = true; + delete editor.options.autotypeset.textAlign; + editor.execCommand('autotypeset'); + ua.manualDeleteFillData(editor.body); + equal(editor.body.innerHTML.toLowerCase().replace(/\r\n/ig,''),'

    欢迎使用

    ueditor!

    ','删除空行'); + start(); + }, 50 ); + stop(); +}); + +test('首行缩进',function(){ + var editor = te.obj[0]; + editor.setContent('

    欢迎使用ueditor!

    '); + setTimeout(function(){ + editor.options.autotypeset.indent = true; + editor.options.autotypeset.textAlign= "left"; + editor.execCommand('autotypeset'); + ua.manualDeleteFillData(editor.body); + var html = '

    欢迎使用ueditor!

    '; + ua.checkHTMLSameStyle(html ,editor.document,editor.body,'首行缩进'); + start(); + }, 50 ); + stop(); +}); + +/*trace 2650*/ +test( 'trace 3277:图像对齐', function () { + var editor = te.obj[0]; + editor.setContent( '

    ' ); + setTimeout(function(){ + editor.options.autotypeset.imageBlockLine = 'center'; + delete editor.options.autotypeset.textAlign;//imageBlockLine + var html= '

    '; + editor.execCommand('autotypeset'); + ua.checkHTMLSameStyle(html ,editor.document,editor.body,'图像对齐'); + start(); + }, 50 ); + stop(); +} ); + +//ie下 +test('trace 2651:字体样式',function(){ + var editor = te.obj[0]; + editor.setContent('

    欢迎使用ueditor!

    '); + setTimeout(function(){ + editor.options.autotypeset.clearFontSize = editor.options.autotypeset.clearFontFamily = true; + delete editor.options.autotypeset.textAlign; + editor.execCommand('autotypeset'); + equal(ua.getChildHTML(editor.body),'

    欢迎使用ueditor!

    ','恢复字体默认样式'); + start(); + }, 50 ); + stop(); +}); + +test('去掉class,去掉多余节点',function(){ + var editor = te.obj[0]; + editor.setContent('

    欢迎使用ueditor!

    '); + editor.options.autotypeset.removeClass = true; + delete editor.options.autotypeset.textAlign; + editor.execCommand('autotypeset'); + equal(ua.getChildHTML(editor.body),'

    欢迎使用ueditor!

    ','去掉class'); +}); + +test('粘贴过滤',function(){ + var div = document.body.appendChild(document.createElement('div')); + var editor = te.obj[0]; + editor.setContent(''); + editor.options.autotypeset.pasteFilter = true; + editor.options.autotypeset.removeEmptyline = true; + delete editor.options.autotypeset.textAlign; + editor.execCommand('autotypeset'); + var html ={html:'hello1'}; + editor.fireEvent('beforepaste',html); + editor.execCommand( 'insertHtml',html.html,true); + editor.fireEvent("afterpaste"); + var txt='

    hello1'; + ua.checkHTMLSameStyle(txt, editor.document, editor.body, '文字左对齐,表情居中'); + + editor.setContent(''); + editor.options.autotypeset.imageBlockLine = 'none'; + editor.options.autotypeset.textAlign = 'center'; + editor.options.autotypeset.removeEmptyline = true; + editor.options.autotypeset.pasteFilter = true; + editor.execCommand('autotypeset'); + html ={html:'

    hello1

    hello2

    '}; + editor.fireEvent('beforepaste',html); + editor.execCommand( 'insertHtml',html.html,true); + editor.fireEvent("afterpaste"); + txt='

    hello1hello2

    '; + ua.checkHTMLSameStyle(txt, editor.document, editor.body, '文字居中,表情居左'); +}); + +test('trace:4018,4012',function(){ + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue2'; + var editor2 = UE.getEditor('ue2'); + editor2.ready(function(){ + editor2.setContent('Mayday123,.Mayday123,.'); + var c = $('#edui18_state div'); + ua.click(c[4]); + ua.click($("input")[19]); + var d = $(".edui-autotypesetpicker-body tr"); + var e = d[7].getElementsByTagName('input'); + ua.click(e[0]); + var button = $(".edui-autotypesetpicker-body button"); + ua.click(button[0]); + if(ua.browser.ie&&ua.browser.ie==8){ + equal(editor2.getContent(),"

    Mayday123,.Mayday123,.

    ","未执行半角转全角"); + }else{ + equal(editor2.getContent(),'

    Mayday123,.Mayday123,.

    ',"未执行半角转全角"); + } + setTimeout(function () { + UE.delEditor('ue2'); + window.localStorage.clear(); + start(); + }, 100); + }); + stop(); +}); + +test('trace:3991',function(){ + var editor3 = te.obj[0]; + setTimeout(function(){ + editor3.setContent(''); + editor3.execCommand('inserttable', {numCols: 3, numRows: 3}); + var text =editor3.body.getElementsByTagName('td')[0]; + var range = new baidu.editor.dom.Range(editor3.document); + range.setStart(text,0).collapse(1).select(); + editor3.execCommand("inserttitlecol"); + equal(editor3.queryCommandState("inserttitlecol"),-1,'标题列不能向右合并'); + var f = $("#edui538_state")[0]; + start(); + }, 100); + stop(); +}); + +test('trace:3967',function(){ + var editor = te.obj[0]; + editor.setContent('123
    '); + editor.execCommand('insertorderedlist','decimal'); + editor.execCommand('source'); + setTimeout(function(){ + editor.execCommand('source'); + setTimeout(function(){ + editor.execCommand('source'); + var x = editor.getContent(); + ok(x.indexOf('br')== x.lastIndexOf('br'),'只有一个
    '); + start(); + },50) + },50) + stop(); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autoupload.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autoupload.js new file mode 100644 index 000000000..fa824cda6 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/autoupload.js @@ -0,0 +1,16 @@ +/** + * Created by JetBrains PhpStorm. + * User: Jinqn + * Date: 13-10-29 + * Time: 下午5:14 + * To change this template use File | Settings | File Templates. + */ +module('plugins.autoupload'); + +test('拖放图片上传',function(){ + equal('',''); +}); + +test('粘贴QQ截图',function(){ + equal('',''); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/background.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/background.js new file mode 100644 index 000000000..cf490e688 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/background.js @@ -0,0 +1,53 @@ +module( 'plugins.background' ); + + +test( 'getAllHtml能取到背景', function() { + var sc = document.createElement("script"); + var editor = te.obj[2]; + sc.id="sc"; + sc.type = "text/plain"; + document.body.appendChild(sc); + editor.render('sc'); + editor.ready(function(){ + equal( editor.queryCommandState( 'background' ), 0, 'check background state' ); + this.body.style.backgroundColor = "#d7e3bc"; +// this.body.style.backgroundImage = '/ueditor/php/upload//8721363160868.gif'; + setTimeout(function(){ + var headHtml = []; + editor.fireEvent('getAllHtml',headHtml); + equal(ua.formatColor(editor.body.style.backgroundColor),'#d7e3bc','检查body背景色'); + +// equal(editor.body.style.backgroundImage,'','检查body背景图片'); + document.getElementById('sc').parentNode.removeChild(document.getElementById('sc')); + start(); + },50); + }); + stop(); +} ); +test( ' trace 3744 setContent 背景色', function() { + var editor = te.obj[0]; + editor.setContent('



    '); + stop(); + setTimeout(function(){ + equal(ua.formatColor($(editor.body).css('background-color')),'#8064a2','setContent 背景色'); + start(); + },50); +}); +test( ' trace 3751 3748 设置 背景色', function() { + var editor = te.obj[0]; + var backgroundStyle = {'background-repeat': "no-repeat", 'background-position': "center center", 'background-color': "#4F81BD"}; + editor.setContent('


    '); + editor.execCommand('background',backgroundStyle); + stop(); + setTimeout(function(){ + equal(editor.queryCommandValue('background')['background-repeat'],'no-repeat'); + equal(ua.formatColor(editor.queryCommandValue('background')['background-color'].toLowerCase()),'#4f81bd'); + ok(/center/.test(editor.queryCommandValue('background')['background-position'])); + editor.execCommand('source'); + setTimeout(function(){ + ua.checkSameHtml(editor.body.lastChild.outerHTML,'


    ','source查看 背景色'); +// equal(editor.body.lastChild.outerHTML,'


    ','source查看 背景色'); + start(); + },50); + },50); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/basestyle.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/basestyle.js new file mode 100644 index 000000000..0008d7e2d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/basestyle.js @@ -0,0 +1,315 @@ +module("plugins.basestyle"); + +test('sub--table', function () { + var editor = te.obj[0]; + setTimeout(function () { + editor.setContent('
    hello1hello2
    hello3hello4
    '); + setTimeout(function () { + var range = te.obj[1]; + var body = editor.document.body; + //1.2的版本中,table标签套了div标签,原来的var tbody = body.firstChild.firstChild;改为如下 + var tbody = editor.document.getElementsByTagName('table')[0].firstChild; + range.selectNode(body.firstChild).select(); + var tds = body.firstChild.getElementsByTagName('td'); + var td; +// for ( var index = 0; td = tds[index++]; ) { +// editor.currentSelectedArr.push( td ); +// } + editor.execCommand('subscript'); + setTimeout(function () { + equal(ua.getChildHTML(tbody.firstChild.firstChild), 'hello1', '检查第1个单元格中文本是否是下标'); + equal(ua.getChildHTML(tbody.firstChild.firstChild.nextSibling), 'hello2', '检查第2个单元格中文本是否是下标'); + equal(ua.getChildHTML(tbody.lastChild.firstChild), 'hello3', '检查第3个单元格中文本是否是下标'); + equal(ua.getChildHTML(tbody.lastChild.firstChild.nextSibling), 'hello4', '检查第4个单元格中文本是否是下标'); + equal(editor.queryCommandState('superscript'), 0, 'check sup state'); + equal(editor.queryCommandState('subscript'), 1, 'check sub state'); + + editor.execCommand('subscript'); + /**trace 943,为表格去上下标**/ + equal(tbody.firstChild.firstChild.innerHTML, 'hello1', '检查第1个单元格中文本是否不是下标'); + equal(tbody.firstChild.firstChild.nextSibling.innerHTML, 'hello2', '检查第2个单元格中文本是否不是下标'); + equal(tbody.lastChild.firstChild.innerHTML, 'hello3', '检查第3个单元格中文本是否不是下标'); + equal(tbody.lastChild.firstChild.nextSibling.innerHTML, 'hello4', '检查第4个单元格中文本是否你是下标'); + equal(editor.queryCommandState('superscript'), 0, 'check sup state'); + equal(editor.queryCommandState('subscript'), 0, 'check sub state'); + + editor.execCommand('superscript'); + /*上下标互斥*/ + equal(ua.getChildHTML(tbody.firstChild.firstChild), 'hello1', '检查第1个单元格中文本是否是上标'); + equal(ua.getChildHTML(tbody.firstChild.firstChild.nextSibling), 'hello2', '检查第2个单元格中文本是否是上标'); + equal(ua.getChildHTML(tbody.lastChild.firstChild), 'hello3', '检查第3个单元格中文本是否是上标'); + equal(ua.getChildHTML(tbody.lastChild.firstChild.nextSibling), 'hello4', '检查第4个单元格中文本是否是上标'); + equal(editor.queryCommandState('superscript'), 1, 'check sup state'); + equal(editor.queryCommandState('subscript'), 0, 'check sub state'); + start(); + }, 50); + }, 50); + }, 50); + stop(); +}); + +//如果没有setTimeout在FF(3.6和9都是)中range会出错,其他浏览器没问题 +test('闭合插入上下标', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    你好

    '); + var body = editor.body; + stop(); + setTimeout(function () { + range.setStart(body.firstChild.firstChild, 1).collapse(1).select(true); + editor.execCommand('superscript'); + equal(ua.getChildHTML(body.firstChild), '你好', '查看执行上标后的结果'); + range = editor.selection.getRange(); + range.insertNode(editor.document.createTextNode('hello')); + equal(ua.getChildHTML(body.firstChild), '你hello好', '上标标签中插入文本'); + start(); + }, 100) +}); + +test('不闭合插入上下标', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('hello1hello2baidu_linkhello3'); + var body = editor.document.body; + stop(); + setTimeout(function () { + range.setStart(body.firstChild.firstChild, 0).setEnd(body.firstChild.lastChild, 3).select(); + editor.execCommand('superscript'); + ua.manualDeleteFillData(body); + ua.checkSameHtml(editor.getContent(), '

    hello1hello2baidu_linkhello3

    ', '普通文本添加上标'); + start(); + }, 100); +}); + +/*trace 870*/ +//无法模拟光标自动移到的场景,因此模拟输入文本通过插入文本节点实现的方法,在插入文本后光标仍然在原来的位置 +// 我们不确定光标实际在哪 +test('trace 870:加粗文本前面去加粗', function () { + var editor = te.obj[0]; + var body = editor.body; + var range = te.obj[1]; + editor.setContent('


    '); + range.setStart(body.firstChild, 0).collapse(true).select(); + editor.execCommand('bold'); + range = editor.selection.getRange(); + range.insertNode(editor.document.createTextNode('hello')); + equal(editor.queryCommandState('bold'), 1, '加粗'); + editor.execCommand('bold'); + range = editor.selection.getRange(); + equal(editor.queryCommandState('bold'), 0, '不加粗'); + range.insertNode(editor.document.createTextNode('hello2')); + /*插入一个文本节点*/ + ua.manualDeleteFillData(editor.body); + /*ie下插入节点后会自动移动光标到节点后面,而其他浏览器不会*/ + if (ua.browser.chrome || ua.browser.safari || (ua.browser.ie && ua.browser.ie > 8 && ua.browser.ie<11))// ie9,10改range + equal(editor.getContent(), '

    hello2hello

    '); + else + equal(editor.getContent(), '

    hellohello2

    '); +}); + +/*trace 1043*/ +test('bold-在已加粗文本中间去除加粗', function () { + var editor = te.obj[0]; + var body = editor.body; + var range = te.obj[1]; + editor.setContent('hellossss'); + range.setStart(body.firstChild.firstChild, 0).collapse(true).select(); + editor.execCommand('bold'); + range = editor.selection.getRange(); + equal(editor.queryCommandState('bold'), 0, " 被去掉"); + range.insertNode(range.document.createTextNode('aa')); + /*在当前的range选区插入文本节点*/ + ua.manualDeleteFillData(editor.body); + equal(ua.getChildHTML(body.firstChild), "aahellossss", "新文本节点没有加粗"); +}); + +/*trace 958*/ +test('bold-在已加粗文本中间去除加粗', function () { + var editor = te.obj[0]; + var body = editor.body; + var range = te.obj[1]; + editor.setContent(''); + editor.execCommand('bold'); + ok(ua.getChildHTML(body), "", "editor不focus时点加粗,不会多一个空行"); +}); + +/*trace 958*/ +test('bold-加粗状态反射', function () { + var editor = te.obj[0]; + var body = editor.body; + var range = te.obj[1]; + editor.setContent('

    this is a dog

    '); + stop(); + setTimeout(function () { + range.selectNode(body.firstChild).select(); + editor.execCommand('bold'); + range.setStart(body.firstChild.firstChild.firstChild, 2).collapse(true).select(); + equal(editor.queryCommandState('bold'), 1, '闭合选择,加粗高亮'); + ua.manualDeleteFillData(editor.body); + range.setStart(body.firstChild.firstChild.firstChild, 0).setEnd(body.firstChild.firstChild.lastChild, 4).select(); + equal(editor.queryCommandState('bold'), 1, '不闭合选择,加粗高亮'); + start(); + }, 100) +}); + +/*trace 580*/ +test('bold-连续加粗2次', function () { + var editor = te.obj[0]; + var body = editor.body; + var range = te.obj[1]; + editor.setContent('

    this is a dog

    '); + var text = body.firstChild.firstChild; + range.setStart(text, 0).setEnd(text, 3).select(); + editor.execCommand('bold'); + /*第一次加粗*/ + equal(editor.queryCommandState('bold'), 1, '加粗按钮高亮'); + text = body.firstChild.lastChild; + range.setStart(text, 1).setEnd(text, 3).select(); + /*不闭合选区文本*/ + equal(editor.queryCommandState('bold'), 0, '不闭合选择,加粗不高亮'); + ua.manualDeleteFillData(editor.body); + editor.execCommand('bold'); + /*第二次加粗*/ + equal(editor.queryCommandState('bold'), 1, '加粗高亮'); +}); + +/*trace 1983*/ +test('bold-2个单词,中间有空格第一个单词加粗,第二个单词加粗再去加粗', function () { + var editor = te.obj[0]; + var body = editor.body; + var range = te.obj[1]; + body.innerHTML = '

    hello world

    '; //用setContent复现不了这个问题 + var text = body.firstChild.firstChild; + range.setStart(text, 0).setEnd(text, 5).select(); + editor.execCommand('bold'); + text = body.firstChild.lastChild; + range.setStart(text, 1).setEnd(text, 6).select(); + editor.execCommand('bold'); + editor.execCommand('bold'); + ok(body.firstChild.childNodes.length == 3 && body.firstChild.childNodes[1].length == 1, '空格保留'); +}); + +test('测试 userAction.manualdeleteFilldata', function () { + var editor = te.obj[0]; + var body = editor.body; + var range = te.obj[1]; + editor.setContent('

    '); + var fillData = editor.document.createTextNode(domUtils.fillChar); // 在ie 6,7下,使用appendChild时,需要body先加载,必须将上句document前加editor,否则出错 + body.appendChild(fillData); + var space = ua.browser.ie ? ' ' : '
    ';//getContent()结果:‘
    ’,innerHTML结果:
    + notEqual(body.innerHTML.toLowerCase(), '

    ' + space + '

    ', '清除不可见字符前不相等'); + ua.manualDeleteFillData(body); + equal(body.innerHTML.toLowerCase(), '

    ' + space + '

    ', '清除不可见字符后相等'); +}); + +test('trace 1884:单击B再单击I ', function () { + var editor = te.obj[0]; + var body = editor.body; + var range = te.obj[1]; + editor.setContent(''); + range.setStart(body.firstChild, 0).collapse(1).select(); + editor.execCommand('bold'); + equal(editor.queryCommandState('bold'), 1, 'b高亮'); + editor.execCommand('italic'); + equal(editor.queryCommandState('italic'), 1, 'b高亮'); +}); + +test('单击B再在其他地方单击I,空的strong标签被删除 ', function () { + var editor = te.obj[0]; + var body = editor.body; + var range = te.obj[1]; + editor.setContent('

    hello

    '); + range.setStart(body.firstChild, 0).collapse(1).select(); + editor.execCommand('bold'); + equal(editor.queryCommandState('bold'), 1, 'b高亮'); + range.setStart(body.firstChild, 1).collapse(1).select(); + editor.execCommand('italic'); + equal(editor.queryCommandState('italic'), 1, 'b高亮'); + ua.manualDeleteFillData(body); + if (!ua.browser.ie) { //ie下有问题不能修,屏蔽ie + equal(body.innerHTML.toLowerCase(), '

    hello

    ', '空strong标签被删除') + } +}); + +test('ctrl+i', function () { + var editor = te.obj[0]; + var body = editor.body; + var range = te.obj[1]; + editor.setContent('

    没有加粗的文本

    '); + range.selectNode(body.firstChild).select(); + var p = body.firstChild; + setTimeout(function () { + ua.keydown(editor.body, {'keyCode': 73, 'ctrlKey': true}); + editor.focus(); + setTimeout(function () { + equal(ua.getChildHTML(p), '没有加粗的文本'); + start(); + }, 150); + }, 100); + stop(); +}); + +test('ctrl+u', function () { + var editor = te.obj[0]; + var body = editor.body; + var range = te.obj[1]; + editor.setContent('

    没有加粗的文本

    '); + setTimeout(function () { + range.selectNode(body.firstChild).select(); + setTimeout(function () { + var html = '没有加粗的文本'; + ua.checkHTMLSameStyle(html, editor.document, body.firstChild, '文本被添加了下划线'); + equal(editor.body.firstChild.firstChild.style.textDecoration, 'underline'); + start(); + }, 150); + ua.keydown(editor.body, {'keyCode': 85, 'ctrlKey': true}); + }, 150); + stop(); +}); + +test('ctrl+b', function () { + var editor = te.obj[0]; + var body = editor.body; + var range = te.obj[1]; + + editor.setContent('

    没有加粗的文本

    '); + range.selectNode(body.firstChild).select(); + setTimeout(function () { + ua.keydown(editor.body, {'keyCode': 66, 'ctrlKey': true}); + setTimeout(function () { + equal(ua.getChildHTML(body.firstChild), '没有加粗的文本'); + start(); + }, 150); + }, 150); + stop(); +}); + +/*trace 3240*/ +test('表格中文本加粗', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable'); + ua.manualDeleteFillData(editor.body); + setTimeout(function () { + var tds = editor.body.getElementsByTagName('td'); + tds[0].innerHTML = 'asd'; + tds[10].innerHTML = 'asd'; + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[2].cells[0]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + + editor.execCommand('bold'); + ua.manualDeleteFillData(editor.body); + equal(editor.queryCommandState('bold'), 1, 'b高亮'); + equal(trs[0].cells[0].firstChild.tagName.toLowerCase(), 'strong', '[0][0]单元格中文本标签'); + if (!ua.browser.ie) + equal(trs[1].cells[0].firstChild.tagName.toLowerCase(), 'br', '[1][0]单元格中文本标签'); + equal(trs[2].cells[0].firstChild.tagName.toLowerCase(), 'strong', '[2][0]单元格中文本标签'); + start(); + }, 50); + stop(); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/blockquote.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/blockquote.js new file mode 100644 index 000000000..4f203349d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/blockquote.js @@ -0,0 +1,165 @@ +module( "plugins.blockquote" ); + +/*trace 967*/ +//这个用例暂不测ie,因为ie中输入回车无效 +//test( '切换到源码模式再切换回来点引用', function () { +// if(!ua.browser.ie){ +// var editor = te.obj[0]; +// var body = editor.body; +// editor.setContent( 'hello' ); +// editor.execCommand( 'source' ); +// var tas = editor.iframe.parentNode.getElementsByTagName( 'textarea' ); +// tas[tas.length - 1].value = ''; +// stop(); +// setTimeout( function () { //source.js中有延时操作 +// editor.execCommand( 'source' ); +// editor.execCommand( 'blockquote' ); +// setTimeout( function () { //模拟回车,在引用后回车两段都是引用 +// //firefox竟然要多触发一次。。什么乱七八糟的bug啊 +// //if ( ua.getBrowser() == "firefox" ) +// //te.presskey( "enter", "" ); +// editor.focus(); +// te.presskey( "enter", "" ); +// setTimeout( function () { +// editor.focus(); +// setTimeout( function () { +// var bq = body.firstChild; +// equal( body.childNodes.length, 1, 'body有1个孩子' ); +// equal( bq.childNodes.length, 2, 'blockquote有2个孩子' ); +// ok( bq.childNodes[0]&&bq.childNodes[0].tagName.toLowerCase()=='p', '第一个孩子是p' ); +// ok( bq.childNodes[1]&&bq.childNodes[1].tagName.toLowerCase()=='p', '第二个孩子是p' ); +// start(); +// }, 50 ); +// }, 30 ); +// }, 60 ); +// }, 50 ); +// } +// else +// ok(ua.browser.ie,'这个用例暂不测,因为ie中输入回车无效'); +//} ); + +test( '在表格中添加和去除引用', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( 'hello
    hello
    ' ); + var body = editor.body; + var tds = body.lastChild.getElementsByTagName( 'td' ); + range.setStart( tds[0].firstChild, 2 ).collapse( true ).select(); /*闭合选取*/ + editor.execCommand( 'blockquote' ); + equal( body.lastChild.tagName.toLowerCase(), 'blockquote', '引用加到表格外面去了' ); + equal( tds[0].firstChild.nodeType, 3, 'td里仍然是文本' ); + equal( tds[0].firstChild.data, 'he', 'td里仍然是文本he' ); + range.setStart( tds[0].firstChild, 2 ).collapse( true ).select(); + editor.execCommand( 'blockquote' ); /*再执行一次引用,会去掉引用*/ + ok( body.lastChild.tagName.toLowerCase() != 'blockquote', '引用去掉了' ); //1.2版本table外加了div + stop(); + setTimeout(function(){ + tds = body.lastChild.getElementsByTagName( 'td' ); + range.selectNode( tds[0] ).select(); /*不闭合选中表格,添加引用*/ + editor.execCommand( 'blockquote' ); + equal( body.lastChild.tagName.toLowerCase(), 'blockquote', '非闭合方式选中添加引用' ); + start(); + },50); +} ); + +test( '在列表中添加引用', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( 'hello
    1. hello1

    2. hello2

    ' ); + var body = editor.body; + var lis = body.lastChild.getElementsByTagName( 'li' ); + range.setStart( lis[0].firstChild, 1 ).collapse( 1 ).select(); /*闭合选取*/ + editor.execCommand( 'blockquote' ); + equal( body.lastChild.tagName.toLowerCase(), 'blockquote', '引用加到列表外面去了' ); + equal( lis[0].firstChild.nodeType, 1, '列表里套着p' ); + equal( lis[0].firstChild.firstChild.data, 'hello1', '列表里仍然是文本hello1' ); +} ); + +/*trace 1183*/ +test( 'trace1183:选中列表中添加引用,再去掉引用', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello1

    hello2

    ' ); + var body = editor.body; + range.setStart( body, 0 ).setEnd( body, 2 ).select(); + editor.execCommand( 'insertorderedlist' ); /*添加列表*/ + ua.manualDeleteFillData( editor.body ); + var ol = body.getElementsByTagName( 'ol' )[0]; + var html = ua.getChildHTML( ol ); + + editor.execCommand( 'blockquote' ); + editor.execCommand( 'blockquote' ); + ua.manualDeleteFillData( editor.body ); + equal( ua.getChildHTML( body.getElementsByTagName( 'ol' )[0] ), html, '引用前后列表没有发生变化' ); + equal( body.getElementsByTagName( 'ol' ).length, 1, '只有一个有序列表' ); +} ); + +test( 'trace 3298:对段落添加引用和去除引用', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello1

    hello2 world

    ' ); + var body = editor.body; + range.setStart( body.firstChild, 0 ).setEnd( body.lastChild, 1 ).select(); /*不闭合添加引用*/ + editor.execCommand( 'blockquote' ); + equal( ua.getChildHTML( body ), '

    hello1

    hello2  world

    ', '不闭合添加引用' ); + equal( editor.queryCommandState( 'blockquote' ), 1, '引用高亮' ); + + range.setStart( body.firstChild.lastChild, 0 ).collapse( true ).select(); /*闭合去除引用*/ + editor.execCommand( 'blockquote' ); + equal( ua.getChildHTML( body ), '

    hello1

    hello2  world

    ', '闭合去除引用' ); + equal( editor.queryCommandState( 'blockquote' ), 0, '引用不高亮' ); + + range.setStart( body.firstChild, 0 ).setEnd( body.lastChild, 1 ).select(); /*非闭合去除引用*/ + editor.execCommand( 'blockquote' ); + equal( ua.getChildHTML( body ), '

    hello1

    hello2  world

    ' ); + equal( editor.queryCommandState( 'blockquote' ), 0, '非闭合去除引用后,引用不高亮' ); + + range.setStart( body.lastChild, 0 ).collapse( true ).select(); /*闭合添加引用*/ + editor.execCommand( 'blockquote' ); + equal( ua.getChildHTML( body ), '

    hello1

    hello2  world

    ', '闭合添加引用 ' ); +} ); + +/*trace 3285*/ +test( 'trace 3285:startContainer为body添加引用', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( 'hello
    1. hello1
    2. hello2
    ' ); + var body = editor.body; + range.setStart( body, 0 ).setEnd( body, 2 ).select(); /*不闭合选取*/ + editor.execCommand( 'blockquote' ); +// var padding = ua.browser.ie&&ua.browser.ie<9?' style=\" list-paddingleft-2\"':(ua.browser.webkit?' class=\" list-paddingleft-2\"':' style=\" list-paddingleft-2\"'); + var padding = ' class=\" list-paddingleft-2\"'; + equal( ua.getChildHTML( body ), '

    hello

  • hello1

  • hello2

  • ', '选中body加引用' ); + equal( editor.queryCommandState( 'blockquote' ), 1, '引用高亮' ); + editor.undoManger.undo(); + range.setStart( body, 1 ).collapse( true ).select(); /*闭合选取*/ + equal( editor.queryCommandState( 'blockquote' ), 0, '引用不高亮' ); +} ); + +//ie 不通过 +test('aa标签',function(){ + var editor = te.obj[0]; + var range = te.obj[1]; + if(!ua.browser.ie){ + editor.setContent('hello'); + range.setStart(editor.body.firstChild.firstChild,0).collapse(1).select(); + editor.execCommand('blockquote'); + equal(ua.getChildHTML(editor.body),'
    hello
    ','aa标签'); + editor.setContent('hellohello2'); + range.setStart(editor.body.lastChild.firstChild,0).setEnd(editor.body.lastChild.firstChild,3).select(); + editor.execCommand('blockquote'); + equal(ua.getChildHTML(editor.body),'

    hello

    hello2
    ',''); + } +}); + +/*trace 3284*/ +test('trace 3284:列表内引用',function(){ + var editor = te.obj[0]; + var range = te.obj[1]; +// var padding = ua.browser.ie&&ua.browser.ie<9?' style=\"padding-left: 30px\"':(ua.browser.webkit?' style=\"padding-left: 30px;\"':' style=\"padding-left: 30px;\"'); + var padding = ' class=\" list-paddingleft-2\"'; + editor.setContent('
    1. hello1

    2. hello2

    '); + range.setStart(editor.body.firstChild.firstChild.firstChild.firstChild,0).setEnd(editor.body.firstChild.lastChild.firstChild.firstChild,6).select(); + editor.execCommand('blockquote'); + equal(ua.getChildHTML(editor.body ),'
  • hello1

  • hello2

  • ','引用删除'); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/catchremoteimage.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/catchremoteimage.js new file mode 100644 index 000000000..24942b4a6 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/catchremoteimage.js @@ -0,0 +1,45 @@ +module( 'plugins.catchremoteimage' ); + +test( '成功远程图片抓取', function () { + UEDITOR_CONFIG.UEDITOR_HOME_URL = '../../../'; + for (var config in window.UEDITOR_CONFIG) { + if (typeof(window.UEDITOR_CONFIG[config]) == 'string'){ + window.UEDITOR_CONFIG[config] = window.UEDITOR_CONFIG[config].replace('_test/tools/br/', ''); + } + } + var editor = new UE.Editor({'autoFloatEnabled':false}); + stop(); + setTimeout(function(){ + var div = document.body.appendChild( document.createElement( 'div' ) ); + editor.render( div ); + + editor.ready(function(){ + var body = editor.body; + editor.setContent( '

    ' ); + editor.fireEvent( "catchRemoteImage" ); + var count = 0; + var handler = setInterval( function () { + count++; + var imgs = body.getElementsByTagName( 'img' ); + var src = imgs [1].getAttribute( 'src' ); + if ( /upload/.test( src ) ) { + clearInterval( handler ); + ok( /upload/.test( imgs[0].getAttribute( 'src' ) ), '图片已经被转存到本地' ); +// equal( imgs[0].getAttribute( 'src' ), imgs[0].getAttribute( '_src' ), '查看_src' ); +// equal( imgs[1].getAttribute( 'src' ), imgs[1].getAttribute( '_src' ), '查看_src' ); + equal( imgs.length, 2, '2个图片' ); + start(); + } else if ( count > 100 ) { + clearInterval( handler ); + ok( false, '超时,文件获取失败' ); + start(); + } + }, 100 ); + te.dom.push( div ); + },50); + },100); +} ); + +//test( '失败远程图片抓取', function () { +////超时太长了,而且就是一个alert,alert出来还会影响后面跑用例,先占个坑 +//} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/charts.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/charts.js new file mode 100644 index 000000000..2413fdff9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/charts.js @@ -0,0 +1,105 @@ +module( 'plugins.charts' ); + +test( '图表命令检测', function() { + expect(3); + + var container = te.obj[0].container, + editor = null, + count = 0; + + UE.delEditor( te.obj[0] ); + container.parentNode.removeChild( container ); + + container = document.createElement( "div" ); + container.id = "container"; + document.body.appendChild( container ); + editor = UE.getEditor( "container", { + initialContent: '' + + '
    ' + + '


    ' + + '

    ' + } ); + + + stop(); + + editor.ready( function () { + + var firstTd = editor.body.getElementsByTagName("td")[0]; + var range = new baidu.editor.dom.Range(editor.document); + + range.selectNode( firstTd).collapse(true).select(); + + equal( editor.queryCommandState( 'charts' ), -1, '数据验证失败, 状态为禁用' ); + + + + //设置数据格式合法的表格 + editor.setContent('

    abcdef
    1999123456
    '); + + firstTd = editor.body.getElementsByTagName("td")[0]; + + range.setStart( firstTd,0).collapse(true).select(); + + equal( editor.queryCommandState( 'charts' ) != -1, true, '数据合法, 状态可用' ); + + editor.execCommand( 'charts', { + title: '测试标题', + subTitle: '标题2', + xTitle: 'X轴标题', + yTitle: 'Y轴标题', + suffix: '后缀', + tip: '提示', + dataFormat: '1', + chartType: 1 + } ); + + var tableNode = editor.body.getElementsByTagName("table")[0]; + + equal( tableNode.getAttribute("data-chart") !== null, true, '插入图表命令执行成功' ); + + setTimeout(function(){ + UE.delEditor("container"); + document.getElementById("container")&&te.dom.push( document.getElementById("container")); + start(); + },300); + + } ); + +} ); +test( '图表命令检测', function() { +// expect(5); + + UE.delEditor( te.obj[0] ); + var div = document.createElement( "div" ); + div.id = "container"; + document.body.appendChild( div ); + var editor = UE.getEditor( "container", { + initialContent: '
    ' + + '

    ' + } ); + stop(); + editor.ready( function () { + var range = editor.selection.getRange(); + range.selectNode( editor.body.getElementsByTagName("td")[0]).collapse(true).select(); + equal( editor.queryCommandState( 'charts' ), -1, '列数不够, 状态为禁用' ); + //
    12
    22
    + editor.setContent('
    e
    12
    22
    '); + range.selectNode( editor.body.getElementsByTagName("td")[0]).collapse(true).select(); + equal( editor.queryCommandState( 'charts' ), -1, '第一行不都是th, 状态为禁用' ); + editor.setContent('
    e
    12
    22
    '); + range.selectNode( editor.body.getElementsByTagName("td")[0]).collapse(true).select(); + equal( editor.queryCommandState( 'charts' ), -1, '第一列不是th, 状态为禁用' ); + editor.setContent('
    552
    2
    24
    '); + range.selectNode( editor.body.getElementsByTagName("td")[0]).collapse(true).select(); + equal( editor.queryCommandState( 'charts' ), -1, '每行单元格数不匹配, 状态为禁用' ); + editor.setContent('
    1ee
    22
    '); + range.selectNode( editor.body.getElementsByTagName("td")[0]).collapse(true).select(); + equal( editor.queryCommandState( 'charts' ), -1, '内容不是数字, 状态为禁用' ); + setTimeout(function(){ + UE.delEditor("container"); + document.getElementById("container")&&te.dom.push( document.getElementById("container")); + start(); + },300); + } ); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/cleardoc.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/cleardoc.js new file mode 100644 index 000000000..53de1efb8 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/cleardoc.js @@ -0,0 +1,125 @@ +/** + * Created by JetBrains PhpStorm. + * User: shenlixia01 + * Date: 11-8-15 + * Time: 下午3:47 + * To change this template use File | Settings | File Templates. + */ +module( 'plugins.cleardoc' ); + +test( '取得焦点后清空后查看range', function () { + var editor = te.obj[0]; + editor.setContent( '

    hello1

    hello2
    ' ); + editor.focus(); + var body = editor.body; + editor.execCommand( 'cleardoc' ); + ua.manualDeleteFillData( editor.body ); + if ( UE.browser.ie ) { + equal( ua.getChildHTML( body ), '

    ' ); //目前ie清空文档后不放空格占位符 + } + else { + equal( ua.getChildHTML( body ), '


    ', '清空文档' ); + } +} ); + +test( '编辑器没有焦点,清空', function () { + var editor = te.obj[0]; + editor.setContent( '

    hello1

    hello2
    ' ); + var body = editor.body; + editor.execCommand( 'cleardoc' ); + ua.manualDeleteFillData( editor.body ); + if ( UE.browser.ie ) { + equal( ua.getChildHTML( body ), '

    ' ); + } + else { + equal( ua.getChildHTML( body ), '


    ', '清空文档' ); + } +} ); + +test( 'enterTag为br', function () { + var editor = te.obj[0]; + editor.options.enterTag='br'; + editor.setContent( '
    hello
    ' ); + var body = editor.body; + editor.execCommand( 'cleardoc' ); + ua.manualDeleteFillData( editor.body ); + if (UE.browser.ie) { + equal(ua.getChildHTML(body), '
    ', '清空文档'); + } + else { + equal(ua.getChildHTML(body), '
    ', '清空文档'); + } +} ); + +/*trace1061*/ +test( '删除时不会删除block元素', function() { + if(ua.browser.opera) return 0; + var editor = te.obj[0]; + editor.setContent( '

    hello

    ' ); + setTimeout(function() { + var range = te.obj[1]; + range.selectNode( editor.body.firstChild ).select(); + editor.execCommand( 'cleardoc' ); + equal( editor.body.lastChild.tagName.toLowerCase(), 'p', 'h1替换为p' ); + ua.manualDeleteFillData(editor.body); + if ( !baidu.editor.browser.ie ) + equal( editor.body.lastChild.innerHTML, '
    ', '内容被删除了' ); + else + equal( editor.body.lastChild.innerHTML, '', '内容被删除了' ); +// if(!ua.browser.opera){ +// range = editor.selection.getRange(); +// equal( range.startContainer.tagName.toLowerCase(), 'p', '光标位置' ); +// } + start(); + },50); + stop(); +} ); + +test('选中文本,清空',function(){ + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    hello

    hello1

    ') + range.selectNode(editor.body.firstChild).select(); + editor.execCommand('cleardoc'); + var br = ua.browser.ie?'':'
    '; + equal(ua.getChildHTML(editor.body),'

    '+br+'

    ',''); +}); + +/*trace 1104*/ +test( '全选后删除', function() { + var editor = te.obj[0]; + if ( baidu.editor.browser.ie ) + editor.setContent( '

    dsafds 

     

     

     

     

     

     

    ' ); + else + editor.setContent( '




    d






    ' ); + setTimeout(function() { + editor.focus(); + editor.execCommand( 'selectall' ); + editor.execCommand( 'cleardoc' ); + ua.manualDeleteFillData(editor.body); + equal( editor.body.childNodes.length, 1, '删除后只剩一个bolock元素' ); + equal( editor.body.firstChild.tagName.toLowerCase(), 'p', '删除后只剩一个p' ); + if ( !UE.browser.ie ) + equal( editor.body.lastChild.innerHTML, '
    ', '内容被删除了' ); + else + equal( editor.body.lastChild.innerHTML, '', '内容被删除了' ); + start(); + },50); + stop(); +} ); + +test( '删除所有列表', function() { + var editor = te.obj[0]; + editor.setContent('
    1. hello1
    2. 你好
    '); + setTimeout(function() { + var body = editor.body; + editor.focus(); + editor.execCommand( 'selectall' ); + editor.execCommand( 'cleardoc' ); + equal( body.childNodes.length, 1, '删除后只剩一个ol元素' ); + var br = UE.browser.ie?"":"
    "; + equal( ua.getChildHTML(body), '

    '+br+'

    ', '删除后只剩一个p' ); + start(); + },50); + stop(); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/contextmenu.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/contextmenu.js new file mode 100644 index 000000000..4ecf7d3f6 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/contextmenu.js @@ -0,0 +1,311 @@ +///** +// * Created by JetBrains PhpStorm. +// * User: dongyancen +// * Date: 12-9-19 +// * Time: 下午4:19 +// * To change this template use File | Settings | File Templates. +// */ +module('plugins.contextmenu'); + +//test('stop', function () {stop();}); +test('基本右键菜单', function () { + var editor = te.obj[0]; + stop(); + + ua.contextmenu(editor.body); + var lang = editor.getLang("contextMenu"); + equal(document.getElementsByClassName("edui-menu-body").length, 3, '默认3个menu,一个主的,一个段落格式,一个表格'); + var menuBody = document.getElementsByClassName("edui-menu-body")[0]; + equal(menuBody.parentNode.parentNode.parentNode.style.display, '', '第一个menu显示'); + equal(menuBody.childNodes.length, 11, '第一个menu8个items3个分隔线'); +// var space = browser.webkit||ua.browser.ie==9?"\n":''; + var innerText = lang['selectall'] + lang.cleardoc + lang.paragraph + lang.table + lang.insertparagraphbefore + lang.insertparagraphafter + lang['copy'] + lang['paste']; + if (browser.gecko) { + equal(menuBody.textContent, innerText, '检查menu显示的字符'); + } + else { + equal(menuBody.innerText.replace(/[\r\n\t\u200b\ufeff]/g, ''), innerText, '检查menu显示的字符'); + } + ok(menuBody.childNodes[0].className.indexOf("edui-for-selectall") > -1, '检查menu样式'); + var menuparagraphBody = document.getElementsByClassName("edui-menu-body")[1]; + equal(menuparagraphBody.parentNode.parentNode.parentNode.style.display, 'none', '第二个menu隐藏'); + var menutableBody = document.getElementsByClassName("edui-menu-body")[2]; + if (ua.browser.ie) { + ua.mouseenter(menuBody.childNodes[3]); + } else { + ua.mouseover(menuBody.childNodes[3]); + } + setTimeout(function () { + lang = editor.getLang("contextMenu"); + equal(menuparagraphBody.parentNode.parentNode.parentNode.style.display, 'none', '显示submenu,检查submenu的display值:""'); + equal(menuparagraphBody.childNodes.length, 4, '检查submenu的menuitems数量'); + equal(menutableBody.parentNode.parentNode.parentNode.style.display, 'none', '显示table submenu,检查submenu的display值:""'); + /*trace 3038*/ + if (ua.browser.ie && ua.browser.ie < 9) { + equal(menutableBody.childNodes.length, 2, 'ie有一条分隔线'); + } else { + equal(menutableBody.childNodes.length, 1, '只有插入表格选项'); + } + innerText = lang["justifyleft" ] + lang["justifyright" ] + lang["justifycenter" ] + lang[ "justifyjustify" ]; + if (browser.gecko) { + equal(menuparagraphBody.textContent, innerText, '检查menu显示的字符'); + equal(menutableBody.textContent, lang["inserttable" ], '检查table menu显示的字符'); + } + else { + equal(menuparagraphBody.innerText.replace(/[\r\n\t\u200b\ufeff]/g, ''), innerText, '检查menu显示的字符'); + equal(menutableBody.innerText.replace(/[\r\n\t\u200b\ufeff]/g, ''), lang["inserttable" ], '检查table menu显示的字符'); + } + ua.click(menuparagraphBody.childNodes[1]); + setTimeout(function () { + equal(editor.body.firstChild.style.textAlign, 'right', '文本右对齐'); + document.getElementById('edui_fixedlayer').parentNode.removeChild(document.getElementById('edui_fixedlayer')); + te.dom.push(editor.container); + start(); + }, 500); + }, 200); +}); + +test('表格右键菜单', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + stop(); + var lang = editor.getLang("contextMenu"); + editor.setContent('



    '); + setTimeout(function () { + range.setStart(editor.body.firstChild.firstChild.firstChild.firstChild.firstChild, 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild.firstChild.firstChild); +// 点开右键菜单 + equal(document.getElementsByClassName("edui-menu-body").length, 5, '获得edui-menu-body名称的class个数5'); + var menuBody = document.getElementsByClassName("edui-menu-body")[0]; + equal(menuBody.childNodes.length, 13, '第一个menu11个items2个分隔线'); + var innerText = lang.selectall + lang.cleardoc + lang.table + lang.tablesort + lang.borderbk+ lang.aligntd + lang.aligntable + lang.insertparagraphbefore + lang.insertparagraphafter + lang['copy'] + lang['paste']; + if (browser.gecko) { + equal(menuBody.textContent, innerText, '检查menu显示的字符'); + } + else { + equal(menuBody.innerText.replace(/[\r\n\t\u200b\ufeff]/g, ''), innerText, '检查menu显示的字符'); + } + + var menutableBody = document.getElementsByClassName("edui-menu-body")[1]; + var forTable = document.getElementsByClassName('edui-for-table'); +//点开'表格'子菜单 + if (ua.browser.ie) { + ua.mouseenter(forTable[forTable.length - 1]); + } else { + ua.mouseover(forTable[forTable.length - 1]); + } + setTimeout(function () { + lang = editor.getLang("contextMenu"); + equal(menutableBody.parentNode.parentNode.parentNode.style.display, 'none', '显示submenu,检查submenu的display值:""'); + equal(menutableBody.childNodes.length, 19, '14个items5个分隔线'); + var innerText = lang.deletetable + lang.deleterow + lang.deletecol+ lang.insertcol + lang.insertcolnext + lang.insertrow + lang.insertrownext + lang.insertcaption + lang.inserttitle + lang.inserttitlecol + lang.mergeright + lang.mergedown + lang.edittd + lang.edittable+lang.setbordervisible; + if (browser.gecko) { + equal(menutableBody.textContent, innerText, '检查menu显示的字符'); + } + else { + equal(menutableBody.innerText.replace(/[\r\n\t\u200b\ufeff]/g, ''), innerText, '检查menu显示的字符'); + } + ua.click(menutableBody.childNodes[0]); + equal(editor.body.getElementsByTagName('table').length, 0, '删除表格'); + setTimeout(function () { + document.getElementById('edui_fixedlayer').parentNode.removeChild(document.getElementById('edui_fixedlayer')); + te.dom.push(editor.container); + start(); + }, 200); + }, 200); + }, 100); +}); + +/*trace 3044*/ +test('trace 3044:表格名称中右键', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + stop(); + var lang = editor.getLang("contextMenu"); + editor.execCommand('cleardoc'); + editor.execCommand('inserttable'); + range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + var menutableBody = document.getElementsByClassName("edui-menu-body")[1]; + var forTable = document.getElementsByClassName('edui-for-table'); + if (ua.browser.ie) { + ua.mouseenter(forTable[forTable.length - 1]); + } else { + ua.mouseover(forTable[forTable.length - 1]); + } + setTimeout(function () { + lang = editor.getLang("contextMenu"); + ua.click(menutableBody.childNodes[9]); + var caption = editor.body.getElementsByTagName('caption'); + equal(caption.length, 1, '插入表格名称'); + range.setStart(caption[0], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild.firstChild); + forTable = document.getElementsByClassName('edui-for-table'); + if (ua.browser.ie) { + ua.mouseenter(forTable[forTable.length - 1]); + } else { + ua.mouseover(forTable[forTable.length - 1]); + } + setTimeout(function () { + lang = editor.getLang("contextMenu"); + menutableBody = document.getElementsByClassName("edui-menu-body")[1]; + if (ua.browser.ie == 8) { + equal(menutableBody.childNodes.length, 9, '9个子项目,其中有2条分隔线'); + } else { + equal(menutableBody.childNodes.length, 7, '7个子项目'); + } + var innerText = lang.deletetable + lang.deletecaption + lang.inserttitle+lang.inserttitlecol + lang.edittd + lang.edittable+lang.setbordervisible; + if (browser.gecko) { + equal(menutableBody.textContent, innerText, '检查menu显示的字符'); + } else { + equal(menutableBody.innerText.replace(/[\r\n\t\u200b\ufeff]/g, ''), innerText, '检查menu显示的字符'); + } + setTimeout(function () { + document.getElementById('edui_fixedlayer').parentNode.removeChild(document.getElementById('edui_fixedlayer')); + te.dom.push(editor.container); + start(); + }, 200); + }, 200); + }, 200); +}); + + + + +/*trace 3088*/ +test('trace 3088:检查表格属性', function () { +// if (ua.browser.ie >8)return; + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor('ue'); + + stop(); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + var lang = editor.getLang("contextMenu"); + editor.execCommand('cleardoc'); + editor.execCommand('inserttable'); + range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); + editor.execCommand('inserttitle'); + range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); + editor.execCommand('insertcaption'); + range.setStart(editor.body.getElementsByTagName('caption')[0], 0).collapse(true).select(); + editor.execCommand('deletetitle'); + setTimeout(function () { + range.setStart(editor.body.getElementsByTagName('caption')[0], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild.firstChild); + setTimeout(function () { + var menutable = document.getElementsByClassName("edui-menu-body")[1]; + var forTable = document.getElementsByClassName('edui-for-table'); + //点开'表格属性'(表格子菜单的倒数第二项) + if (ua.browser.ie&&ua.browser.ie<9) { + ua.mouseenter(forTable[forTable.length - 1]); + ua.click(menutable.childNodes[menutable.childNodes.length-2]); + } else { + ua.mouseover(forTable[forTable.length - 1]); + ua.click(menutable.childNodes[menutable.childNodes.length-2]); + } + lang = editor.getLang("contextMenu"); + setTimeout(function () { + var iframe = document.getElementsByTagName('iframe'); + var iframe1 ; + for (var i = 0; i hello

    '); + setTimeout(function () { + range.setStart(body.firstChild, 1).collapse(true).select(); + editor.execCommand("touppercase"); + equal(editor.getContent(), "

    hello

    ", "闭合选择--up"); + start(); + }, 50); + }, 100); +}); +test('非闭合选择----字符串全选', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    hello1

    hello2

    '); + setTimeout(function () { + range.setStart(body.firstChild, 0).setEnd(body.lastChild, 1).select(); + editor.execCommand("touppercase"); + equal(editor.getContent(), "

    HELLO1

    HELLO2

    ", "非闭合--字符串全选--up"); + editor.execCommand("touppercase"); + equal(editor.getContent(), "

    HELLO1

    HELLO2

    ", "非闭合--两次up"); + editor.execCommand("tolowercase"); + equal(editor.getContent(), "

    hello1

    hello2

    ", "非闭合--字符串全选--low"); + editor.execCommand("tolowercase"); + equal(editor.getContent(), "

    hello1

    hello2

    ", "非闭合---两次low"); + start(); + }, 50); + stop(); +}); +test('非闭合选择----子字符串', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    hello1

    hello2

    '); + setTimeout(function () { + range.setStart(body.firstChild.firstChild, 2).setEnd(body.lastChild.firstChild, 2).select(); + editor.execCommand("touppercase"); + equal(editor.getContent(), "

    heLLO1

    HEllo2

    ", "非闭合--子字符串--up"); + editor.execCommand("tolowercase"); + equal(editor.getContent(), "

    hello1

    hello2

    ", "非闭合--子字符串--low"); + start(); + }, 50); + stop(); +}); +test('非闭合选择----字符串包括大写跟小写', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + var text = "

    HEllo1

    heLLo2

    "; + editor.setContent(text); + setTimeout(function () { + range.setStart(body.firstChild.firstChild, 0).setEnd(body.lastChild.firstChild, 6).select(); + editor.execCommand("touppercase"); + equal(editor.getContent(), "

    HELLO1

    HELLO2

    ", "非闭合--包含大小写--up"); + editor.setContent(text); + setTimeout(function () { + range.setStart(body.firstChild.firstChild, 0).setEnd(body.lastChild.firstChild, 6).select(); + editor.execCommand("tolowercase"); + equal(editor.getContent(), "

    hello1

    hello2

    ", "非闭合--包含大小写--low"); + start(); + }, 50); + }, 50); + stop(); +}); +test('非闭合选择----字符串包括换行跟空格', function () { + if (ua.browser.ie == 9)return;//TODO 1.2.6 + if (ua.browser.ie == 8)return;//TODO 1.2.6 PUBLICGE-3402 + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    HEllo1
    heLLO2

    '); + setTimeout(function () { + range.setStart(body.firstChild.firstChild, 0).setEnd(body.firstChild.lastChild, 6).select(); + editor.execCommand("touppercase"); + equal(editor.getContent(), "

    HELLO1
    HELLO2

    ", "非闭合--包含大小写--up"); + editor.execCommand("tolowercase"); + equal(editor.getContent(), "

    hello1
    hello2

    ", "非闭合--包含大小写--low"); + start(); + }, 50); + stop(); +}); +test('标签table', function () { + //单个单元格,多个单元格,两个表格 + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + var text = "
    hello1hello2
    hello3hello4
    "; + editor.setContent(text); + stop(); + setTimeout(function () { + var tds = body.firstChild.getElementsByTagName('td'); + range.selectNode(tds[1]).select(); + editor.execCommand("touppercase"); + equal(tds[1].innerHTML, "HELLO2", "table--up"); + editor.execCommand("tolowercase"); + equal(tds[1].innerHTML, "hello2", "table--low"); + + range.setStart(tds[1], 0).setEnd(tds[2], 1).select(); + editor.execCommand("touppercase"); + equal(tds[1].innerHTML, "HELLO2", "table--单元格2--up"); + equal(tds[2].innerHTML, "HELLO3", "table--单元格3--up"); + editor.execCommand("tolowercase"); + equal(tds[1].innerHTML, "hello2", "table--单元格2--low"); + equal(tds[2].innerHTML, "hello3", "table--单元格3--low"); + + range.setStart(tds[0], 0).setEnd(tds[3], 1).select(); + editor.execCommand("touppercase"); + equal(tds[0].innerHTML, "HELLO1", "table--单元格1--up"); + equal(tds[1].innerHTML, "HELLO2", "table--单元格2--up"); + equal(tds[2].innerHTML, "HELLO3", "table--单元格3--up"); + equal(tds[3].innerHTML, "HELLO4", "table--单元格4--up"); + editor.execCommand("tolowercase"); + equal(tds[0].innerHTML, "hello1", "table--单元格1--low"); + equal(tds[1].innerHTML, "hello2", "table--单元格2--low"); + equal(tds[2].innerHTML, "hello3", "table--单元格3--low"); + equal(tds[3].innerHTML, "hello4", "table--单元格4--low"); + start(); + }, 50); +}); + +test('标签h1', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    hello1

    hello2

    '); + range.setStart(body.firstChild.firstChild, 2).setEnd(body.lastChild.firstChild, 2).select(); + editor.execCommand("touppercase"); + equal(editor.getContent(), "

    heLLO1

    HEllo2

    ", "h1--up"); + editor.execCommand("tolowercase"); + equal(editor.getContent(), "

    hello1

    hello2

    ", "h1--low"); +}); + +test('h1&table', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + var text = "

    hello

    hello1hello2
    hello3hello4
    "; + editor.setContent(text); + stop(); + setTimeout(function () { + range.setStart(body.firstChild.firstChild, 0).setEnd(body.lastChild.firstChild.lastChild.lastChild.firstChild, 6).select(); + var tds = body.lastChild.getElementsByTagName('td'); + editor.execCommand("touppercase"); + ok(body.firstChild.tagName == "h1" || body.firstChild.tagName == "H1", "h1标签"); + equal(body.firstChild.innerHTML, "HELLO", "h1--up"); + equal(tds[0].innerHTML, "HELLO1", "table--单元格1--up"); + equal(tds[1].innerHTML, "HELLO2", "table--单元格2--up"); + equal(tds[2].innerHTML, "HELLO3", "table--单元格3--up"); + equal(tds[3].innerHTML, "HELLO4", "table--单元格4--up"); + editor.execCommand("tolowercase"); + ok(body.firstChild.tagName == "h1" || body.firstChild.tagName == "H1", "h1标签"); + equal(body.firstChild.innerHTML, "hello", "h1--low"); + equal(tds[0].innerHTML, "hello1", "table--单元格1--low"); + equal(tds[1].innerHTML, "hello2", "table--单元格2--low"); + equal(tds[2].innerHTML, "hello3", "table--单元格3--low"); + equal(tds[3].innerHTML, "hello4", "table--单元格4--low"); + start(); + }, 50); +}); + +test('三个组合', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + var text = "

    hello

    hello1hello2
    hello3hello4

    hello

    "; + editor.setContent(text); + var tds = body.firstChild.nextSibling.getElementsByTagName('td'); + range.setStart(body.firstChild.firstChild, 2).setEnd(body.lastChild.firstChild, 2).select(); + editor.execCommand("touppercase"); + ok(body.firstChild.tagName == "p" || body.firstChild.tagName == "P", "p标签"); + equal(body.firstChild.innerHTML, "heLLO", "p--up"); + equal(tds[0].innerHTML, "HELLO1", "table--单元格1--up"); + equal(tds[1].innerHTML, "HELLO2", "table--单元格2--up"); + equal(tds[2].innerHTML, "HELLO3", "table--单元格3--up"); + equal(tds[3].innerHTML, "HELLO4", "table--单元格4--up"); + ok(body.lastChild.tagName == "h1" || body.lastChild.tagName == "H1", "h1标签"); + equal(body.lastChild.innerHTML, "HEllo", "h1--up"); + editor.execCommand("tolowercase"); + ok(body.firstChild.tagName == "p" || body.firstChild.tagName == "P", "p标签"); + equal(body.firstChild.innerHTML, "hello", "p--low"); + equal(tds[0].innerHTML, "hello1", "table--单元格1--low"); + equal(tds[1].innerHTML, "hello2", "table--单元格2--low"); + equal(tds[2].innerHTML, "hello3", "table--单元格3--low"); + equal(tds[3].innerHTML, "hello4", "table--单元格4--low"); + ok(body.lastChild.tagName == "h1" || body.lastChild.tagName == "H1", "h1标签"); + equal(body.lastChild.innerHTML, "hello", "h1--low"); +}); + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/copy.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/copy.js new file mode 100644 index 000000000..eded27dc8 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/copy.js @@ -0,0 +1,50 @@ +module('plugins.copy'); + +//需要点击授权弹出框,暂时去除 +//test('检查IE下复制命令是否执行正常', function () { +// +// if (browser.ie) { +// var editor = te.obj[0]; +// editor.setContent('

    hello

    '); +// editor.focus(); +// +// editor.execCommand('selectall'); +// editor.execCommand('copy'); +// editor.body.innerHTML = ''; +// editor.execCommand('selectall'); +// editor.body.document.execCommand('paste'); +// +// equal(utils.trim(window.clipboardData.getData('text')), 'hello', '检查粘贴板内容,IE下成功复制内容'); +// setTimeout(function(){ +// equal(editor.getContent(), '

    hello

    ', '检查原生粘贴命令,IE下成功复制内容'); +// start(); +// },100); +// +// stop(); +// } +// +//}); + +test('检查非IE下是否正常加载zeroclipboard粘贴板插件', function () { + te.dom[0].parentNode.removeChild(te.dom[0]); + var sc = document.createElement("script"); + sc.id="sc"; + sc.type = "text/plain"; + sc.style.height = "100px"; + document.body.appendChild(sc); + var me = UE.getEditor('sc',{'autoFloatEnabled':true,'topOffset':60,'autoHeightEnabled':true,'scaleEnabled':false}); + me.ready(function(){ + setTimeout(function(){ + if (!browser.ie) { + ok(window.ZeroClipboard, '是否正常加载zeroclipboard粘贴板插件'); + } + setTimeout(function () { + UE.delEditor('sc'); + document.getElementById('sc')&&document.getElementById('sc').parentNode.removeChild(document.getElementById('sc')); + start(); + }, 500); + }, 300); + }); + stop(); + +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/customstyle.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/customstyle.js new file mode 100644 index 000000000..c8bc6852c --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/customstyle.js @@ -0,0 +1,451 @@ +/** + * + */ +module( 'plugins.customstyle' ); + +test( 'block的元素(p)', function () { + var editor = te.obj[0]; + editor.setContent('

    hello

    '); + setTimeout(function () { + var range = editor.selection.getRange(); + range.selectNode(editor.body.firstChild).select();//非闭合选区 + + editor.execCommand('customstyle', { + style:'border:1px solid #ccc', + label:'aaa', + tag:'h3' + }); + ua.manualDeleteFillData(editor.body); + equal(editor.body.firstChild.getAttribute('label'), 'aaa', '检查标签'); + range.selectNode(editor.body.firstChild).select(); + equal(editor.queryCommandValue('customstyle'), 'aaa', 'queryCommandValue'); + equal(editor.queryCommandState('customstyle'), '0', 'queryCommandState'); + var hStyle = $(editor.body.firstChild); + ok(editor.body.firstChild.style.borderWidth == '1px', '检查边框宽'); + ok(hStyle.css('border-top-style') == 'solid' && hStyle.css('border-bottom-style') == 'solid' && hStyle.css('border-left-style') == 'solid' && hStyle.css('border-right-style') == 'solid', '检查边框风格'); + if (ua.browser.ie && ua.browser.ie < 9) + ok(hStyle.css('border-top-color') == '#ccc' && hStyle.css('border-bottom-color') == '#ccc' && hStyle.css('border-left-color') == '#ccc' && hStyle.css('border-right-color') == '#ccc', '检查边框颜色'); + else + ok(hStyle.css('border-top-color') == 'rgb(204, 204, 204)' && hStyle.css('border-bottom-color') == 'rgb(204, 204, 204)' && hStyle.css('border-left-color') == 'rgb(204, 204, 204)' && hStyle.css('border-right-color') == 'rgb(204, 204, 204)', '检查边框颜色'); + range.setStart(editor.body.firstChild, 0).collapse(true).select();//闭合选区 + editor.execCommand('customstyle', { + style:'border:1px solid #ccc', + label:'aaa', + tag:'h3' + }); + ua.manualDeleteFillData(editor.body); + range.selectNode(editor.body.firstChild).select(); + equal(editor.queryCommandValue('customstyle'), ''); + equal(editor.queryCommandState('customstyle'), '0', 'queryCommandState'); + /*trace 1732*/ + var p = editor.body.firstChild; + equal(p.tagName.toLowerCase(), 'p', '闭合去掉h3标签'); + equal(p.innerHTML, 'hello', '检查innerHTML'); + + editor.setContent('

    hello


    '); + range.selectNode(editor.body.firstChild).select(); + editor.execCommand('customstyle', { + style:'border:1px solid #ccc', + label:'aaa', + tag:'h3' + }); + var p = editor.body.firstChild; + equal(p.tagName.toLowerCase(), 'p', '非闭合去掉h3标签'); + start(); + }, 50); + stop(); +} ); +test( 'block的元素(div)', function () { + var editor = te.obj[0]; + editor.setContent( '
    hello
    ' ); + setTimeout(function(){ + var range = editor.selection.getRange(); + range.selectNode( editor.body.firstChild ).select();//非闭合选区 + editor.execCommand( 'customstyle', { + style:'border:1px solid #ccc', + label:'aaa', + tag:'h3' + } ); + ua.manualDeleteFillData( editor.body ); + equal( editor.body.firstChild.getAttribute( 'label' ), 'aaa', '检查标签' ); + var hStyle = $( editor.body.firstChild ); + ok( editor.body.firstChild.style.borderWidth=='1px', '检查边框宽' ); + ok( hStyle.css( 'border-top-style' ) == 'solid' && hStyle.css( 'border-bottom-style' ) == 'solid' && hStyle.css( 'border-left-style' ) == 'solid' && hStyle.css( 'border-right-style' ) == 'solid', '检查边框风格' ); + if ( ua.browser.ie&&ua.browser.ie<9 ) + ok( hStyle.css( 'border-top-color' ) == '#ccc' && hStyle.css( 'border-bottom-color' ) == '#ccc' && hStyle.css( 'border-left-color' ) == '#ccc' && hStyle.css( 'border-right-color' ) == '#ccc', '检查边框颜色' ); + else + ok( hStyle.css( 'border-top-color' ) == 'rgb(204, 204, 204)' && hStyle.css( 'border-bottom-color' ) == 'rgb(204, 204, 204)' && hStyle.css( 'border-left-color' ) == 'rgb(204, 204, 204)' && hStyle.css( 'border-right-color' ) == 'rgb(204, 204, 204)', '检查边框颜色' ); + range.setStart(editor.body.firstChild,0).collapse(true).select();//闭合选区 + editor.execCommand( 'customstyle', { + style:'border:1px solid #ccc', + label:'aaa', + tag:'h3' + } ); + ua.manualDeleteFillData( editor.body ); + /*trace 1732*/ + var p = editor.body.firstChild; + equal( p.tagName.toLowerCase(), 'p', 'h3被去掉了' ); + equal( p.innerHTML, 'hello', '检查innerHTML' ); + start(); +},50); +stop(); +} ); + +test( 'inline的元素(a)', function () { + var editor = te.obj[0]; + editor.setContent( 'hello' ); + var range = editor.selection.getRange(); + range.selectNode( editor.body.firstChild ).select();//非闭合选区 + + editor.execCommand( 'customstyle', { + style:'border:1px solid #ccc', + label:'aaa', + tag:'h3' + } ); + range.selectNode( editor.body.firstChild ).select(); + equal(editor.queryCommandValue('customstyle'),'aaa','queryCommandValue'); + equal(editor.queryCommandState('customstyle'),'0','queryCommandState'); + ua.manualDeleteFillData( editor.body ); + equal( editor.body.firstChild.getAttribute( 'label' ), 'aaa', '检查标签' ); + var hStyle = $( editor.body.firstChild ); + ok( editor.body.firstChild.style.borderWidth=='1px', '检查边框宽' ); + ok( hStyle.css( 'border-top-style' ) == 'solid' && hStyle.css( 'border-bottom-style' ) == 'solid' && hStyle.css( 'border-left-style' ) == 'solid' && hStyle.css( 'border-right-style' ) == 'solid', '检查边框风格' ); + if (ua.browser.ie&&ua.browser.ie<9 ) + ok( hStyle.css( 'border-top-color' ) == '#ccc' && hStyle.css( 'border-bottom-color' ) == '#ccc' && hStyle.css( 'border-left-color' ) == '#ccc' && hStyle.css( 'border-right-color' ) == '#ccc', '检查边框颜色' ); + else + ok( hStyle.css( 'border-top-color' ) == 'rgb(204, 204, 204)' && hStyle.css( 'border-bottom-color' ) == 'rgb(204, 204, 204)' && hStyle.css( 'border-left-color' ) == 'rgb(204, 204, 204)' && hStyle.css( 'border-right-color' ) == 'rgb(204, 204, 204)', '检查边框颜色' ); + range.setStart(editor.body.firstChild,0).collapse(true).select();//闭合选区 + editor.execCommand( 'customstyle', { + style:'border:1px solid #ccc', + label:'aaa', + tag:'h3' + } ); + ua.manualDeleteFillData( editor.body ); + /*trace 1732*/ + var a = editor.body.getElementsByTagName('a')[0]; + equal( a.tagName.toLowerCase(), 'a', 'h3被去掉了' ); + equal( a.innerHTML, 'hello', '检查innerHTML' ); + range.selectNode( editor.body.firstChild ).select(); + equal(editor.queryCommandValue('customstyle'),'','queryCommandValue'); + equal(editor.queryCommandState('customstyle'),'0','queryCommandState'); +} ); +//h 与span标签作为选区的情况,在下的用例中自然使用到 +test( 'block的元素-样式的反复转换:块-块;包含的选取方式:整段、部分、多段', function () { + var editor = te.obj[0]; + editor.setContent( '

    hello

    world

    ' ); + var range = editor.selection.getRange(); + range.setStart(editor.body.firstChild.firstChild,0).setEnd(editor.body.firstChild.firstChild,2).select();//非闭合选区,部分 + editor.execCommand( 'customstyle', { + style:'border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;margin:0 0 20px 0;', + label:'居中标题', + tag:'h1' + } ); + ua.manualDeleteFillData( editor.body ); + equal( editor.body.getElementsByTagName('h1')[0].getAttribute( 'label' ), '居中标题', '非闭合选区,部分选择,设置块元素的样式:居中标题' ); + var hStyle = $( editor.body.getElementsByTagName('h1')[0]); + ok( editor.body.getElementsByTagName('h1')[0].style.borderBottomWidth == '2px' , '检查边框宽' ); + ok( hStyle.css( 'border-bottom-style' ) == 'solid' , '检查边框风格' ); + ok( hStyle.css( 'padding-bottom' ) == '0px'&&hStyle.css( 'padding-top' ) == '0px'&&hStyle.css( 'padding-left' ) == '0px'&&hStyle.css( 'padding-right' ) == '4px' , '检查padding' ); + ok( hStyle.css( 'margin-bottom' ) == '20px'&&hStyle.css( 'margin-top' ) == '0px'&&hStyle.css( 'margin-left' ) == '0px'&&hStyle.css( 'margin-right' ) == '0px' , '检查margin' ); + ok( hStyle.css( 'text-align' ) == 'center' , '检查对齐方式' ); + if ( ua.browser.ie&&ua.browser.ie<9 ) + ok( hStyle.css( 'border-bottom-color' ) == '#ccc' , '检查边框颜色' ); + else + ok( hStyle.css( 'border-bottom-color' ) == 'rgb(204, 204, 204)' , '检查边框颜色' ); + range.setStart(editor.body.getElementsByTagName('h1')[0],0).collapse(true).select();//闭合选区 + editor.execCommand( 'customstyle', { + tag:'h1', + label:'居左标题', + style:'border-bottom:#ccc 2px solid;padding:0 4px 0 0;margin:0 0 10px 0;' + } ); + ua.manualDeleteFillData( editor.body ); + equal( editor.body.getElementsByTagName('h1')[0].getAttribute( 'label' ), '居左标题', '闭合选区设置块元素的样式:居左标题' ); + var hStyle = $(editor.body.getElementsByTagName('h1')[0]); + ok( editor.body.getElementsByTagName('h1')[0].style.borderBottomWidth == '2px' , '检查边框宽' ); + ok( hStyle.css( 'border-bottom-style' ) == 'solid' , '检查边框风格' ); + ok( hStyle.css( 'padding-bottom' ) == '0px'&&hStyle.css( 'padding-top' ) == '0px'&&hStyle.css( 'padding-left' ) == '0px'&&hStyle.css( 'padding-right' ) == '4px' , '检查padding' ); + ok( hStyle.css( 'margin-bottom' ) == '10px'&&hStyle.css( 'margin-top' ) == '0px'&&hStyle.css( 'margin-left' ) == '0px'&&hStyle.css( 'margin-right' ) == '0px' , '检查margin' ); + ok( hStyle.css( 'text-align' ) != 'center' , '检查对齐方式' ); + if (ua.browser.ie&&ua.browser.ie<9 ) + ok( hStyle.css( 'border-bottom-color' ) == '#ccc' , '检查边框颜色' ); + else + ok( hStyle.css( 'border-bottom-color' ) == 'rgb(204, 204, 204)' , '检查边框颜色' ); + range.setStart(editor.body.firstChild,0).setEnd(editor.body.lastChild,1).select();//非闭合选区,多段 + editor.execCommand( 'customstyle', { + tag:'h3', + label:'标题3', + style:'border-bottom:#ccc 1px solid;padding:0 1px 0 0;margin:0 0 10px 0;' + } ); + ua.manualDeleteFillData( editor.body ); + ok(editor.body.getElementsByTagName('h1').length==0&&editor.body.getElementsByTagName('h3').length==2,'选中两行(中间夹一行空行),设置成标题3'); + equal( editor.body.getElementsByTagName('h3')[0].getAttribute( 'label' ), '标题3', '标题3' ); + var hStyle = $( editor.body.getElementsByTagName('h3')[0]); + ok( editor.body.getElementsByTagName('h3')[0].style.borderBottomWidth == '1px' , '检查边框宽' ); + ok( hStyle.css( 'border-bottom-style' ) == 'solid' , '检查边框风格' ); + ok( hStyle.css( 'padding-bottom' ) == '0px'&&hStyle.css( 'padding-top' ) == '0px'&&hStyle.css( 'padding-left' ) == '0px'&&hStyle.css( 'padding-right' ) == '1px' , '检查padding' ); + ok( hStyle.css( 'margin-bottom' ) == '10px'&&hStyle.css( 'margin-top' ) == '0px'&&hStyle.css( 'margin-left' ) == '0px'&&hStyle.css( 'margin-right' ) == '0px' , '检查margin' ); + if ( ua.browser.ie&&ua.browser.ie<9 ) + ok( hStyle.css( 'border-bottom-color' ) == '#ccc' , '检查边框颜色' ); + else + ok( hStyle.css( 'border-bottom-color' ) == 'rgb(204, 204, 204)' , '检查边框颜色' ); + equal( editor.body.getElementsByTagName('h3')[1].getAttribute( 'label' ), '标题3', '标题3' ); + var hStyle = $( editor.body.getElementsByTagName('h3')[1] ); + ok( editor.body.getElementsByTagName('h3')[1].style.borderBottomWidth == '1px' , '检查边框宽' ); + ok( hStyle.css( 'border-bottom-style' ) == 'solid' , '检查边框风格' ); + ok( hStyle.css( 'padding-bottom' ) == '0px'&&hStyle.css( 'padding-top' ) == '0px'&&hStyle.css( 'padding-left' ) == '0px'&&hStyle.css( 'padding-right' ) == '1px' , '检查padding' ); + ok( hStyle.css( 'margin-bottom' ) == '10px'&&hStyle.css( 'margin-top' ) == '0px'&&hStyle.css( 'margin-left' ) == '0px'&&hStyle.css( 'margin-right' ) == '0px' , '检查margin' ); + if ( ua.browser.ie&&ua.browser.ie<9 ) + ok( hStyle.css( 'border-bottom-color' ) == '#ccc' , '检查边框颜色' ); + else + ok( hStyle.css( 'border-bottom-color' ) == 'rgb(204, 204, 204)' , '检查边框颜色' ); +}); +test( 'block的元素-样式的反复转换:块-块;包含的选取方式: 多段部分', function () { + var editor = te.obj[0]; + var range = editor.selection.getRange(); + editor.setContent( '

    hello

    world

    !!!

    ' ); + range.setStart(editor.body.firstChild.firstChild,2).setEnd(editor.body.lastChild.firstChild,1).select();//非闭合选区,多段部分 + editor.execCommand( 'customstyle', { + tag:'h1', + label:'标题1', + style:'border-bottom:#ccc 1px solid;padding:0 3px 0 0;margin:10px 0 10px 0;' + } ); + ua.manualDeleteFillData( editor.body ); + ok(editor.body.getElementsByTagName('h1').length==3,'选中多行的部分,设置成标题1'); + equal( editor.body.getElementsByTagName('h1')[0].getAttribute( 'label' ), '标题1', '标题1' ); + var hStyle = $( editor.body.getElementsByTagName('h1')[0] ); + ok( editor.body.getElementsByTagName('h1')[0].style.borderBottomWidth == '1px' , '检查边框宽' ); + ok( hStyle.css( 'border-bottom-style' ) == 'solid' , '检查边框风格' ); + ok( hStyle.css( 'padding-bottom' ) == '0px'&&hStyle.css( 'padding-top' ) == '0px'&&hStyle.css( 'padding-left' ) == '0px'&&hStyle.css( 'padding-right' ) == '3px' , '检查padding' ); + ok( hStyle.css( 'margin-bottom' ) == '10px'&&hStyle.css( 'margin-top' ) == '10px'&&hStyle.css( 'margin-left' ) == '0px'&&hStyle.css( 'margin-right' ) == '0px' , '检查margin' ); + if ( ua.browser.ie&&ua.browser.ie<9 ) + ok( hStyle.css( 'border-bottom-color' ) == '#ccc' , '检查边框颜色' ); + else + ok( hStyle.css( 'border-bottom-color' ) == 'rgb(204, 204, 204)' , '检查边框颜色' ); + equal( editor.body.getElementsByTagName('h1')[1].getAttribute( 'label' ), '标题1', '标题1' ); + var hStyle = $( editor.body.getElementsByTagName('h1')[1] ); + ok( editor.body.getElementsByTagName('h1')[1].style.borderBottomWidth == '1px' , '检查边框宽' ); + ok( hStyle.css( 'border-bottom-style' ) == 'solid' , '检查边框风格' ); + ok( hStyle.css( 'padding-bottom' ) == '0px'&&hStyle.css( 'padding-top' ) == '0px'&&hStyle.css( 'padding-left' ) == '0px'&&hStyle.css( 'padding-right' ) == '3px' , '检查padding' ); + ok( hStyle.css( 'margin-bottom' ) == '10px'&&hStyle.css( 'margin-top' ) == '10px'&&hStyle.css( 'margin-left' ) == '0px'&&hStyle.css( 'margin-right' ) == '0px' , '检查margin' ); + if ( ua.browser.ie&&ua.browser.ie<9 ) + ok( hStyle.css( 'border-bottom-color' ) == '#ccc' , '检查边框颜色' ); + else + ok( hStyle.css( 'border-bottom-color' ) == 'rgb(204, 204, 204)' , '检查边框颜色' ); + equal( editor.body.getElementsByTagName('h1')[2].getAttribute( 'label' ), '标题1', '标题1' ); + var hStyle = $( editor.body.getElementsByTagName('h1')[2] ); + ok( editor.body.getElementsByTagName('h1')[2].style.borderBottomWidth == '1px' , '检查边框宽' ); + ok( hStyle.css( 'border-bottom-style' ) == 'solid' , '检查边框风格' ); + ok( hStyle.css( 'padding-bottom' ) == '0px'&&hStyle.css( 'padding-top' ) == '0px'&&hStyle.css( 'padding-left' ) == '0px'&&hStyle.css( 'padding-right' ) == '3px' , '检查padding' ); + ok( hStyle.css( 'margin-bottom' ) == '10px'&&hStyle.css( 'margin-top' ) == '10px'&&hStyle.css( 'margin-left' ) == '0px'&&hStyle.css( 'margin-right' ) == '0px' , '检查margin' ); + if ( ua.browser.ie&&ua.browser.ie<9 ) + ok( hStyle.css( 'border-bottom-color' ) == '#ccc' , '检查边框颜色' ); + else + ok( hStyle.css( 'border-bottom-color' ) == 'rgb(204, 204, 204)' , '检查边框颜色' ); + +} ); +test( 'block的元素-样式的反复转换:块-内联;包含的选取方式:闭合、多段部分', function () { + var editor = te.obj[0]; + editor.setContent( '

    hello

    world

    ' ); + var range = editor.selection.getRange(); + range.setStart(editor.body.firstChild,0).setEnd(editor.body.lastChild,1).select();//现设块样式 + editor.execCommand( 'customstyle', { + style:'border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;margin:0 0 20px 0;', + label:'居中标题', + tag:'h1' + } ); + range.setStart(editor.body.getElementsByTagName('h1')[0],0).collapse(true).select();//闭合选区 + editor.execCommand( 'customstyle', { + tag:'span', + label:'强调', + style:'font-style:italic;font-weight:bold;color:#000' + } ); + ua.manualDeleteFillData( editor.body ); + equal( editor.body.getElementsByTagName('span')[0].getAttribute( 'label' ), '强调', '闭合选区设置样式:强调' ); + var hStyle = $( editor.body.getElementsByTagName('span')[0] ); + if ( ua.browser.webkit ) + ok( hStyle.css( 'font-style' ) == 'italic'&&hStyle.css( 'font-weight' ) == 'bold' , '检查字体' ); + else + ok( hStyle.css( 'font-style' ) == 'italic'&&hStyle.css( 'font-weight' ) == '700' , '检查字体' ); + if(ua.browser.ie&&ua.browser.ie<9) + equal( hStyle.css( 'color' ) , '#000' , '检查颜色' ); + else + equal( hStyle.css( 'color' ) ,'rgb(0, 0, 0)' , '检查颜色' ); + range.setStart(editor.body.getElementsByTagName('h1')[0].lastChild,0).setEnd(editor.body.getElementsByTagName('h1')[1].firstChild,2).select();//多段部分 + editor.execCommand( 'customstyle', { + tag:'span', + label:'明显强调', + style:'font-style:italic;font-weight:bold;color:rgb(51, 153, 204)' + } ); + ua.manualDeleteFillData( editor.body ); + equal( editor.body.getElementsByTagName('h1')[1].firstChild.getAttribute( 'label' ), '明显强调', '闭合选区设置样式:明显强调' ); + var hStyle = $( editor.body.getElementsByTagName('h1')[1].firstChild ); + if ( ua.browser.webkit ) + ok( hStyle.css( 'font-style' ) == 'italic'&&hStyle.css( 'font-weight' ) == 'bold' , '检查字体' ); + else + ok( hStyle.css( 'font-style' ) == 'italic'&&hStyle.css( 'font-weight' ) == '700' , '检查字体' ); + if(ua.browser.ie&&ua.browser.ie<9) + equal( hStyle.css( 'color' ) , 'rgb(51,153,204)', '检查颜色' ); + else + equal( hStyle.css( 'color' ) ,'rgb(51, 153, 204)' , '检查颜色' ); +} ); +test( 'block的元素-样式的反复转换:内联-块;包含的选取方式:闭合', function () { //从内联-块的转换意义不大,其实还是针对块的转换,就不做多种方式选取了 + var editor = te.obj[0]; + editor.setContent( '

    hello

    ' ); + var range = editor.selection.getRange(); + range.setStart(editor.body.firstChild,0).setEnd(editor.body.firstChild,1).select(); + editor.execCommand( 'customstyle', { + tag:'span', + label:'强调', + style:'font-style:italic;font-weight:bold;color:#000' + } ); + range.setStart(editor.body.firstChild,0).collapse(true).select(); + editor.execCommand( 'customstyle', { + style:'border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;margin:0 0 20px 0;', + label:'居中标题', + tag:'h1' + } ); + ua.manualDeleteFillData( editor.body ); + equal( editor.body.getElementsByTagName('h1')[0].getAttribute( 'label' ), '居中标题', '居中标题' ); + var hStyle = $( editor.body.getElementsByTagName('h1')[0] ); + ok( editor.body.getElementsByTagName('h1')[0].style.borderBottomWidth == '2px' , '检查边框宽' ); + ok( hStyle.css( 'border-bottom-style' ) == 'solid' , '检查边框风格' ); + ok( hStyle.css( 'padding-bottom' ) == '0px'&&hStyle.css( 'padding-top' ) == '0px'&&hStyle.css( 'padding-left' ) == '0px'&&hStyle.css( 'padding-right' ) == '4px' , '检查padding' ); + ok( hStyle.css( 'margin-bottom' ) == '20px'&&hStyle.css( 'margin-top' ) == '0px'&&hStyle.css( 'margin-left' ) == '0px'&&hStyle.css( 'margin-right' ) == '0px' , '检查margin' ); + if ( ua.browser.ie&&ua.browser.ie<9 ) + ok( hStyle.css( 'border-bottom-color' ) == '#ccc' , '检查边框颜色' ); + else + ok( hStyle.css( 'border-bottom-color' ) == 'rgb(204, 204, 204)' , '检查边框颜色' ); + if(!editor.body.getElementsByTagName('h1')[0].firstChild.data ){return;} + equal( editor.body.getElementsByTagName('h1')[0].firstChild.tagName.toLowerCase(),'span','h1内包含样式:强调'); + equal( editor.body.getElementsByTagName('h1')[0].firstChild.getAttribute( 'label' ), '强调', '闭合选区设置样式:强调' ); + var hStyle = $( editor.body.getElementsByTagName('span')[0] ); + if ( ua.browser.webkit ) + ok( hStyle.css( 'font-style' ) == 'italic'&&hStyle.css( 'font-weight' ) == 'bold' , '检查字体' ); + else + ok( hStyle.css( 'font-style' ) == 'italic'&&hStyle.css( 'font-weight' ) == '700' , '检查字体' ); + if(ua.browser.ie&&ua.browser.ie<9) + equal( hStyle.css( 'color' ) , '#000' , '检查颜色' ); + else + equal( hStyle.css( 'color' ) ,'rgb(0, 0, 0)' , '检查颜色' ); +} ); +test( 'block的元素-样式的反复转换:内联-内联;包含的选取方式:闭合,非闭合,多段', function () { + var div = document.body.appendChild( document.createElement( 'div' ) ); + var editor = new baidu.editor.Editor({'initialContent':'

    欢迎使用ueditor

    ','elementPathEnabled' : true,'autoFloatEnabled':false}); + + stop(); + setTimeout(function(){ + editor.render( div ); + setTimeout(function(){ + editor.setContent( '

    hello

    world

    ' ); + var range = editor.selection.getRange(); + range.setStart(editor.body.firstChild,0).setEnd(editor.body.firstChild,1).select(); + editor.execCommand( 'customstyle', { + tag:'span', + label:'强调', + style:'font-style:italic;font-weight:bold;color:#000' + } ); + equal( editor.body.getElementsByTagName('p')[0].firstChild.tagName.toLowerCase(), 'span', '闭合选区设置样式:强调' ); + equal( editor.body.getElementsByTagName('p')[0].firstChild.getAttribute( 'label' ), '强调', '闭合选区设置样式:强调' ); + var hStyle = $( editor.body.getElementsByTagName('span')[0] ); + if ( ua.browser.webkit ) + ok( hStyle.css( 'font-style' ) == 'italic'&&hStyle.css( 'font-weight' ) == 'bold' , '检查字体' ); + else + ok( hStyle.css( 'font-style' ) == 'italic'&&hStyle.css( 'font-weight' ) == '700' , '检查字体' ); + if(ua.browser.ie&&ua.browser.ie<9) + equal( hStyle.css( 'color' ) , '#000' , '检查颜色' ); + else + equal( hStyle.css( 'color' ) ,'rgb(0, 0, 0)' , '检查颜色' ); + range.setStart(editor.body.firstChild.firstChild.firstChild,0).setEnd(editor.body.lastChild.firstChild,3).select(); + editor.execCommand( 'customstyle', { + tag:'span', + label:'明显强调', + style:'font-style:italic;font-weight:bold;color:rgb(51, 153, 204)' + } ); + range.selectNode(editor.body.firstChild).select(); + var eles = editor.queryCommandValue( 'elementpath' ); + ua.checkElementPath( eles, ['body', 'p', 'span', 'span'], '选中第一行' ); + var span2 = editor.body.getElementsByTagName('p')[0].firstChild.firstChild; + var hStyle = $( span2 ); + equal( span2.tagName.toLowerCase(), 'span', '非闭合选区设置样式:明显强调' ); + equal(span2.getAttribute( 'label' ), '明显强调', '非闭合选区设置样式:明显强调' ); + if ( ua.browser.webkit ) + ok( hStyle.css( 'font-style' ) == 'italic'&&hStyle.css( 'font-weight' ) == 'bold' , '检查字体' ); + else + ok( hStyle.css( 'font-style' ) == 'italic'&&hStyle.css( 'font-weight' ) == '700' , '检查字体' ); + if(ua.browser.ie&&ua.browser.ie<9) + equal( hStyle.css( 'color' ) , 'rgb(51,153,204)' , '检查颜色' ); + else + equal( hStyle.css( 'color' ) ,'rgb(51, 153, 204)', '检查颜色' ); + var span3 = editor.body.getElementsByTagName('p')[1].firstChild; + var hStyle = $( span3 ); + equal( span3.tagName.toLowerCase(), 'span', '非闭合选区设置样式:明显强调' ); + equal(span3.getAttribute( 'label' ), '明显强调', '非闭合选区设置样式:明显强调' ); + if ( ua.browser.webkit ) + ok( hStyle.css( 'font-style' ) == 'italic'&&hStyle.css( 'font-weight' ) == 'bold' , '检查字体' ); + else + ok( hStyle.css( 'font-style' ) == 'italic'&&hStyle.css( 'font-weight' ) == '700' , '检查字体' ); + if(ua.browser.ie&&ua.browser.ie<9) + equal( hStyle.css( 'color' ) ,'rgb(51,153,204)', '检查颜色' ); + else + equal( hStyle.css( 'color' ) ,'rgb(51, 153, 204)', '检查颜色' ); + range.setStart(span2.firstChild,0).collapse(true).select(); + editor.execCommand( 'customstyle', { + tag:'span', + label:'强调', + style:'font-style:italic;font-weight:bold;color:#000' + } ); + equal( span2.firstChild.tagName.toLowerCase(), 'span', '非闭合选区设置样式:强调' ); + equal( span2.firstChild.getAttribute( 'label' ), '强调', '闭合选区设置样式:强调' ); + var hStyle = $( span2.firstChild ); + if ( ua.browser.webkit ) + ok( hStyle.css( 'font-style' ) == 'italic'&&hStyle.css( 'font-weight' ) == 'bold' , '检查字体' ); + else + ok( hStyle.css( 'font-style' ) == 'italic'&&hStyle.css( 'font-weight' ) == '700' , '检查字体' ); + if(ua.browser.ie&&ua.browser.ie<9) + equal( hStyle.css( 'color' ) ,'#000', '检查颜色' ); + else + equal( hStyle.css( 'color' ) ,'rgb(0, 0, 0)', '检查颜色' ); + start(); + },50); +},50); + +} ); + +test('h1空节点',function(){ + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild,0).collapse(1).select(); + editor.execCommand('customstyle',{tag:'h1', label:'居中标题', style:'border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;margin:0 0 20px 0;'}); + ua.manualDeleteFillData(editor.body); + equal(editor.body.firstChild.tagName,'H1','h1标签'); + equal($(editor.body.firstChild).css('textAlign'),'center','居中'); + range.setStart(editor.body.firstChild.firstChild,0).collapse(1).select(); + ua.keyup(editor.body,{keyCode:32}); + var br = ua.browser.ie?' ':'
    '; +// 无法模拟空格 +// equal(ua.getChildHTML(editor.body),'

    '+br+'

    ','h1空节点点击空格键'); + + editor.execCommand('customstyle',{tag:'h1', label:'居中标题', style:'border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;margin:0 0 20px 0;'}); + range.setStart(editor.body.firstChild,0).collapse(1).select(); + ua.keyup(editor.body,{keyCode:13}); + ua.manualDeleteFillData(editor.body); + equal(ua.getChildHTML(editor.body),'

    '+br+'

    ','h1空节点点击回车键'); +}); + +test('trace 1840:单击后插入“居中标题”',function(){ + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    ' ); + range.setStart(body.firstChild,0).select(); + editor.execCommand('customstyle',{tag:'h1', label:'居中标题', style:'border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;margin:0 0 20px 0;'}); + equal(body.firstChild.tagName.toLowerCase(),'h1','检查tagname'); + var childs = body.firstChild.childNodes; + var count = 0; + for(var index=0;index
    1
    2
    '); +// var br = ua.browser.ie?'':'
    '; + var html = '
    1
    2
    '; + ua.checkSameHtml(editor.body.innerHTML,html,'table补全,对代码的行号不处理') +} ); +test( '空td,th,caption', function () { + var editor = te.obj[0]; + editor.setContent( '
    ' ); + var br = ua.browser.ie&&ua.browser.ie<11?'':'
    '; + var html = '
    '+br+'
    '+br+''+br+'
    '+br+''+br+'
    '+br+''+br+'
    '; + ua.checkSameHtml(editor.body.innerHTML,html,'空td,th,caption,添加text') +} ); +test( '转换a标签', function () { + var editor = te.obj[0]; + editor.setContent( '' ); + var br = ua.browser.ie?' ':'
    '; + var html = '

    '; + ua.checkSameHtml(html,editor.body.innerHTML,'转换a标签'); +} ); +test( '转换img标签', function () { + var editor = te.obj[0]; + editor.setContent( '' ); +// var html = '

    '; + equal(editor.body.getElementsByTagName('img')[0].getAttribute('_src'),"http://www.baidu.com/img/shouye_b5486898c692066bd2cbaeda86d74448.gif"); +} ); +test( '删span中的white-space标签', function () { + if(ua.browser.webkit){ + var editor = te.obj[0]; + editor.setContent( 'sadfsadf' ); + var html = '

    sadfsadf

    '; + ua.checkSameHtml(html,editor.body.innerHTML,'删span中的white-space标签'); + } +} ); +//TODO 1.2.6 +//test( '删p中的margin|padding标签', function () { +// var editor = te.obj[0]; +// editor.setContent( '

    hello

    ' ); +// var html = '

    hello

    '; +// ua.checkSameHtml(html,editor.body.innerHTML,'删p中的margin|padding标签'); +//} ); +test( '给空p加br&&转对齐样式', function () { + var editor = te.obj[0]; + editor.setContent( '

    ' ); + var br = ua.browser.ie?' ':'
    '; +// "


    " + var html = '

    '+br+'

    '; + ua.checkSameHtml(editor.body.innerHTML,html, '给空p加br&&转对齐样式'); +} ); +test( '删div', function () { + var editor = te.obj[0]; + editor.setContent( '

    视频

    ' ); + var html = '

    视频

    '; + ua.checkSameHtml(html,editor.body.innerHTML,'删div'); +} ); +test( 'allowDivTransToP--false 不转div', function () { + var div = document.body.appendChild(document.createElement('div')); + div.id ='ue'; + var editor = UE.getEditor('ue',{allowDivTransToP:false}); + stop(); + editor.ready(function(){ + var html = '
    视频
    '; + editor.setContent( html ); + var padding = (ua.browser.ie&&ua.browser.ie<9)?'PADDING-BOTTOM: 1px; PADDING-LEFT: 1px; PADDING-RIGHT: 1px; PADDING-TOP: 1px':'padding: 1px;'; + var html_a = '
    视频
    '; + ua.checkSameHtml(html_a,editor.body.innerHTML,'不转div'); + UE.delEditor('ue'); + start(); + }); +} ); +test( 'li', function () { + var editor = te.obj[0]; + editor.setContent( '
  • ' ); + var html = ''; + ua.checkSameHtml(html,editor.body.innerHTML,'li'); +} ); +//
  • pistachio天
  • +//TODO 现在在过滤机制里面去除无用的标签 +test( "getContent--去除无用的空标签:autoClearEmptyNode==true", function() { + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor('ue',{autoClearEmptyNode:true,'autoFloatEnabled':false}); + // + stop(); + editor.ready(function () { + te.dom.push(div); + editor.focus(); + var innerHTML = 'xxem
    xxxx
    '; + editor.setContent(innerHTML); + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + equal(editor.getContent(), '

    xxem

    xxxx

    ', "span style空,套空的em和不空的em"); + //style="color:#c4bd97;" + innerHTML = 'xxem'; + editor.setContent(innerHTML); + if (ua.browser.ie>8) { + ua.checkSameHtml(editor.getContent().toLowerCase(), '

    xxem

    ', "span style不空,套空的em和不空的em"); + } + else { + ua.checkSameHtml(editor.getContent().toLowerCase(),'

    xxem

    ', "span style不空,套空的em和不空的em"); + } + innerHTML = 'xxem'; + editor.setContent(innerHTML); + /*inline标签上只要有属性就不清理*/ + if (ua.browser.ie >8) { + ua.checkSameHtml(editor.getContent().toLowerCase(), '

    xxem

    ', "span 有style但内容为空"); + } + else { + ua.checkSameHtml(editor.getContent().toLowerCase(), '

    xxem

    ', "span 有style但内容为空"); + } + innerHTML = 'asdfxxem'; + editor.setContent(innerHTML); + if (ua.browser.ie >8) { + ua.checkSameHtml(editor.getContent().toLowerCase(), '

    asdfxxem

    ', "span 有style内容不空"); + } + else { + ua.checkSameHtml(editor.getContent().toLowerCase(), '

    asdfxxem

    ', "span 有style内容不空"); + } + innerHTML = 'axxem'; + editor.setContent(innerHTML); + ua.checkSameHtml(editor.getContent(), '

    axxem

    ', "a 有href但内容为空,不过滤a标签"); + setTimeout(function () { + UE.delEditor('ue'); + start() + },300); + }, 50); + }, 50); + }); +}); + +//editor.options.autoClearEmptyNode +test("getContent--不去除无用的空标签:autoClearEmptyNode==false", function() { + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor('ue',{autoClearEmptyNode:false,'autoFloatEnabled':false}); + stop(); + editor.ready(function () { + te.dom.push(div); + editor.focus(); + var innerHTML = 'xxem'; + editor.setContent(innerHTML); + equal(editor.getContent().toLowerCase(), '

    xxem

    ', "span style空,套空的em和不空的em"); + innerHTML = 'xxem'; + editor.setContent(innerHTML); + ua.manualDeleteFillData(editor.body); + if (ua.browser.ie >8) { + ua.checkSameHtml(editor.getContent().toLowerCase(), '

    xxem

    ', "span 有style但内容为空"); + } + else { + ua.checkSameHtml(editor.getContent().toLowerCase(), '

    xxem

    ', "span 有style但内容为空"); + } + setTimeout(function () { + UE.delEditor('ue'); + start() + }, 500); + }); +}); + +test("getContent--转换空格,nbsp与空格相间显示", function() { + var editor = te.obj[0]; + editor.focus(); + //策略改变,原nbsp不做处理,类似:'

    d

    '中的空格会被过滤 + var innerHTML = '
    x x x  x    
    '; + editor.setContent(innerHTML); + equal(editor.getContent(), '

    x  x   x  x     

    ', "转换空格,nbsp与空格相间显示"); +}); +test( '转换script标签', function () { + var editor = te.obj[0]; + var br = ua.browser.ie?'

     

    ':('


    '); + editor.setContent( '' ); + var html = br+'
    '; + ua.checkSameHtml(editor.body.innerHTML,html,'转换script标签'); +} ); +test( 'trace 3698 1.3.0 版本修复: script(style)标签里面的内容不转码', function () { + var editor = te.obj[0]; + editor.setContent(''); + equal(editor.document.getElementById('myEditor').innerHTML,'','内容不保留');//1.3.6 针对ie下标签不能隐藏问题的修复 + // todo 1.3.0 trace 3698 + editor.setContent(''); + var br = ua.browser.ie?'

     

    ':('


    '); + ua.checkSameHtml(editor.getContent(),br+'','内容不转码'); +} ); +test( '转换style标签:style data不为空', function () { + var editor = te.obj[0]; + editor.setContent( '' ); + var br = ua.browser.ie?'

     

    ':('


    '); + var html = br+'
    '; + ua.checkSameHtml(editor.body.innerHTML,html,'转换script标签'); +} ); +test( '转换style标签:style data不空', function () { + var editor = te.obj[0]; + editor.setContent( '' ); + var br = ua.browser.ie?'

     

    ':('


    '); + + var html = br+'
    '; + ua.checkSameHtml(editor.body.innerHTML,html,'转换script标签'); +} ); +test( 'div出编辑器转换', function () { + var editor = te.obj[0]; + var str = '' ; + var html = '
    ueditor
    '; + editor.body.innerHTML = html; + editor.execCommand( 'source' ); + stop(); + setTimeout(function(){ + equal(editor.getContent(),str,'div出编辑器转换'); + start(); + },20); +} ); +test( 'img出编辑器转换', function () { + var editor = te.obj[0]; + var str = ua.browser.ie? '

    ':'

    ' ; + if(ua.browser.ie==8) + str ='

    '; + if(ua.browser.ie==11) + str = '

    '; + var html = '

    '; + editor.body.innerHTML = html; + editor.execCommand( 'source' ); + stop(); + setTimeout(function(){ + ua.checkSameHtml(editor.getContent(),str,'img出编辑器转换'); + start(); + },20); +} ); +//ue.setContent(''); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/directionality.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/directionality.js new file mode 100644 index 000000000..39c912972 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/directionality.js @@ -0,0 +1,149 @@ +module( "plugins.directionality" ); + +//1 notblockelement&&collapsed=false +test( '非块元素,不闭合', function() { + var editor = te.obj[0], d = editor.document, range = te.obj[1], db = editor.body; + editor.setContent('xxxxgggsiekes'); + setTimeout(function () { + range.selectNode(d.getElementsByTagName("strong")[0]).collapse(true).select(); + + equal(editor.queryCommandValue('directionality'), "ltr", "ltr queryCommandValue"); + editor.execCommand('directionality', "rtl"); + equal(ua.getChildHTML(db), "

    xxxxgggsiekes

    ", "directionrtl"); + equal(editor.queryCommandValue('directionality'), "rtl", "directionrtl queryCommandValue"); + + editor.execCommand('directionality', "ltr"); + equal(ua.getChildHTML(db), "

    xxxxgggsiekes

    ", "directionltr"); + equal(editor.queryCommandValue('directionality'), "ltr", "directionltr queryCommandValue"); + start(); + }, 20); + stop(); +} ); +//2 blockelement&&collapsed=false +test( '块元素,不闭合', function() { + var editor = te.obj[0],d = editor.document,range = te.obj[1],db = editor.body; + editor.setContent('

    gggsiekes

    '); + setTimeout(function () { + range.selectNode(d.getElementsByTagName("h1")[0]).select(); + + editor.execCommand('directionality', "ltr"); + equal(ua.getChildHTML(db), "

    gggsiekes

    ", "directionltr"); + equal(editor.queryCommandValue('directionality'), "ltr", "directionltr queryCommandValue"); + + editor.execCommand('directionality', "rtl"); + equal(ua.getChildHTML(db), "

    gggsiekes

    ", "directionrtl"); + equal(editor.queryCommandValue('directionality'), "rtl", "directionrtl queryCommandValue"); + start(); + }, 20); + stop(); +} ); + +test( '非块元素,闭合', function() { + var editor = te.obj[0], d = editor.document, range = te.obj[1], db = editor.body; + editor.setContent('gggsiekes'); + setTimeout(function () { + range.selectNode(d.getElementsByTagName("strong")[0].firstChild).collapse(true).select(); + editor.execCommand('directionality', "rtl"); + equal(ua.getChildHTML(db), "

    gggsiekes

    ", "directionrtl"); + equal(editor.queryCommandValue('directionality'), "rtl", "directionrtl queryCommandValue"); + + editor.execCommand('directionality', "ltr"); + equal(ua.getChildHTML(db), "

    gggsiekes

    ", "directionltr"); + equal(editor.queryCommandValue('directionality'), "ltr", "directionltr queryCommandValue"); + + editor.setContent('gggsiekes'); + range.selectNode(d.getElementsByTagName("strong")[0]).collapse(true).select(); + editor.execCommand('directionality', "rtl"); + equal(ua.getChildHTML(db), "

    gggsiekes

    ", "directionrtl"); + equal(editor.queryCommandValue('directionality'), "rtl", "查询文字输入方向为从右向左"); + + editor.execCommand('directionality', "ltr"); + equal(ua.getChildHTML(db), "

    gggsiekes

    ", "从左向右"); + equal(editor.queryCommandValue('directionality'), "ltr", "查询文字输入方向为从左向右"); + start(); + }, 20); + stop(); +} ); +//4 range between blockelement and notblockelement +test( '选区包含块和非块元素', function() { + var editor = te.obj[0],d = editor.document,range = te.obj[1],db = editor.body; + editor.setContent('gggsiekes

    xx

    '); + setTimeout(function () { + range.setStart(d.getElementsByTagName("strong")[0].firstChild, 0).setEnd(d.getElementsByTagName("p")[1].firstChild, 2).select(); + editor.execCommand('directionality', "rtl"); + equal(ua.getChildHTML(db), "

    gggsiekes

    xx

    ", "directionrtl"); + equal(editor.queryCommandValue('directionality'), "rtl", "directionrtl queryCommandValue"); + + editor.execCommand('directionality', "ltr"); + equal(ua.getChildHTML(db), "

    gggsiekes

    xx

    ", "directionltr"); + equal(editor.queryCommandValue('directionality'), "ltr", "directionltr queryCommandValue"); + start(); + }, 20); + stop(); +} ); +//5 betweenblockelement +test( '选区在两个块元素之间', function() { + var editor = te.obj[0], d = editor.document, range = te.obj[1], db = editor.body; + editor.setContent('

    sss

    xx

    '); + setTimeout(function () { + range.setStart(d.getElementsByTagName("p")[0].firstChild, 0).setEnd(d.getElementsByTagName("p")[1].firstChild, 2).select(); + editor.execCommand('directionality', "rtl"); + equal(ua.getChildHTML(db), "

    sss

    xx

    ", "directionrtl"); + equal(editor.queryCommandValue('directionality'), "rtl", "directionrtl queryCommandValue"); + + editor.execCommand('directionality', "ltr"); + equal(ua.getChildHTML(db), "

    sss

    xx

    ", "directionltr"); + equal(editor.queryCommandValue('directionality'), "ltr", "directionltr queryCommandValue"); + start(); + }, 20); + stop(); +} ); +//6 br +test( 'betweenblockelement', function() { + var editor = te.obj[0],d = editor.document,range = te.obj[1],db = editor.body; + editor.setContent( '

    xx

    br' ); + setTimeout(function () { + range.setStart(d.getElementsByTagName("p")[0].firstChild, 0).setEnd(db.lastChild, 1).select(); + editor.execCommand('directionality', "rtl"); + equal(ua.getChildHTML(db), "

    xx

    br

    ", "directionrtl"); + equal(editor.queryCommandValue('directionality'), "rtl", "directionrtl queryCommandValue"); + + editor.execCommand('directionality', "ltr"); + equal(ua.getChildHTML(db), "

    xx

    br

    ", "directionltr"); + equal(editor.queryCommandValue('directionality'), "ltr", "directionltr queryCommandValue"); + start(); + }, 20); + stop(); +} ); +//7   +test( '空格 ', function() { + var editor = te.obj[0], d = editor.document, range = te.obj[1], db = editor.body; + editor.setContent('

    xx

     '); + setTimeout(function () { + range.setStart(d.getElementsByTagName("p")[0].firstChild, 0).setEnd(db.lastChild, 1).select(); + editor.execCommand('directionality', "rtl"); + equal(ua.getChildHTML(db), "

    xx

     

    ", "directionrtl"); + equal(editor.queryCommandValue('directionality'), "rtl", "directionrtl queryCommandValue"); + + editor.execCommand('directionality', "ltr"); + equal(ua.getChildHTML(db), "

    xx

     

    ", "directionltr"); + equal(editor.queryCommandValue('directionality'), "ltr", "directionltr queryCommandValue"); + start(); + }, 20); + stop(); +} ); + +test('body',function(){ + var editor=te.obj[0]; + var range=te.obj[1]; + editor.setContent('

    xx

    '); + range.setStart(editor.body,0).collapse(1).select(); + editor.execCommand('directionality', 'rtl'); + if(ua.browser.ie){ + equal( ua.getChildHTML( editor.body ), "

    xx

    ", "directionrtl" ); + } + else{ + equal( ua.getChildHTML( editor.body ), "

    xx

    ", "directionrtl" ); + } + +}) diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/dragdrop.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/dragdrop.js new file mode 100644 index 000000000..90847bfab --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/dragdrop.js @@ -0,0 +1,37 @@ +/** + * Created with JetBrains PhpStorm. + * User: Administrator + * Date: 13-4-29 + * Time: 上午11:40 + * To change this template use File | Settings | File Templates. + */ +module( 'plugins.dragdrop' ); +test( 'trace 3385:拖拽图像不会把p切开', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + stop(); + + body.innerHTML = '

    hel

    lo

    '; + range.selectNode(body.childNodes[1]).select(); + equal(body.childNodes.length,3,'img在两个p之间'); + equal(body.firstChild.tagName.toLowerCase(),"p",'img在两个p之间'); + equal(body.childNodes[1].tagName.toLowerCase(),"img",'img在两个p之间'); + equal(body.childNodes[2].tagName.toLowerCase(),"p",'img在两个p之间'); + + ua.dragend(body); + setTimeout(function(){ + equal(body.childNodes.length,1,'img在p里面'); + equal(body.firstChild.tagName.toLowerCase(),'p','img在p里面'); + equal(body.firstChild.childNodes[1].tagName.toLowerCase(),'img','img在p里面'); + body.innerHTML = '

    asds

    ad

    '; + range.selectNode(body.childNodes[1]).select(); + ua.dragend(body); + setTimeout(function(){ + equal(body.childNodes.length,1,'拖拽图像不会把p切开,删除空span:img在p里面') + equal(body.firstChild.tagName.toLowerCase(),'p','img在p里面'); + equal(body.firstChild.childNodes[1].tagName.toLowerCase(),'img','img在p里面'); + start(); + },300); + },100); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/elementpath.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/elementpath.js new file mode 100644 index 000000000..efde71c12 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/elementpath.js @@ -0,0 +1,263 @@ +module('plugins.elementpath'); +/* +
  • 表格 +
  • 列表 +
  • 文本 +
  • 图片 +
  • 超链接 +
  • 加粗加斜 +
  • 下划线,删除线 + * */ + +//1.2的版本中,表格的外面会自动套一个带格式的div +test('表格', function () { + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor('ue', {'initialContent': '

    欢迎使用ueditor

    ', 'elementPathEnabled': true, 'autoFloatEnabled': false}); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + editor.setContent('
    hello1strongTexthello2spanText
    '); + var body = editor.body; + /*选中整个表格*/ + range.selectNode(body.firstChild).select(); + var eles = editor.queryCommandValue('elementpath'); + ua.checkElementPath(eles, ['body', 'table', 'tbody', 'tr', 'td'], '选中整个表格'); + /*在单元格中单击*/ + var tds = body.getElementsByTagName('td'); + range.setStart(tds[0].firstChild, 0).collapse(true).select(); + ua.checkElementPath(eles, ['body', 'table', 'tbody', 'tr', 'td'], '在单元格中单击'); + /*在单元格中的加粗文本中单击*/ + ua.manualDeleteFillData(editor.body); + range.setStart(tds[1].firstChild.firstChild, 1).collapse(true).select(); + eles = editor.queryCommandValue('elementpath'); + ua.checkElementPath(eles, ['body', 'table', 'tbody', 'tr', 'td', 'strong'], '在单元格中的加粗文本中单击'); + /*在单元格中的下划线文本中单击*/ + ua.manualDeleteFillData(editor.body); + range.setStart(tds[1].lastChild.firstChild, 1).collapse(true).select(); + eles = editor.queryCommandValue('elementpath'); + ua.checkElementPath(eles, ['body', 'table', 'tbody', 'tr', 'td', 'span'], '在单元格中的下划线文本中单击'); + /*选中有下划线的文本*/ + ua.manualDeleteFillData(editor.body); + range.setStart(tds[1].lastChild.lastChild, 1).setEnd(tds[1].lastChild.lastChild, 4).select(); + eles = editor.queryCommandValue('elementpath'); + ua.checkElementPath(eles, ['body', 'table', 'tbody', 'tr', 'td', 'span'], '选中有下划线的文本'); + setTimeout(function(){ + UE.delEditor('ue'); + te.dom.push(document.getElementById('ue')); + start(); + },200); + }); + stop(); +}); +test(' 通过选区路径取range', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.options.elementPathEnabled = true; + editor.setContent('
    12
    345
    '); + stop(); + setTimeout(function () { + var tds = editor.body.getElementsByTagName('td'); + var trs = editor.body.getElementsByTagName('tr'); + var tbodys = editor.body.getElementsByTagName('tbody'); + var table = editor.body.getElementsByTagName('table'); + range.setStart(tds[3].firstChild, 0).collapse(true).select(); + editor.queryCommandValue('elementpath'); + editor.execCommand('elementpath', '4'); + setTimeout(function () { + range = editor.selection.getRange(); + if (ua.browser.gecko||ua.browser.webkit) { + ua.checkResult(range, trs[1], trs[1], 1, 2, false, '取range--td'); + } else { + if (ua.browser.ie) + ua.checkResult(range, tds[3].firstChild, tds[3].lastChild, 0, 2, false, '取range--td'); + else + ua.checkResult(range, tds[3].firstChild, editor.body, 0, 1, false, '取range--td'); + } + range.setStart(tds[3].firstChild, 1).collapse(1).select(); + editor.execCommand('elementpath', '3'); + setTimeout(function () { + range = editor.selection.getRange(); + if (ua.browser.gecko||ua.browser.webkit) { + ua.checkResult(range, tbodys[0], tbodys[0], 1, 2, false, '取range--tr'); + } else { + if (ua.browser.ie) + ua.checkResult(range, tds[2].firstChild, tds[3].lastChild, 0, 2, false, '取range--tr'); + else + ua.checkResult(range, tds[2].firstChild, editor.body, 0, 1, false, '取range--tr'); + } + range.setStart(tds[3].firstChild, 0).collapse(1).select(); + editor.execCommand('elementpath', '2'); + setTimeout(function () { + range = editor.selection.getRange(); + if (ua.browser.gecko||ua.browser.webkit) { + ua.checkResult(range, table[0], table[0], 0, 1, false, '取range--tbody'); + } else { + if (ua.browser.ie) + ua.checkResult(range, tds[0].firstChild, tds[3].lastChild, 0, 2, false, '取range--tbody'); + else + ua.checkResult(range, editor.body, editor.body, 0, 1, false, '取range--tbody'); + } + editor.setContent('

    45645

    '); + range.selectNode(editor.body.firstChild).select(); + editor.queryCommandValue('elementpath'); + editor.execCommand('elementpath', 1); + setTimeout(function () { + range = editor.selection.getRange(); + var p = editor.body.firstChild; + if (ua.browser.gecko||ua.browser.webkit) { + ua.checkResult(range, editor.body, editor.body, 0, 1, false, '取range--p'); + } else { + ua.checkResult(range, p.firstChild, p.firstChild, 0, 5, false, '取range--p'); + } + start(); + }, 20); + }, 20); + }, 100); + }, 20); + }, 50); +}); + +test('trace 1539:列表', function () { + var div = document.body.appendChild(document.createElement('div')); + var editor = new baidu.editor.Editor({'initialContent': '

    欢迎使用ueditor

    ', 'elementPathEnabled': true, 'autoFloatEnabled': false}); + stop(); + setTimeout(function () { + editor.render(div); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + editor.setContent('
    1. hello1
    2. hello2
      hello3
    '); + var body = editor.body; + /*选中所有列表*/ + range.selectNode(body.firstChild).select(); + var eles = editor.queryCommandValue('elementpath'); + ua.checkElementPath(eles, ['body', 'ol', 'li', 'p'], '选中整个列表'); + /*选中列表中的表格*/ + range.selectNode(body.firstChild.getElementsByTagName('table')[0]).select(); + eles = editor.queryCommandValue('elementpath'); + ua.checkElementPath(eles, ['body', 'ol', 'li', 'table', 'tbody', 'tr', 'td'], '选中列表中的表格'); + /*选中列表中的br*/ + range.setStart(body.firstChild.firstChild.nextSibling.firstChild.firstChild, 6).collapse(true).select(); + eles = editor.queryCommandValue('elementpath'); + ua.checkElementPath(eles, ['body', 'ol', 'li', 'p'], '选中列表中的br'); + div.parentNode.removeChild(div); + start(); + }); + }, 20); +}); +test('文本和超链接', function () { + var div = document.body.appendChild(document.createElement('div')); + var editor = new baidu.editor.Editor({'initialContent': '

    欢迎使用ueditor

    ', 'elementPathEnabled': true, 'autoFloatEnabled': false}); + editor.render(div); + stop(); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + editor.setContent('
    '); + var body = editor.body; + /*选中文本hello*/ + range.selectNode(body.firstChild.firstChild).select(); + var eles = editor.queryCommandValue('elementpath'); + ua.checkElementPath(eles, ['body', 'p'], '选中文本'); + /*选中超链接*/ + range.selectNode(body.firstChild.lastChild.firstChild).select(); + eles = editor.queryCommandValue('elementpath'); + ua.checkElementPath(eles, ['body', 'p', 'a'], '选中文本'); + div.parentNode.removeChild(div); + start(); + }); +}); + +//在版本1.2中,如果没有setTimeout在FF(3.6和9都是)中range会出错,其他浏览器没问题 +test('图片', function () { + if(ua.browser.ie>8)return;//todo 1.3.6 #3847 + var div = document.body.appendChild(document.createElement('div')); + div.id = "ue"; + var editor = UE.getEditor("ue",{'initialContent': '

    欢迎使用ueditor

    ', 'elementPathEnabled': true, 'autoFloatEnabled': false}); + stop(); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + editor.setContent('

    hello

    '); + var body = editor.body; + /*选中图片*/ + setTimeout(function () { + range.selectNode(body.firstChild.lastChild).select(); + var eles = editor.queryCommandValue('elementpath'); + ua.checkElementPath(eles, ['body', 'p', 'img'], '选中图片'); + setTimeout(function () { + UE.delEditor('ue'); + te.dom.push(document.getElementById('ue')); + start(); + }, 200); + + }, 20) + }); +}); + +test('锚点', function () { + if(ua.browser.ie>8)return;//todo 1.3.6 #3847 + var div = document.body.appendChild(document.createElement('div')); + var editor = new baidu.editor.Editor({'initialContent': '

    欢迎使用ueditor

    ', 'elementPathEnabled': true, 'autoFloatEnabled': false}); + editor.render(div); + stop(); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + editor.setContent('

    hello

    '); + var body = editor.body; + /*选中图片*/ + setTimeout(function () { + range.selectNode(body.firstChild.lastChild).select(); + var eles = editor.queryCommandValue('elementpath'); + ua.checkElementPath(eles, ['body', 'p', 'anchor'], '选中锚点'); + div.parentNode.removeChild(div); + start(); + }, 20) + }); +}); +test('文本', function () { + var div = document.body.appendChild(document.createElement('div')); + var editor = new baidu.editor.Editor({'initialContent': '

    欢迎使用ueditor

    ', 'elementPathEnabled': true, 'autoFloatEnabled': false}); + editor.render(div); + stop(); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + editor.setContent('hello'); + var body = editor.body; + /*选中图片*/ + setTimeout(function () { + range.setStart(body.firstChild.firstChild, 1).setEnd(body.firstChild.firstChild, 3).select(); + var eles = editor.queryCommandValue('elementpath'); + ua.checkElementPath(eles, ['body', 'p'], '选中文本'); + div.parentNode.removeChild(div); + start(); + }, 20) + }); +}); + +test('trace 3995表格和文本', function () { + if(ua.browser.ie==11)return;//todo dev1.4.0 + + var div = document.body.appendChild(document.createElement('div')); + var editor = new baidu.editor.Editor({'initialContent': '

    欢迎使用ueditor

    ', 'elementPathEnabled': true, 'autoFloatEnabled': false}); + editor.render(div); + stop(); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + var body = editor.body; + range.setStart(body.firstChild.firstChild, 2).collapse(true).select(); + editor.execCommand('inserttable'); + /*选中图片*/ + setTimeout(function () { + range.selectNode(body).select(); + var eles = editor.queryCommandValue('elementpath'); + editor.execCommand('elementpath', 1); + ua.checkElementPath(eles, ['body', 'p'], '选中文本和表格'); + range.selectNode(body.firstChild.nextSibling).select(); + eles = editor.queryCommandValue('elementpath'); + ua.checkElementPath(eles, ['body', 'table'], '选中表格'); + editor.execCommand('elementpath', 4); + eles = editor.queryCommandValue('elementpath'); + ua.checkElementPath(eles, ['body', 'table', 'tbody', 'tr', 'td'], '选中表格'); + div.parentNode.removeChild(div); + start(); + }, 20); + }); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/enterkey.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/enterkey.js new file mode 100644 index 000000000..83eee009c --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/enterkey.js @@ -0,0 +1,634 @@ +module( 'plugins.enterkey' ); +///* +// 闭合选区 +// 1.p末尾或中间回车 +// 2.列表中回车(关于列表的回车必须加上li这个插件) +// 2.1 列表标号后面有文本 +// 2.2列表标号后没有文本 +// 3.h1后回车 +// 4.带有BIU样式的文本后面回车 +// +// 不闭合选区 +// 1.选中部分表格后回车 +// 2.选中文本后回车 +// + +// 复合操作 +// 1.回车后撤销 +// */ +//fixed in future +/*trace 3174*/ +//test( 'trace 2864:table中回车,br做回车', function () { +// te.dom[0].parentNode.removeChild(te.dom[0]); +// var div2 = document.body.appendChild( document.createElement( 'div' ) ); +// $( div2 ).css( 'width', '500px' ).css( 'height', '500px' ).css( 'border', '1px solid #ccc' ); +// te.dom.push(div2); +// baidu.editor.plugins.table = function(){}; +// var editor = new baidu.editor.Editor({'initialContent':'

    欢迎使用ueditor

    ','autoFloatEnabled':false,'enterTag':'br'}); +// te.obj.push(editor); +// editor.render(div2); +// var range = new baidu.editor.dom.Range( editor.document ); +// te.obj.push(range); +// editor.setContent('
    aa
    ' ); +// stop(); +// setTimeout(function(){ +// te.obj[4].selectNode(editor.body.firstChild.firstChild.firstChild.firstChild).select(); +// ua.keydown(editor.body,{'keyCode':13}); +// setTimeout(function(){ +// equal(ua.getChildHTML(te.obj[3].body.firstChild),'
    ','
    做回车'); +// te.dom[1].parentNode.removeChild(te.dom[1]); +// start(); +// },50); +// },50); +//} ); +//test( 'br做回车,选区非闭合', function () { +// te.dom[0].parentNode.removeChild(te.dom[0]); +// var div2 = document.body.appendChild( document.createElement( 'div' ) ); +// $( div2 ).css( 'width', '500px' ).css( 'height', '500px' ).css( 'border', '1px solid #ccc' ); +// te.dom.push(div2); +// baidu.editor.plugins.table = function(){}; +// var editor = new baidu.editor.Editor({'initialContent':'

    欢迎使用ueditor

    ','autoFloatEnabled':false,'enterTag':'br'}); +// te.obj.push(editor); +// editor.render(div2); +// stop(); +// editor.ready(function(){ +// var range = new baidu.editor.dom.Range( editor.document ); +// te.obj.push(range); +// editor.setContent('

    hello1

    hello2

    ' ); +// +// setTimeout(function(){ +// te.obj[4].setStart(editor.body.firstChild,0).setEnd(editor.body.lastChild,1).select(); +// ua.keydown(editor.body,{'keyCode':13}); +// setTimeout(function(){ +// ua.manualDeleteFillData(te.obj[3].body); +// var html = 'h
    lo'; +// equal(ua.getChildHTML(te.obj[3].body.firstChild),html,'
    做回车'); +// te.dom[1].parentNode.removeChild(te.dom[1]); +// start(); +// },50); +// },50); +// }); +//} ); + +test( 'br做回车,选区非闭合', function () { + te.dom[0].parentNode.removeChild(te.dom[0]); + var div2 = document.body.appendChild( document.createElement( 'div' ) ); + $( div2 ).css( 'width', '500px' ).css( 'height', '500px' ).css( 'border', '1px solid #ccc' ); + te.dom.push(div2); + baidu.editor.plugins.table = function(){}; + var editor = new baidu.editor.Editor({'initialContent':'

    欢迎使用ueditor

    ','autoFloatEnabled':false,'enterTag':'br'}); + te.obj.push(editor); + editor.render(div2); + stop(); + editor.ready(function(){ + var range = new baidu.editor.dom.Range( editor.document ); + te.obj.push(range); + editor.setContent('

    hello

    ' ); + te.obj[4].setStart(editor.body.firstChild.firstChild,1).setEnd(editor.body.firstChild.firstChild,3).select(); + ua.keydown(editor.body,{'keyCode':13}); + setTimeout(function(){ + ua.manualDeleteFillData(te.obj[3].body); + var html = 'h
    lo'; + equal(ua.getChildHTML(te.obj[3].body.firstChild),html,'
    做回车'); + editor.setContent('

    hello

    ' ); + te.obj[4].setStart( editor.body.lastChild,0 ).setEnd(editor.body.lastChild,1).select(); + ua.keydown(editor.body,{'keyCode':13}); + setTimeout(function(){ + ua.manualDeleteFillData(te.obj[3].body); + var html = 'hello
    '; + equal(ua.getChildHTML(te.obj[3].body.firstChild),html,'
    做回车'); + editor.setContent('

    hello

    heoll

    ' ); + te.obj[4].setStart( editor.body.lastChild,1 ).setEnd(editor.body.lastChild,2).select(); + ua.keydown(editor.body,{'keyCode':13}); + setTimeout(function(){ + ua.manualDeleteFillData(te.obj[3].body); + var html = 'hello
    '; + equal(ua.getChildHTML(te.obj[3].body.firstChild),html,'
    做回车'); + editor.setContent('

    hello


    ' ); + te.obj[4].setStart( editor.body.lastChild,0 ).setEnd(editor.body.lastChild,1).select(); + ua.keydown(editor.body,{'keyCode':13}); + setTimeout(function(){ + ua.manualDeleteFillData(te.obj[3].body); + var html = 'hello
    '; + equal(ua.getChildHTML(te.obj[3].body.firstChild),html,'
    做回车'); + editor.setContent('

    hello

    www.baidu.com

    ' ); + te.obj[4].setStart( editor.body.lastChild,0 ).setEnd(editor.body.lastChild,1).select(); + ua.keydown(editor.body,{'keyCode':13}); + setTimeout(function(){ + ua.manualDeleteFillData(te.obj[3].body); + var html = 'hello
    '; + equal(ua.getChildHTML(te.obj[3].body.firstChild),html,'
    做回车'); + te.dom[1].parentNode.removeChild(te.dom[1]); + start(); + },20); + },20); + },20); + },20); + },20); + }); +} ); + +test( 'br做回车,选区闭合', function () { + te.dom[0].parentNode.removeChild(te.dom[0]); + var div2 = document.body.appendChild( document.createElement( 'div' ) ); + $( div2 ).css( 'width', '500px' ).css( 'height', '500px' ).css( 'border', '1px solid #ccc' ); + te.dom.push(div2); + baidu.editor.plugins.table = function(){}; + var editor = new baidu.editor.Editor({'initialContent':'

    欢迎使用ueditor

    ','autoFloatEnabled':false,'enterTag':'br'}); + te.obj.push(editor); + editor.render(div2); + stop(); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + te.obj.push(range); + editor.setContent('

    hello

    '); + + setTimeout(function () { + te.obj[4].setStart(editor.body.firstChild.firstChild, 1).collapse(true).select(); + ua.keydown(editor.body, {'keyCode':13}); + setTimeout(function () { + ua.manualDeleteFillData(te.obj[3].body); + var html = 'h
    ello'; + equal(ua.getChildHTML(te.obj[3].body.firstChild), html, '
    做回车,选区闭合'); + te.dom[1].parentNode.removeChild(te.dom[1]); + start(); + }, 50); + }, 50); + }); +} ); + +test( 'br做回车,选区闭合,在节点尾部输入回车,要插入2个br', function () { + te.dom[0].parentNode.removeChild(te.dom[0]); + var div2 = document.body.appendChild( document.createElement( 'div' ) ); + $(div2).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + te.dom.push(div2); + baidu.editor.plugins.table = function () { + }; + var editor = new baidu.editor.Editor({'initialContent':'

    欢迎使用ueditor

    ', 'autoFloatEnabled':false, 'enterTag':'br'}); + te.obj.push(editor); + editor.render(div2); + stop(); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + te.obj.push(range); + editor.setContent('

    hello

    '); + setTimeout(function () { + te.obj[4].setStart(editor.body.firstChild.firstChild, 5).collapse(true).select(); + ua.keydown(editor.body, {'keyCode':13}); + setTimeout(function () { + ua.manualDeleteFillData(te.obj[3].body); + var html = 'hello

    '; + equal(ua.getChildHTML(te.obj[3].body.firstChild), html, '
    做回车,选区闭合,在节点尾部输入回车'); + te.dom[1].parentNode.removeChild(te.dom[1]); + start(); + }, 50); + }, 50); + }); +}); + +test( 'table首行中回车', function () { + var editor = te.obj[0]; + if(!ua.browser.ie){ + var range = new baidu.editor.dom.Range( editor.document ); + editor.setContent('

    ' ); + range.selectNode(editor.body.firstChild.firstChild.firstChild.firstChild).select(); + ua.keydown(editor.body,{'keyCode':13}); + stop(); + setTimeout(function(){ + equal(ua.getChildHTML(te.obj[0].body.firstChild),'
    ','加入p');//opera中,由原生方法实现p标签 + start(); + },20); + } +} ); + +test( '去除_moz_dirty', function () { + if(browser.gecko){ + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '迎使用uedit' ); + range.selectNode(editor.body.firstChild.lastChild.firstChild).select(); + ua.keydown(editor.body,{'keyCode':13}); + setTimeout( function () { + equal(ua.getChildHTML(editor.body),'

    迎使用uedit

    ',''); + start(); + }, 20 ); + stop(); + } +} ); + +///*不作处理chrome会产生div*/ +test( 'chrome删除div', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + if(ua.browser.webkit){ + editor.body.innerHTML = '

    一级标题


    '; + range.setStart( body.firstChild.firstChild, 4 ).collapse( 1 ).select(); + ua.keydown(editor.body,{'keyCode':13}); + range.selectNode(body.lastChild.firstChild).select(); + var index = editor.undoManger.index; + var br = ua.browser.ie ? '' : '
    '; + ua.keyup(editor.body,{'keyCode':13}); + equal(editor.undoManger.list.length,2,'保存现场'); + setTimeout( function () { + equal( body.childNodes.length, 2, '2个子节点' ); + equal(body.lastChild.tagName.toLowerCase(),'p','div转成p'); + equal(ua.getChildHTML(body),'

    一级标题


    ','检查内容'); + start(); + }, 60 ); + stop(); + }else{ + } +} ); +test( 'formatBlock', function () { + if(ua.browser.ie)return; //这个处理不针对ie + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '
    hello1
    hello2
    ' ); + setTimeout( function () { + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0],1).collapse(true).select(); + ua.keydown(editor.body,{'keyCode':13}); + setTimeout( function () { + ua.keyup(editor.body,{'keyCode':13}); + setTimeout( function () { + var td = editor.body.getElementsByTagName('td')[0]; + equal(td.firstChild&&td.firstChild.tagName.toLowerCase(),'p','加上p'); + equal(td.firstChild.innerHTML,'hello1','hello1'); + start(); + }, 60 ); + }, 60 ); + }, 60 ); + stop(); +} ); +test( '跨td不删', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '
    hello1
    hello2
    ' ); + editor.addListener("keydown", function (type, evt) { + setTimeout( function () { + ok(evt.defaultPrevented||!evt.returnValue, "keydown"); + start(); + }, 60 ); + }); + setTimeout(function () { + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).setEnd(tds[2], 1).select(); + ua.keydown(editor.body, {'keyCode': 13}); + }, 60); + stop(); +} ); +////presskey相关,先不测 +//test( '普通文本中间回车', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '

    你好编辑器

    ' ); +// range.setStart( body.firstChild.firstChild, 2 ).collapse( 1 ).select(); +// editor.focus(); +// setTimeout( function () { +// te.presskey( "enter", "" ); +// editor.focus(); +// setTimeout( function () { +// var ps = body.childNodes; +// equal( ps.length, 2, '2个p' ); +// equal( ps[0].tagName.toLowerCase(), 'p', 'tag名为p' ); +// equal( ps[1].tagName.toLowerCase(), 'p', 'tag名为p' ); +// equal( ua.getChildHTML( ps[0] ), '你好', '第一个p里是你好' ); +// equal( ua.getChildHTML( ps[1] ), '编辑器', '第一个p里是编辑器' ); +// start(); +// }, 30 ); +// }, 100 ); +// stop(); +//} ); +// +//test( '普通文本末尾回车', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '

    你好编辑器

    ' ); +// range.setStart( body.firstChild, 1 ).collapse( 1 ).select(); +// editor.focus(); +// var br = (ua.browser.ie) ? '' : '
    '; +// setTimeout( function () { +// te.presskey( "enter", "" ); +// ua.keydown( body ); +// editor.focus(); +// setTimeout( function () { +// var ps = body.childNodes; +// equal( ps.length, 2, '2个p' ); +// equal( ps[0].tagName.toLowerCase(), 'p', 'tag名为p' ); +// equal( ps[1].tagName.toLowerCase(), 'p', 'tag名为p' ); +// equal( ua.getChildHTML( ps[0] ), '你好编辑器', '第一个p里是你好编辑器' ); +// equal( ua.getChildHTML( ps[1] ), br, '第一个p里是br' ); +// start(); +// }, 60 ); +// }, 100 ); +// stop(); +//} ); +// +// //不好检查 +//test( 'table中回车', function () { +// var div2 = document.body.appendChild( document.createElement( 'div' ) ); +// $( div2 ).css( 'width', '500px' ).css( 'height', '500px' ).css( 'border', '1px solid #ccc' ); +// baidu.editor.plugins.table = function(){}; +// var editor = new baidu.editor.Editor({'initialContent':'

    欢迎使用ueditor

    ','autoFloatEnabled':false}); +// editor.render(div2); +// stop(); +// setTimeout(function(){ +// var range = new baidu.editor.dom.Range( editor.document ); +// var body = editor.body; +// editor.setContent('




    ' ); +// var tds = editor.body.getElementsByTagName( 'td' ); +// tds[0].innerHTML = 'hello'; +// tds[1].innerHTML = 'hello'; +// tds[2].innerHTML = 'hello'; +// range.setStart( tds[0].firstChild, 0 ).setEnd(tds[2].lastChild,1).select(); +// var re = ua.keydown(editor.body,{'keyCode':13}); +// setTimeout(function(){ +// start(); +// },20); +// },20); +//} ); +///*不作处理chrome会产生div*/ +//test( 'trace766 :H1回车', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '

    一级标题

    ' ); +// +// range.setStart( body.firstChild, 1 ).collapse( 1 ).select(); +// editor.focus(); +// var br = ua.browser.ie ? '' : '
    '; +// setTimeout( function () { +// te.presskey( "enter", "" ); +// editor.focus(); +// setTimeout( function () { +// +// var tagName = body.lastChild.tagName.toLowerCase(); +// ok( tagName == 'p' || tagName == 'h1', '回车后不会产生div' ); +// equal( body.childNodes.length, 2, '2个子节点' ); +// start(); +// }, 60 ); +// }, 100 ); +// stop(); +//} ); +// +// +//test( 'trace 1382:空列表标号后回车', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '
    ' ); +// var li = body.getElementsByTagName( 'li' )[0]; +// range.setStart( li, 0 ).collapse( 1 ).select(); +// editor.focus(); +// var br = ua.browser.ie ? '' : '
    '; +// setTimeout( function () { +// te.presskey( "enter", "" ); +// editor.focus(); +// setTimeout( function () { +// var ol = body.getElementsByTagName( 'ol' ); +// equal( ol.length, 0, '列表被删除了' ); +// start(); +// }, 100 ); +// }, 100 ); +// stop(); +//} ); +// +//test( '列表有内容处回车', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '
    1. 列表1
    2. 列表2
    ' ); +// var lis = body.getElementsByTagName( 'li' ); +// range.setStart( lis[1].firstChild, 1 ).collapse( 1 ).select(); +// editor.focus(); +// var br = ua.browser.ie ? '' : '
    '; +// setTimeout( function () { +// te.presskey( "enter", "" ); +// editor.focus(); +// setTimeout( function () { +// var ol = body.getElementsByTagName( 'ol' )[0]; +// lis = ol.childNodes; +// equal( lis.length, 3, '3个li' ); +// for ( var index = 0; index < lis.length; index++ ) +// equal( lis[index].tagName.toLowerCase(), 'li', 'tag名为li' ); +// equal( ua.getChildHTML( lis[1] ), '

    列表2

    ', '第二个列表自动加了p' ); +// equal( ua.getChildHTML( lis[2] ), '

    ' + br + '

    ', '新增了一个列表项' ); +// start(); +// }, 70 ); +// }, 100 ); +// stop(); +//} ); +// +// +//test( 'trace766 :BIU文本中间回车', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '

    有样式的文本

    ' ); +// +// var str = body.getElementsByTagName( 'strong' )[0]; +// range.setStart( str.firstChild, 2 ).collapse( 1 ).select(); +// editor.focus(); +// var br = ua.browser.ie ? '' : '
    '; +// setTimeout( function () { +// te.presskey( "enter", "" ); +// editor.focus(); +// setTimeout( function () { +//// ua.checkHTMLSameStyle( '有样​', editor.document, body.firstChild, '查看第1个p的内容' ); +// //1.2版本中,回车/空格只后有不可见的字符,ua.checkHTMLSameStyle检查的话,的内容不好检查,即会多出一个子节点,改成如下: +// baidu.editor.dom.domUtils.removeDirtyAttr( body.lastChild ); +// if ( ua.browser.chrome ) { +// equal( body.firstChild.innerHTML.toLowerCase(), '有样​', '查看第1个p的内容' ); +// ua.checkHTMLSameStyle( '式的文本', editor.document, body.lastChild, '查看第2个p的内容' ); +// } +// else if ( ua.browser.gecko ) { +// equal( body.firstChild.innerHTML.toLowerCase(), '有样', '查看第1个p的内容' ); +// equal( body.lastChild.innerHTML, '​式的文本', '查看第2个p的内容' ); +// } +// else { +// equal( body.firstChild.innerHTML.toLowerCase(), '有样​', '查看第1个p的内容' ); +// ua.checkHTMLSameStyle( '式的文本', editor.document, body.lastChild, '查看第2个p的内容' ); +// } +// start(); +// }, 70 ); +// }, 100 ); +// stop(); +//} ); +// +//test( 'trace841 :BIU文本后面回车', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '

    有样式的文本

    ' ); +// var strong = body.getElementsByTagName( 'strong' )[0]; +//// range.setStart( strong.firstChild, 6 ).collapse( 1 ).select(); +// range.setStart( strong, 1 ).collapse( 1 ).select(); +// editor.focus(); +// setTimeout( function () { +// te.presskey( "enter", "" ); +// editor.focus(); +// setTimeout( function () { +// ua.keydown( body, {keyCode:13} ); +// baidu.editor.dom.domUtils.removeDirtyAttr( body.lastChild ); +//// ua.checkHTMLSameStyle( '有样​', editor.document, body.firstChild, '查看第1个p的内容' ); +// //1.2版本中,回车/空格只后有不可见的字符,ua.checkHTMLSameStyle检查的话,的内容不好检查,即会多出一个子节点,而且每种浏览器的具体结果不同,改成如下: +// if ( ua.browser.chrome ) +// equal( body.firstChild.innerHTML.toLowerCase(), '有样式的文本​', '查看第1个p的内容' ); +// else if ( ua.browser.gecko ) +// equal( body.firstChild.innerHTML.toLowerCase(), '有样式的文本', '查看第1个p的内容' ); +// else +// equal( body.firstChild.innerHTML.toLowerCase(), '有样式的文本​', '查看第1个p的内容' ); +// /*ie中有一个已知bug,trace841,暂时不修的*/ +// var br = ua.browser.gecko ? '' : '
    '; +// if ( !ua.browser.ie ) { +// /*firefox不知道为什么用程序的方式回车始终不会产生br,可能太快了,浏览器没来得及处理*/ +// if ( ua.browser.gecko ) +// equal( body.lastChild.innerHTML, '', '查看第2个p的内容' ); +// else +// ua.checkHTMLSameStyle( '' + br + '', editor.document, body.lastChild, '查看第2个p的内容' ); +// } +// start(); +// }, 500 ); +// }, 100 ); +// stop(); +//} ); +// +// +//test( '不闭合选择普通文本回车', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '

    普通文本回车

    ' ); +// range.setStart( body.firstChild.firstChild, 2 ).setEnd( body.firstChild.firstChild, 4 ).select(); +// editor.focus(); +// setTimeout( function () { +// te.presskey( "enter", "" ); +// editor.focus(); +// setTimeout( function () { +// var ps = body.childNodes; +// equal( ps.length, 2, '2个p' ); +// equal( ps[0].tagName.toLowerCase(), 'p', 'tag名为p' ); +// equal( ps[1].tagName.toLowerCase(), 'p', 'tag名为p' ); +// equal( ua.getChildHTML( ps[0] ), '普通', '第一个p里是你好编辑器' ); +// equal( ua.getChildHTML( ps[1] ), '回车', '第2个p里是br' ); +// start(); +// }, 60 ); +// }, 100 ); +// stop(); +//} ); +// +//test( '不闭合选择段落回车', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '

    不闭合选择两个段落1

    不闭合选择两个段落2

    ' ); +// range.setStart( body.firstChild.firstChild, 3 ).setEnd( body.lastChild.firstChild, 5 ).select(); +// editor.focus(); +// var br = ua.browser.ie ? '' : '
    '; +// setTimeout( function () { +// te.presskey( "enter", "" ); +// editor.focus(); +// setTimeout( function () { +// var ps = body.childNodes; +// equal( ps.length, 2, '2个p' ); +// equal( ps[0].tagName.toLowerCase(), 'p', 'tag名为p' ); +// equal( ps[1].tagName.toLowerCase(), 'p', 'tag名为p' ); +// equal( ua.getChildHTML( ps[0] ), '不闭合', '第一个p里是你好编辑器' ); +// equal( ua.getChildHTML( ps[1] ), '两个段落2', '第一个p里是br' ); +// start(); +// }, 60 ); +// }, 100 ); +// stop(); +//} ); +// +// +//test( '撤销回车不闭合删除段落', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '

    不闭合选择两个段落1

    不闭合选择两个段落2

    ' ); +// range.setStart( body.firstChild.firstChild, 3 ).setEnd( body.lastChild.firstChild, 5 ).select(); +// editor.focus(); +// var br = ua.browser.ie ? '' : '
    '; +// setTimeout( function () { +// te.presskey( "enter", "" ); +// editor.focus(); +// setTimeout( function () { +// var ps = body.childNodes; +// equal( ps.length, 2, '2个p' ); +// equal( ps[0].tagName.toLowerCase(), 'p', 'tag名为p' ); +// equal( ps[1].tagName.toLowerCase(), 'p', 'tag名为p' ); +// equal( ua.getChildHTML( ps[0] ), '不闭合', '第一个p里是你好编辑器' ); +// equal( ua.getChildHTML( ps[1] ), '两个段落2', '第一个p里是br' ); +// editor.undoManger.undo(); +// equal( ps.length, 2, '2个p' ); +// equal( ps[0].tagName.toLowerCase(), 'p', 'tag名为p' ); +// equal( ps[1].tagName.toLowerCase(), 'p', 'tag名为p' ); +// equal( ua.getChildHTML( ps[0] ), '不闭合选择两个段落1', '第一个p里是你好编辑器' ); +// equal( ua.getChildHTML( ps[1] ), '不闭合选择两个段落2', '第一个p里是br' ); +// start(); +// }, 60 ); +// }, 100 ); +// stop(); +//} ); +// +///*1723 ie 在源码中写
    ,自动变成

    ,在ie中
    会导致undo操作多记了一步*/ +//test( '撤销回车删除空列表', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '
    ' ); +// var li = body.getElementsByTagName( 'li' )[0]; +// range.setStart( li.firstChild, 0 ).collapse( 1 ).select(); +// editor.focus(); +// +// setTimeout( function () { +// te.presskey( "enter", "" ); +// /*好像用程序控制按回车的速度会比程序捕获的速度快, +// 所以程序还没反应过来时keydown已经触发完了, +// 而keydown中用于进行场景保存的,这样就会导致undo操作失效*/ +// ua.keydown( body ); +// editor.focus(); +// setTimeout( function () { +// var ol = body.getElementsByTagName( 'ol' ); +// equal( ol.length, 0, '列表被删除了' ); +// setTimeout( function () { +// editor.undoManger.undo(); +// equal( ua.getChildHTML( body ), '

    ', '撤销删除列表' ); +// start(); +// }, 50 ); +// +// }, 150 ); +// }, 100 ); +// stop(); +//} ); +// +//test( '撤销列表中的回车', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '
    1. 列表
    ' ); +// var li = body.getElementsByTagName( 'li' )[0]; +// range.setStart( li.firstChild, 1 ).collapse( 1 ).select(); +// editor.focus(); +// var br = ua.browser.ie ? '' : '
    '; +// +// setTimeout( function () { +// te.presskey( "enter", "" ); +// ua.keydown( body ); +// editor.focus(); +// setTimeout( function () { +// var li = body.getElementsByTagName( 'li' ); +// equal( li.length, 2, '2个列表子项' ); +// equal( ua.getChildHTML( li[0] ), '

    列表

    ' ); +// equal( ua.getChildHTML( li[1] ), '

    ' + br + '

    ' ); +// editor.undoManger.undo(); +// equal( ua.getChildHTML( body ), '
    1. 列表

    ', '撤销后列表恢复原状' ); +// start(); +// }, 250 ); +// }, 100 ); +// stop(); +//} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/fiximgclick.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/fiximgclick.js new file mode 100644 index 000000000..fe13f3ab9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/fiximgclick.js @@ -0,0 +1,117 @@ +module( 'plugins.fiximgclick' ); + +test( 'webkit下图片可以被选中并出现八个角', function() { + if ( ua.browser.webkit ) { + var sc = document.createElement("script"); + sc.id="sc"; + sc.type = "text/plain"; + document.body.appendChild(sc); + var editor = new UE.ui.Editor({'autoFloatEnabled':true,'topOffset':60,'autoHeightEnabled':true,'scaleEnabled':false}); + editor.render(sc.id); + editor.ready(function () { + editor.setContent( '

    修正webkit下图片选择的问题修正webkit下图片选择的问题

    ' ); + var img = editor.body.getElementsByTagName( 'img' )[0]; + var p = editor.body.firstChild; + ua.click( img ); + var range = editor.selection.getRange(); + ua.checkResult( range, p, p, 1, 2, false, '检查当前的range是否为img' ); + var scale = document.getElementById(editor.ui.id + '_scale'); + ok(scale && scale.style.display!='none', "检查八个角是否已出现"); + ok(img.style.width == scale.style.width && img.style.height == scale.style.height, "检查八个角和图片宽高度是否相等"); + UE.delEditor(sc.id); + domUtils.remove(sc); + start(); + }); + stop(); + } +} ); + +test( '鼠标在八个角上拖拽改变图片大小', function() { + if ( ua.browser.webkit ) { + var sc = document.createElement("script"); + sc.id="sc"; + sc.type = "text/plain"; + document.body.appendChild(sc); + var editor = new UE.ui.Editor({'autoFloatEnabled':true,'topOffset':60,'autoHeightEnabled':true,'scaleEnabled':false}); + editor.render(sc.id); + editor.ready(function () { + editor.setContent( '

    修正webkit下图片选择的问题修正webkit下图片选择的问题

    ' ); + var img = editor.body.getElementsByTagName( 'img' )[0]; + var p = editor.body.firstChild; + ua.click( img ); + var scale = document.getElementById(editor.ui.id + '_imagescale'); + var hand0 = scale.children[0], width, height; + width = parseInt(scale.style.width); + height = parseInt(scale.style.height); + ua.mousedown( hand0, {clientX: 322, clientY: 281} ); + ua.mousemove( document, {clientX: 352, clientY: 301} ); + equal(width-parseInt(scale.style.width), 30, "检查鼠标拖拽中图片宽度是否正确 --"); + equal(height-parseInt(scale.style.height), 20, "检查鼠标拖拽中图片高度是否正确 --"); + ua.mousemove( document, {clientX: 382, clientY: 321} ); + ua.mouseup( document, {clientX: 382, clientY: 321} ); + equal(width-parseInt(scale.style.width), 60, "检查鼠标拖拽完毕图片高度是否正确 --"); + equal(height-parseInt(scale.style.height), 40, "检查鼠标拖拽完毕图片高度是否正确 --"); + ok(img.style.width == scale.style.width && img.style.height == scale.style.height, "检查八个角和图片宽高度是否相等"); + UE.delEditor(sc.id); + domUtils.remove(sc); + start(); + }); + stop(); + } +} ); + +test( '鼠标点击图片外的其他区域时,八个角消失', function() { + if ( ua.browser.webkit ) { + var sc = document.createElement("script"); + sc.id="sc"; + sc.type = "text/plain"; + document.body.appendChild(sc); + var editor = new UE.ui.Editor({'autoFloatEnabled':true,'topOffset':60,'autoHeightEnabled':true,'scaleEnabled':false}); + editor.render(sc.id); + editor.ready(function () { + editor.setContent( '

    修正webkit下图片选择的问题修正webkit下图片选择的问题

    ' ); + var img = editor.body.getElementsByTagName( 'img' )[0]; + var p = editor.body.firstChild; + ua.click( img ); + var scale = document.getElementById(editor.ui.id + '_imagescale'), + cover = document.getElementById(editor.ui.id + '_imagescale_cover'); + ok(scale && scale.style.display!='none', "检查八个角是否已出现"); + ok(cover && cover.style.display!='none', "检查遮罩层是否已出现"); + ua.mousedown( editor.ui.getDom(), {clientX: 100, clientY: 100} ); + ok(cover && cover.style.display=='none', "检查遮罩层是否已消失"); + ok(scale && scale.style.display=='none', "检查八个角是否已消失"); + UE.delEditor(sc.id); + domUtils.remove(sc); + start(); + }); + stop(); + } +} ); + +test( '键盘有操作时,八个角消失', function() { + if ( ua.browser.webkit ) { + var sc = document.createElement("script"); + sc.id="sc"; + sc.type = "text/plain"; + document.body.appendChild(sc); + var editor = new UE.ui.Editor({'autoFloatEnabled':true,'topOffset':60,'autoHeightEnabled':true,'scaleEnabled':false}); + editor.render(sc.id); + editor.ready(function () { + editor.setContent( '

    修正webkit下图片选择的问题修正webkit下图片选择的问题

    ' ); + var img = editor.body.getElementsByTagName( 'img' )[0]; + var p = editor.body.firstChild; + ua.click( img ); + var scale = document.getElementById(editor.ui.id + '_imagescale'), + cover = document.getElementById(editor.ui.id + '_imagescale_cover'); + ok(scale && scale.style.display!='none', "检查八个角是否已出现"); + ok(cover && cover.style.display!='none', "检查遮罩层是否已出现"); + ua.keydown( editor.ui.getDom()); + ok(cover && cover.style.display=='none', "检查遮罩层是否已消失"); + ok(scale && scale.style.display=='none', "检查八个角是否已消失"); + UE.delEditor(sc.id); + domUtils.remove(sc); + start(); + }); + stop(); + } +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/font.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/font.js new file mode 100644 index 000000000..fbe94bc09 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/font.js @@ -0,0 +1,506 @@ +module("plugins.font"); + +//test('stop',function(){stop();}); +test('trace1583:applyInlineStyle--MergeToParent', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + stop(); + setTimeout(function () { + editor.setContent('

    12345678910

    '); + range.setStart(editor.body.firstChild, 0).setEnd(editor.body.firstChild, 4).select(); + editor.execCommand('fontsize', '24px'); + var html = '12345678910'; + ua.checkSameHtml(editor.body.firstChild.innerHTML.toLowerCase(), html, ''); + start(); + }, 50); + +}); +test('trace 3337:字符边框', function () { + + if (ua.browser.opera)return; + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('fontborder'); + range = editor.selection.getRange(); + range.insertNode(editor.document.createTextNode('hello')); + ua.manualDeleteFillData(editor.body); + var br = baidu.editor.browser.ie ? ' ' : '
    '; + if (ua.browser.ie && ua.browser.ie < 9) { + equal(editor.queryCommandValue('fontborder'), '#000 1px solid', '检查反射值'); + equal(ua.getChildHTML(editor.body.firstChild), "hello ", '查看添加了字符边框后的样式'); + } + else { + equal(editor.queryCommandValue('fontborder'), '1px solid rgb(0, 0, 0)', '检查反射值'); + ua.checkHTMLSameStyle('hello' + br, editor.document, editor.body.firstChild, '查看添加了字符边框后的样式'); + } + range.setStart(editor.body.firstChild.firstChild.firstChild, 5).collapse(true).select(); + editor.execCommand('fontborder'); + equal(editor.queryCommandState('fontborder'), '0'); + equal(editor.queryCommandValue('fontborder'), '', '无反射值'); + editor.setContent('

    迎光临

    '); + range.setStart(editor.body.firstChild.firstChild, 0).setEnd(editor.body.firstChild.lastChild, 3).select(); + editor.execCommand('fontborder'); + var p1 = '迎光临'; + var p2 = '迎光临'; + if (ua.browser.ie && ua.browser.ie < 9) + ua.checkSameHtml(editor.body.firstChild.innerHTML, p2, '查看添加了字符边框后的样式'); + else + ua.checkHTMLSameStyle(p1, editor.document, editor.body.firstChild, '查看添加了字符边框后的样式'); +}); +test('设置超链接前景色再清除颜色', function () { + if (ua.browser.ie < 9)return;//TODO 1.2.6 + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    hellobaidu

    '); + range.selectNode(editor.body.firstChild).select(); + editor.execCommand('forecolor', 'rgb(255,0,0)'); + editor.execCommand('backcolor', 'rgb(0,255,0)'); + editor.execCommand('forecolor', 'default'); + // var html = 'hellobaidu';todo 1.2.6.1 样式复制了一次 + var html = 'hellobaidu'; + ua.checkHTMLSameStyle(html, editor.document, editor.body.firstChild, '清除前景色'); +}); + + +test('font转span', function () { + var editor = te.obj[0]; + editor.setContent('hellohello'); + var html = 'hellohello'; + ua.checkHTMLSameStyle(html, editor.document, editor.body.firstChild, '转换font标签'); + /*size的值在sizeMap中有对应的值*/ + editor.setContent('hello'); + html = 'hello'; + ua.checkHTMLSameStyle(html, editor.document, editor.body.firstChild, '转换font标签'); +}); +test('beforegetContent', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.body.innerHTML = '

    hello

    '; + range.selectNode(editor.body.firstChild).select(); + editor.execCommand('forecolor', 'rgb(255,0,0)'); + var div = document.createElement('div'); + var div1 = document.createElement('div'); + stop(); + setTimeout(function () { + /*getContent会触发beforegetcontent事件*/ + div1.innerHTML = editor.getContent(); + div.innerHTML = '

    hello

    '; +// ok( ua.haveSameAllChildAttribs( div, div1 ), '查看空span是否被删除' ); + equal(ua.getChildHTML(div), ua.getChildHTML(div1)); + start(); + }, 50); +}); + +/*为超链接添加删除线,超链接仍然有删除线,trace946*/ +test('underline and linethrough', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + stop(); + editor.setContent('hellobaidutest'); + setTimeout(function () { + if (!ua.browser.opera) { + editor.focus(); + } + var body = editor.body; + ua.manualDeleteFillData(editor.body); + range.selectNode(body.firstChild.firstChild.nextSibling).select(); + ok(/underline/.test(editor.queryCommandValue('underline')), 'query command value is underline'); + ok(/underline/.test(editor.queryCommandValue('strikethrough')), 'query command value is underline'); + ok(editor.queryCommandState('underline'), 'query underline state'); + editor.execCommand('strikethrough'); + var html = 'hellobaidutest'; + ua.checkHTMLSameStyle(html, editor.document, body.firstChild, 'check results'); + start(); + }, 50); +}); + +/*为不同字号的文本加背景色,trace981*/ +test('background--不同字号', function () { + if (!ua.browser.opera) { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('你好'); + editor.focus(); + var body = editor.document.body; + ua.manualDeleteFillData(editor.body); + range.selectNode(body.firstChild.firstChild).select(); + editor.execCommand('backcolor', 'rgb(255,0,0)'); + range.setStart(body.firstChild.firstChild, 1).collapse(1).select(); + editor.execCommand('fontsize', '30px'); + range = editor.selection.getRange(); + range.insertNode(editor.document.createTextNode('hello')); + stop(); + setTimeout(function () { + ua.manualDeleteFillData(editor.body); + /*去掉空白字符*/ + var color = ua.browser.ie && ua.browser.ie < 9 ? '' : ';background-color: rgb(255, 0, 0); '; + var html = '你好hello'; + ua.checkHTMLSameStyle(html, editor.document, editor.body.firstChild, '检查不同字号的文本背景色是否一致'); + start(); + }, 50); + } +}); + +/*trace 937,chrome,safari,maxthon有问题*/ +test('trace 937:为第一个有样式的字加删除线', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    迎光临

    '); + range.selectNode(editor.body.firstChild).select(); + editor.execCommand('strikethrough'); + var p1 = editor.document.createElement('p'); + p1.innerHTML = '迎光临'; + ok(ua.haveSameAllChildAttribs(editor.body.firstChild, p1), '查看添加了下划线后的样式'); +}); + +/*trace 918*/ +test('trace 918:字体的状态反射', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    欢迎你回来

    '); + var p = editor.body.firstChild; + range.selectNode(p).select(); + editor.execCommand('underline'); + var p1 = document.createElement('p'); + p1.innerHTML = '欢迎你回来'; + if (!ua.browser.opera) { + ok(ua.haveSameAllChildAttribs(p, p1), '检查是否添加了下划线'); + } + range.setStart(p.firstChild.firstChild, 3).setEnd(p.firstChild.firstChild, 4).select(); + editor.execCommand('fontfamily', '楷体'); + var txt = '楷体'; + if (ua.browser.opera) + txt = '\"楷体\"'; + equal(editor.queryCommandValue('fontfamily'), txt, '检查字体的状态反射'); + +}); + +test(' 选中文本设置前景色为默认', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + editor.setContent('hello'); + range.selectNode(editor.body.firstChild).select(); + editor.execCommand('forecolor', 'rgb(255,0,0)'); + ua.checkHTMLSameStyle('hello', editor.document, editor.body.firstChild, '文本的前景色设为红色'); + editor.execCommand('forecolor', 'default'); + equal(ua.getChildHTML(editor.body), '

    hello

    ', '设置字体颜色为默认颜色'); + +}); + +/*trace 869*/ +//插件相关!!!!!!!!!! +//test( 'trace 869:设置前景色后清除前景色,再输入文本', function() { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// editor.setContent( '' ); +// stop() +//// alert(navigator.userAgent) +// setTimeout( function() { +// range.setStart( editor.body.firstChild, 0 ).select(); +// editor.execCommand( 'forecolor', 'red' ); +// editor.execCommand( 'forecolor', 'default' ); +// range = editor.selection.getRange(); +// editor.focus(); +// setTimeout( function() { +// //TODO maxthon有2种模式,句柄分为IE的和maxthon两种,需要根据userAgent区别对待,但是貌似还是有问题的 +// te.presskey( '', 'e' ); +// editor.focus(); +// setTimeout( function() { +// var br = baidu.editor.browser.ie ? '' : '
    '; +// ua.manualDeleteFillData( editor.body ); +// equal( editor.getContent(), '

    e' + br + '

    ' ); +// start(); +// }, 250 ); +// }, 100 ); +//// range.insertNode( document.createTextNode( 'hello' ) ); +// }, 150 ); +//} ); + +/*trace 823*/ +//TODO 涉及文本输入和光标位置移动的结合 +// 不好测,采取workaround,不用输入的方式 +test('trace 823:设置前景色后设置删除线', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + editor.setContent('

    你好​hello

    '); + range.selectNode(editor.body.firstChild.firstChild, 0).select(); + editor.execCommand('strikethrough'); + var p1 = editor.document.createElement('p'); + p1.innerHTML = '你好hello'; + ok(ua.haveSameAllChildAttribs(editor.body.firstChild, p1), '检查加入删除线后的样式'); + +}); + +/*trace 819, 765*/ +test('trace 819, 765:删除线和下划线互斥', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + var p1 = editor.document.createElement('p'); + editor.setContent('

    你好

    '); + range.selectNode(editor.body.firstChild).select(); + editor.execCommand('underline'); + p1.innerHTML = '你好'; + ok(ua.haveSameAllChildAttribs(editor.body.firstChild, p1), '下划线'); + range.selectNode(editor.body.firstChild).select(); + + editor.execCommand('strikethrough'); + p1.innerHTML = '你好'; + ok(ua.haveSameAllChildAttribs(editor.body.firstChild, p1), '删除线,和下划线互斥'); + range.selectNode(editor.body.firstChild).select(); + editor.execCommand('underline'); + p1.innerHTML = '你好'; + ok(ua.haveSameAllChildAttribs(editor.body.firstChild, p1), '下划线,和删除线互斥'); + +}); + +///*trace 810*/ +//TODO 1.2.6 +//test( 'trace 810:闭合时设置删除线会改变文本前景色', function() { +// if(!ua.browser.opera){ +// var editor = te.obj[2]; +// var div = document.body.appendChild( document.createElement( 'div' ) ); +// $( div ).css( 'width', '500px' ).css( 'height', '500px' ).css( 'border', '1px solid #ccc' ); +// editor.render(div); +// var range = new baidu.editor.dom.Range( editor.document ); +// stop(); +// setTimeout(function(){ +// editor.setContent( '

    你好​hello

    ' ); +// range.setStart( editor.body.firstChild.firstChild.lastChild, 1 ).collapse( true ).select(); +// editor.execCommand( 'strikethrough' ); +// range = editor.selection.getRange(); +// range.insertNode( editor.document.createTextNode( 'hey' ) ); +// /*ff下会自动加一个空的设置了style的span,比较时不作考虑*/ +// if ( baidu.editor.dom.domUtils.isEmptyNode( editor.body.firstChild.lastChild ) && baidu.editor.browser.gecko ) +// editor.body.firstChild.removeChild( editor.body.firstChild.lastChild ); +// var html = '你好hellohey'; +// ua.checkHTMLSameStyle( html, editor.document, editor.body.firstChild, '检查插入的删除线前景色是否正确' ); +// equal(editor.body.firstChild.innerHTML,html); +// div.parentNode.removeChild(div); +// start(); +// },50); +// } +//} ); + +/*trace 809*/ +test('trace 809:闭合时改变前景色和删除线,再输入文本', function () { + if (!ua.browser.opera) { + var editor = te.obj[0]; + var range = te.obj[1]; + + editor.setContent('

    你好

    '); + var p = editor.body.firstChild; + range.setStart(p.firstChild, 1).collapse(true).select(); + editor.execCommand('forecolor', 'rgb(0,255,0)'); + range = editor.selection.getRange(); + editor.execCommand('underline'); + range = editor.selection.getRange(); + range.insertNode(editor.document.createTextNode('hey')); + var p1 = editor.document.createElement('p'); + p1.innerHTML = '你好​hey'; + ua.manualDeleteFillData(editor.body); + /*ff下会自动加一个空的设置了style的span,比较时不作考虑*/ + if (baidu.editor.dom.domUtils.isEmptyNode(editor.body.firstChild.lastChild) && baidu.editor.browser.gecko) + editor.body.firstChild.removeChild(editor.body.firstChild.lastChild); + ok(ua.haveSameAllChildAttribs(editor.body.firstChild, p1), '检查新输入的文本下划线和颜色是否正确'); + + } +}); + +/*trace 805*/ +test('trace 805:切换删除线和下划线,前景色没了', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    你好早安

    '); + var text = editor.body.firstChild.firstChild.firstChild; + range.selectNode(text).select(); + editor.execCommand('forecolor', 'rgb(255,0,0)'); + range.setStart(text, 0).setEnd(text, 2).select(); + editor.execCommand('underline'); + range.setStart(text, 0).setEnd(text, 2).select(); + editor.execCommand('strikethrough'); + var p1 = editor.document.createElement('p'); + p1.innerHTML = '你好早安'; + ok(ua.haveSameAllChildAttribs(editor.body.firstChild, p1), '查看前景色是不是还在'); + +}); + +/*trace 802*/ +test('trace 802:为设置了字体的文本添加删除线', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + editor.setContent('

    你好早安

    '); + var text = editor.body.firstChild.firstChild.firstChild; + range.setStart(text, 0).setEnd(text, 2).select(); + editor.execCommand('strikethrough'); + var p1 = editor.document.createElement('p'); + p1.innerHTML = '你好早安'; + ok(ua.haveSameAllChildAttribs(editor.body.firstChild, p1), '检查删除线是否正确'); + editor.execCommand('fontfamily', '隶书'); + editor.execCommand('source'); + var txt = '隶书'; + if (ua.browser.opera) + txt = '\"隶书\"'; + if(!ua.browser.gecko)//todo 1.4.0 + equal(editor.queryCommandValue('fontfamily'), txt); + +}); + +/*trace 744*/ +test('trace 744:设置超链接背景色后切换到源码再切回来', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + stop(); + editor.setContent('

    hellobaidu

    '); + range.selectNode(editor.body.firstChild).select(); + editor.execCommand('backcolor', 'rgb(255,0,0)'); + var html = editor.body.firstChild.innerHTML; + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + ua.checkHTMLSameStyle(html, editor.document, editor.body.firstChild, '切换后html代码不变'); + /*切换源码前后代码应当相同*/ + start(); + }, 50); + }, 50); +}); + + +test('对表格中的文本添加颜色和下划线', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + stop(); + editor.setContent('
    hello1hello2
    hello3
    '); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[0]); + ut.setSelected(cellsRange); + if (ua.browser.ie && ua.browser.ie < 9) { + range.setStart(editor.body.firstChild.firstChild.firstChild.firstChild, 0).setEnd(editor.body.firstChild.firstChild.lastChild.firstChild, 6).select(); + } + else { + range.setStart(trs[0].cells[0].firstChild, 0).setEnd(trs[1].cells[0].firstChild, 6).select(); + } + + editor.execCommand('forecolor', 'rgb(255,100,100)'); + setTimeout(function () { + ut.clearSelected(); + trs = editor.body.firstChild.getElementsByTagName('tr'); + ut = editor.getUETable(editor.body.firstChild); + range.selectNode(trs[0].firstChild).select(); + ut.setSelected(range); + setTimeout(function () { + editor.execCommand('underline'); + setTimeout(function () { + var tds = editor.body.firstChild.getElementsByTagName('td'); + trs = editor.body.firstChild.getElementsByTagName('tr'); + ua.checkSameHtml('hello1', tds[0].innerHTML, '第一个单元格有下划线和前景色'); +// equal('hello1', tds[0].innerHTML, '第一个单元格有下划线和前景色'); + ua.checkSameHtml('hello2', tds[1].innerHTML, '第2个单元格有前景色'); + ua.checkSameHtml('hello3', tds[2].innerHTML, '第3个单元格有前景色'); + equal(trs[1].firstChild.getAttribute('colspan'), 2, 'colspan为2'); + equal(editor.queryCommandState('underline'), true, '状态是underline'); + equal(editor.queryCommandState('forecolor'), 0, '非underline和line-through返回0'); + setTimeout(function () { + start(); + }, 100); + }, 100); + }, 100); + }, 100); + }, 50); +}); + +/*trace 740*/ +test('trace 740:设置左右字为红色,修改部分字颜色为蓝色,再修改所有字体', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + stop(); + editor.setContent('

    你好早安

    '); + range.selectNode(editor.body.firstChild).select(); + editor.execCommand('forecolor', 'rgb(255,0,0)'); + var text = editor.body.firstChild.firstChild.firstChild; + range.setStart(text, 2).setEnd(text, 4).select(); + editor.execCommand('forecolor', 'rgb(0,255,0)'); + range.setStart(editor.body.firstChild, 0).setEnd(editor.body.firstChild, 1).select(); + editor.execCommand('fontfamily', ' 楷体, 楷体_GB2312, SimKai; '); + setTimeout(function () { + var html = '你好早安'; + ua.checkSameHtml(html, editor.body.firstChild.innerHTML, '查看字体和颜色是否正确'); + start(); + }, 50); +}); + +/*trace 721*/ +test('trace 721:预先设置下划线和字体颜色,再输入文本,查看下划线颜色', function () { + if (!ua.browser.opera) { + var editor = te.obj[0]; + var range = te.obj[1]; + + editor.setContent('


    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('underline'); + editor.execCommand('forecolor', 'rgb(255,0,0)'); + range = editor.selection.getRange(); + range.insertNode(editor.document.createTextNode('hello')); + ua.manualDeleteFillData(editor.body); + var html = 'hello
    '; + ua.checkHTMLSameStyle(html, editor.document, editor.body.firstChild, '查看下划线颜色是否与字体颜色一致'); + + } +}); + + +test('trace 3342:字符ab, 给a 加边框再给b加边框,边框效果错误', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    hello

    '); + range.setStart(editor.body.firstChild.firstChild, 0).setEnd(editor.body.firstChild.firstChild, 2).select(); + editor.execCommand('fontborder'); + range.setStart(editor.body.firstChild.lastChild, 0).setEnd(editor.body.firstChild.lastChild, 2).select(); + editor.execCommand('fontborder'); +// var br = baidu.editor.browser.ie ? ' ' : '
    '; + if (ua.browser.ie && ua.browser.ie < 9) { + equal(ua.getChildHTML(editor.body.firstChild), "hello", '查看添加了字符边框后的样式'); + }else if(ua.browser.ie && ua.browser.ie == 11){ + equal(ua.getChildHTML(editor.body.firstChild), 'hello', '查看添加了字符边框后的样式'); + } + else { + equal(ua.getChildHTML(editor.body.firstChild), 'hello', '查看添加了字符边框后的样式'); + } +}); + +test('trace 3096:单元格中改变字号', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + var trs = editor.body.firstChild.getElementsByTagName('tr'); + trs[0].cells[0].innerHTML = 'asd'; + setTimeout(function () { + range.setStart(editor.body.firstChild.firstChild.firstChild.firstChild.firstChild, 0).setEnd(editor.body.firstChild.firstChild.firstChild.firstChild.firstChild, 3).select(); + editor.execCommand('fontsize', '32px'); + equal(editor.body.firstChild.getElementsByTagName('td')[0].style.height, '', '不固定高度'); + start(); + }, 50); + stop(); +}); + +test('转换font标签', function () { + var editor = te.obj[0]; + editor.setContent('x'); + var html = '

    x

    '; + ua.checkHTMLSameStyle(html, editor.document, editor.body, '转换font标签'); + editor.setContent('x'); + html = 'x'; + ua.checkHTMLSameStyle(html, editor.document, editor.body.firstChild, '转换font标签'); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/formatmatch.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/formatmatch.js new file mode 100644 index 000000000..423acfb32 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/formatmatch.js @@ -0,0 +1,373 @@ +module('plugins.formatmatch'); + +/*trace 973*/ +test('为一行无格式的文字刷2种不同的格式', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    first

    second

    third

    '); + setTimeout(function () { + var body = editor.body; + range.setStart(body.firstChild.firstChild.firstChild, 2).collapse(true).select(); + editor.execCommand('formatmatch'); + range.selectNode(body.lastChild.firstChild).select(); + ua.mouseup(body); + editor.addListener('mouseup', function () { + equal(editor.queryCommandState('formatmatch'), 0, '刷后状态为0'); + equal(body.lastChild.innerHTML.toLowerCase(), 'third'); + start(); + }); + range.setStart(body.lastChild.previousSibling.firstChild.firstChild, 2).collapse(true).select(); + editor.execCommand('formatmatch'); + range.selectNode(body.lastChild.firstChild).select(); + ua.mouseup(body); + /*editor自身还挂了一个mouseup侦听器,必须在用例执行前调用,否则_selectionChange方法调用无法取到window,会报错*/ + + }, 50); + stop(); +}); + +/*trace 971*/ +test('trace 971:有格式文字刷自己', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + editor.setContent('

    欢迎光临

    '); + setTimeout(function () { + var body = editor.body; + var text = body.firstChild.firstChild.firstChild; + range.setStart(text, 2).collapse(true).select(); + editor.addListener('mouseup', function () { + equal(editor.getContent(), '

    迎光临

    '); + start(); + }); + editor.execCommand('formatmatch'); + range.setStart(text, 0).setEnd(text, 1).select(); + ua.mouseup(editor.body); + + }, 50); + stop(); +}); +//TODO 1.2.6 +//test( 'trace 1553:居中的标题自己刷自己', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// editor.setContent( '

    欢迎使用UEditor编辑器

    ' ); +// setTimeout( function () { +// var body = editor.body; +// var text = body.firstChild.firstChild; +// range.setStart( text, 2 ).setEnd( text, 4 ).select(); +// editor.addListener( 'mouseup', function () { +// if ( (ua.browser.gecko && ua.browser.gecko < 2)||ua.browser.ie ==9) +// equal( editor.getContent(), '

    欢迎使用UEditor编辑器

    ' ); +// else +// equal( editor.getContent(), '

    欢迎使用UEditor编辑器

    ' ); +// } ); +// editor.execCommand( 'formatmatch' ); +// range.setStart( text, 5 ).setEnd( text, 6 ).select(); +// ua.mouseup( editor.body ); +// setTimeout( function () { +// start(); +// }, 500 ); +// }, 50 ); +// stop(); +//} ); + +/*trace:969*/ +test('格式刷的状态反射:非闭合区间', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('hello'); + setTimeout(function () { + var body = editor.body; + range.setStart(body.firstChild.firstChild, 2).collapse().select(); + editor.addListener('mouseup', function () { + equal(editor.queryCommandState('formatmatch'), 0, '刷后状态为0'); + start(); + }); + editor.execCommand('formatmatch'); + equal(editor.queryCommandState('formatmatch'), 1, '刷前状态为1'); + range.setStart(body.firstChild.firstChild, 0).setEnd(body.firstChild.firstChild, 2).select(); + /*格式刷侦听mouseup事件,select方法不能触发mouseup,因此必须手动触发*/ + ua.mouseup(editor.body); + + }, 50); + stop(); +}); + +/*trace 964*/ +test('默认格式图片刷有格式的图片', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('hello'); + setTimeout(function () { + var img = editor.body.firstChild.lastChild; + var img_new = img.previousSibling; + range.selectNode(img).select(); + editor.addListener('mouseup', function () { + equal(editor.queryCommandState('formatmatch'), 0, '刷后状态为0'); + if (!ua.browser.opera) { + equal(img_new.style.cssFloat || img_new.style.styleFloat, 'none', 'check style float', 'float'); + } + equal(img_new.style.backgroundColor, 'red', 'check background color'); + start(); + }); + editor.execCommand('formatmatch'); + range.selectNode(img_new).select(); + ua.mouseup(editor.body); + + }, 50); + stop(); +}); + +/*trace 965*/ +test('有浮动方式图片刷默认的图片', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('hello'); + setTimeout(function () { + var img = editor.body.firstChild.lastChild.previousSibling; + var img_new = img.nextSibling; + range.selectNode(img).select(); + editor.addListener('mouseup', function () { + equal(editor.queryCommandState('formatmatch'), 0, '刷后状态为0'); + if (!ua.browser.opera) { + equal(img_new.style.cssFloat || img_new.style.styleFloat, "left", 'check style float'); + } + /*只有浮动方式会刷,其他都不刷*/ + equal(img_new.style.backgroundColor, '', 'check background color'); + equal(img_new.style.width, '', 'check style width'); + equal($(img_new).attr('width'), 100, 'check width'); + start(); + }); + editor.execCommand('formatmatch'); + range.selectNode(img_new).select(); + ua.mouseup(editor.body); + + }, 50); + stop(); +}); + +/*trace 1068*/ +test('独占一行图片刷默认的图片', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('hello'); + setTimeout(function () { + var img = editor.body.firstChild.lastChild.previousSibling; + var img_new = img.nextSibling; + range.selectNode(img).select(); + editor.addListener('mouseup', function () { + equal(editor.queryCommandState('formatmatch'), 0, '刷后状态为0'); + if (!ua.browser.opera) { + equal(img_new.style.display, "block", 'check display block'); + } + start(); + }); + editor.execCommand('formatmatch'); + range.selectNode(img_new).select(); + ua.mouseup(editor.body); + + }, 50); + stop(); +}); + +/*trace 1068*/ +test('默认的图片图片刷独占一行图片', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('hello'); + setTimeout(function () { + var img = editor.body.firstChild.lastChild; + var img_new = img.previousSibling; + range.selectNode(img).select(); + editor.addListener('mouseup', function () { + equal(editor.queryCommandState('formatmatch'), 0, '刷后状态为0'); + if (!ua.browser.opera) { + equal(img_new.style.display, "inline", 'check display block'); + } + start(); + }); + editor.execCommand('formatmatch'); + range.selectNode(img_new).select(); + ua.mouseup(editor.body); + + }, 50); + stop(); +}); + +/*trace 939*/ +test('trace 939:字母列表刷表格内的字母列表', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('
    1. first
    2. second
    1. third
    2. fourth
    '); + setTimeout(function () { + range.selectNode(editor.body.firstChild).select(); + editor.execCommand('formatmatch'); + editor.addListener('mouseup', function () { + setTimeout(function () { + equal(editor.body.lastChild.getElementsByTagName('ol')[0].style.listStyleType, 'lower-alpha', '查看列表是否仍然是字母的'); + start(); + }, 250); + }); + range.selectNode(editor.body.lastChild).select(); + ua.mouseup(editor.body); + + }, 50); + stop(); +}); + +/*trace 938*/ +test('用格式刷刷整个表格', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    hello

    '); + setTimeout(function () { + range.selectNode(editor.body.firstChild).select(); + editor.addListener('mouseup', function () { + /*整个校验方法不好,没有解决根源的问题, + 校验的目的应当是不会多出不应当出现的内容,除了match还可能会有其他多出来的内容 + 但是style之类的东西比较难校验*/ + equal(editor.body.innerHTML.indexOf('match'), -1, '没有插入match占位符'); + start(); + }); + editor.execCommand('formatmatch'); + range.selectNode(editor.body.lastChild).select(); + editor.currentSelectedArr = [editor.body.lastChild.getElementsByTagName('td')[0]]; + ua.mouseup(editor.body); + + }, 50); + stop(); +}); + +test('表格刷文本', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    hello

    hello2
    '); + setTimeout(function () { + range.selectNode(editor.body.lastChild).select(); +// editor.currentSelectedArr = [editor.body.lastChild.getElementsByTagName('td')[0]]; + editor.addListener('mouseup', function () { + equal(editor.body.firstChild.innerHTML, 'hello', ' 去掉hello的格式'); + start(); + }); + editor.execCommand('formatmatch'); + setTimeout(function () { + range.selectNode(editor.body.firstChild).select(); + ua.mouseup(editor.body); + + }, 50); + }, 50); + stop(); +}); + +/*trace 1096*/ +test('trace 1096,1761:表格刷表格', function () { + + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    hello

    hello2
    hello3
    '); + setTimeout(function () { + var trs = editor.body.lastChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.lastChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[0]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + var tds = editor.body.lastChild.getElementsByTagName('td'); + editor.addListener('mouseup', function () { + ok(ua.isEqualArray(ut.selectedTds, [trs[0].cells[0], trs[1].cells[0]]), '比较选择的区域'); +// equal( editor.body.getElementsByTagName('table')[0].getAttribute( 'border' ), '1', '表格边框宽度相同' ); /*如果没有指定border,那么不主动设置border*/ +// equal( tds[index].style['borderWidth'], '1px', '表格边框宽度相同' ); +// equal( tds[index].style['borderStyle'], 'solid', '表格边框样式相同' ); + for (var index = 0; index < tds.length; index++) { + equal(tds[index].style['borderColor'], tds[0].style['borderColor'], '表格边框颜色相同'); + } + + start(); + }); + editor.execCommand('formatmatch'); +// editor.currentSelectedArr = [tds[1], tds[3]]; + range.setStart(tds[1], 0).setEnd(tds[3], 1).select(); + ua.mouseup(editor.body); +// }, 50); + }, 50); + stop(); +}); + +/*trace 1092, 991*/ +test('文本刷a标签(闭合)', function () { + + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('hellobaidu'); + setTimeout(function () { + + var p = editor.body.firstChild; + var a = p.lastChild; + range.selectNode(p.firstChild).select(); + /*给文本刷上前景色*/ + editor.execCommand('forecolor', 'rgb(255,0,0)'); + editor.addListener('mouseup', function () { + var a = p.lastChild; + ua.clearWhiteNode(a); + equal(a.childNodes.length, 3, '3子节点'); + //1.2版本中空的span里有删不掉的不可见字符,已经从浏览器复制过来了 + ua.checkHTMLSameStyle('baidu', editor.document, a, 'check style'); + start(); + }); + range.selectNode(p.firstChild).select(); + editor.execCommand('formatmatch'); + range.setStart(p.lastChild.firstChild, 2).collapse(true).select(); + ua.mouseup(editor.body); + + }, 50); + stop(); +}); + + + +test('点了格式刷后不刷文本再点一次格式刷', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    first

    second

    third

    '); + setTimeout(function () { + var body = editor.body; + range.setStart(body.firstChild.firstChild.firstChild, 2).collapse(true).select(); + editor.addListener('mouseup', function () { + equal(editor.__allListeners['mouseup'].length, num - 1, 'mouseup的侦听器被删除'); + equal(editor.queryCommandState('formatmatch'), 0, '刷后状态为0'); + equal(body.lastChild.innerHTML.toLowerCase(), 'third'); + + start(); + }); + editor.execCommand('formatmatch'); + var num = editor.__allListeners['mouseup'].length; + /*删除mouseup侦听器后直接返回*/ + editor.execCommand('formatmatch'); + equal(editor.__allListeners['mouseup'].length, num - 1, '如果第一次格式刷没执行,下一次格式刷会先去掉上一个mouseup的侦听器然后直接退出'); + ua.mouseup(body); + + }, 50); + stop(); +}); +test('a标签刷文本', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + setTimeout(function () { + editor.setContent('hellobaidu'); + setTimeout(function () { + var p = editor.body.firstChild; + var a = p.lastChild; + range.setStart(a.firstChild.firstChild, 1).collapse(true).select(); + editor.addListener('mouseup', function () { + /*firefox不支持outerHTML*/ + equal(p.firstChild.innerHTML, 'hello', 'span包含文本'); + ok(p.firstChild.style['color'], 'red', '查看文本是否添加了样式'); + start(); + }); + editor.execCommand('formatmatch'); + range.selectNode(p.firstChild).select(); + ua.mouseup(editor.body); + }, 50); + },50); + stop(); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/horizontal.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/horizontal.js new file mode 100644 index 000000000..032fa0121 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/horizontal.js @@ -0,0 +1,142 @@ +module( "plugins.horizontal" ); +//normal +test( 'horizontal', function() { + var editor = te.obj[0]; + var d = editor.document; + var range = te.obj[1]; + var db = editor.body; + + editor.setContent( 'top

    bottom

    ' ); + setTimeout(function(){ + range.setStart( d.getElementsByTagName( 'em' )[0].firstChild, 0 ).setEnd( db.lastChild.firstChild, 5 ).select(); + equal( editor.queryCommandState( "horizontal" ), 0, "边界不在table里" ); + editor.execCommand( 'horizontal' ); + var spase = ua.browser.ie?'':'
    '; + equal( ua.getChildHTML( db ), "


    m"+spase+"

    ", "边界不在table里" ); + start(); + },50); + stop(); +} ); +test( 'horizontal_br', function() {//trace 3854 + var div = document.body.appendChild(document.createElement('div')); + $(div).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + var editor = new baidu.editor.Editor({'initialContent':'

    欢迎使用ueditor

    ', 'autoFloatEnabled':false,enterTag:'br'}); + + editor.render(div); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + editor.setContent( '
    1. top

    ' ); + range.setStart( editor.body.firstChild.firstChild, 1 ).collapse( true ).select(); + editor.execCommand( 'horizontal' ); + range = editor.selection.getRange(); + var containger = (ua.browser.ie&&ua.browser.ie<9)?editor.body.getElementsByTagName('li')[0]:editor.body.getElementsByTagName('hr')[0].nextSibling; + var offset = (ua.browser.webkit||ua.browser.ie==11)?1:((ua.browser.ie&&ua.browser.ie<9)?3:0); + if(!ua.browser.opera){ + ua.checkResult( range,containger,containger, offset, offset, true, 'check range' ); + } + ua.manualDeleteFillData(editor.body); + equal( ua.getChildHTML( editor.body.firstChild ), "
  • top



  • ", "在列表中插入分隔线,在分隔线后面添加p用于定位" ); + setTimeout(function(){ + te.dom.push(div); + start(); + },50); + }); + stop(); +} ); +test( 'horizontal-delkeydown', function() { + var editor = te.obj[0]; + var d = editor.document; + var range = te.obj[1]; + var db = editor.body; + editor.setContent( 'top

    bottom

    ' ); + setTimeout(function(){ + range.setStart( d.getElementsByTagName( 'em' )[0].firstChild, 0 ).setEnd( db.lastChild.firstChild, 5 ).select(); + editor.execCommand( 'horizontal' ); + setTimeout(function(){ + range.setStart( editor.body.lastChild, 0 ).collapse(true).select(); + editor.fireEvent('delkeydown',{}); + var spase = ua.browser.ie?'':'
    '; + equal( ua.getChildHTML( db ), "

    m"+spase+"

    ", "删除分隔符" ); + start(); + },50); + },50); + stop(); +} ); + +test( '在列表中插入分隔线,回车符为p', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '
    1. top

    ' ); + range.setStart( body.firstChild.firstChild, 1 ).collapse( true ).select(); + editor.execCommand( 'horizontal' ); + range = editor.selection.getRange(); + var p = body.firstChild.firstChild.lastChild; + + var offset = ((ua.browser.ie&&ua.browser.ie>8&&ua.browser.ie<11)||ua.browser.gecko)?0:1; + if(!ua.browser.opera){ + ua.checkResult( range, p.firstChild, p.firstChild, offset, offset, true, 'check range' ); + } + ua.manualDeleteFillData(editor.body); + equal( ua.getChildHTML( body.firstChild ), "
  • top


  • ", "在列表中插入分隔线,在分隔线后面添加p用于定位" ); + +} ); + +//test( '在列表中插入分隔线,回车符为br', function() { +// +// var editor = new baidu.editor.Editor({'enterTag':'br'}); +// var div = document.body.appendChild(document.createElement('div')); +// editor.render(div); +// var range = new baidu.editor.dom.Range(editor.document); +// var body = editor.body; +// editor.setContent( '
    1. top
    ' ); +// range.setStart( body.firstChild.firstChild, 1 ).collapse( true ).select(); +// +// editor.execCommand( 'horizontal' ); +// +// var li = body.firstChild.firstChild; +// if ( !baidu.editor.browser.gecko ) { +// equal( ua.getChildHTML( body ), "
    1. top



    ", "在列表中插入分隔线,在分隔线后面添加p用于定位" ); +// } else { +// equal( ua.getChildHTML( body ), "
    1. top


    ", "ff在列表中插入分隔线" ); +// } +// te.dom.push(div); +//} ); + +//table +test( 'horizontal in table', function() { + var editor = te.obj[0]; + var d = editor.document; + var range = te.obj[1]; + editor.setContent( '
    1
    2
    ' ); + stop(); + setTimeout(function () { + range.setStart(d.getElementsByTagName('tr')[0].firstChild, 0).setEnd(d.getElementsByTagName('tr')[1].firstChild, 0).select(); + equal(editor.queryCommandState("horizontal"), -1, "边界在table里"); + start(); + }, 50); +} ); +//collapsed=true +test( 'horizontal&&collapsed', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var db = editor.body; + editor.setContent( 'top

    bottom

    ' ); + range.setStart( db.lastChild.firstChild, 0 ).collapse( true ).select(); + equal( editor.queryCommandState( "horizontal" ), 0, "边界不在table里" ); + editor.execCommand( 'horizontal' ); + var spase = ua.browser.ie?'':'
    '; + equal( ua.getChildHTML( db ), "

    top


    bottom"+spase+"

    ", "边界不在table里" ); +} ); +//TODO 1.2.6 +//test( 'trace 3338:horizontal&&enterTag', function() { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// editor.options.enterTag ='br'; +// editor.setContent( '
    1. top
    ' ); +// range.setStartAfter(editor.body.firstChild.firstChild.firstChild).collapse( true ).select(); +// editor.execCommand('horizontal'); +// ua.manualDeleteFillData(editor.body); +// var br = (ua.browser.ie && ua.browser.ie<9) || ua.browser.webkit?"
    ":""; +// equal(ua.getChildHTML(editor.body), '
    1. top


      '+br+'
    ', 'enterTag=br'); +//} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/iframe.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/iframe.js new file mode 100644 index 000000000..e8b60e98a --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/iframe.js @@ -0,0 +1,30 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-9-17 + * Time: 下午2:55 + * To change this template use File | Settings | File Templates. + */ +module( 'plugins.iframe' ); +test( '检查高亮和清除_iframe', function() { + var sc = document.createElement("script"); + sc.id="sc"; + sc.type = "text/plain"; + document.body.appendChild(sc); + te.obj[2].render('sc'); + + te.obj[2].ready(function(){ + equal( te.obj[2].queryCommandState( 'insertframe' ), 0, 'check insertframe state' ); + var iframe = document.createElement('iframe'); + $(iframe).attr('src','www.baidu.com'); + this._iframe = iframe; + this.setContent('

    欢迎使用ueditor!

    '); + ok(te.obj[2]._iframe,'加入_iframe'); + setTimeout(function(){ + ok(!te.obj[2]._iframe,'检查selectionchanged会触发去掉_iframe'); + document.getElementById('sc').parentNode.removeChild(document.getElementById('sc')); + start(); + },50); + }); + stop(); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/image.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/image.js new file mode 100644 index 000000000..9bb61ae28 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/image.js @@ -0,0 +1,204 @@ +module( 'plugins.image' ); +/** + * 插入视频 + * 插入图像 + * 选区闭合和不闭合 + * 表格中插入图像 + */ +/*trace1491 修改动图的宽高*/ +test( 'trace1491 修改动图的宽高', function () { + setTimeout(function () { + expect(3); + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('


    '); + setTimeout(function () { + range.setStart(body.firstChild, 0).collapse(1).select(); + editor.execCommand('insertimage', {src: '../data/test.JPG'}); + setTimeout(function () { + ua.manualDeleteFillData(editor.body); + range.selectNode(body.firstChild.firstChild).select(); + var img = body.getElementsByTagName('img')[0]; + editor.execCommand('insertimage', {src: '../data/test.JPG', width: 50, height: 80}); + setTimeout(function () { + equal($(img).attr('width'), '50', '比较width'); + equal($(img).attr('height'), '80', '比较width'); + ok(/data\/test\.JPG/.test(img.getAttribute('src')), '比较src'); + start(); + }, 500); + }, 100); + }, 100); + }, 100); + stop(); +} ); +test( '插入新图像', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '


    ' ); + range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); + editor.execCommand( 'insertimage', {src:'http://img.baidu.com/hi/jx2/j_0001.gif', width:50, height:51} ); + ua.manualDeleteFillData( editor.body ); + var img = body.getElementsByTagName( 'img' )[0]; + equal( img.getAttribute( 'src' ), 'http://img.baidu.com/hi/jx2/j_0001.gif', '比较src' ); + equal( img.getAttribute( 'width' ), '50', '比较width' ); + equal( img.getAttribute( 'height' ), '51', '比较height' ); +} ); + +/*trace 1490 不设宽高,插入图片*/ +test( 'trace 1490 不设宽高,插入图片', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '


    ' ); + range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); + editor.execCommand( 'insertimage', {src:'http://img.baidu.com/hi/jx2/j_0001.gif'} ); + ua.manualDeleteFillData( editor.body ); + var img = body.getElementsByTagName( 'img' )[0]; + equal( img.getAttribute( 'src' ), 'http://img.baidu.com/hi/jx2/j_0001.gif', '比较src' ); +} ); + +test( '插入对齐方式为居中对齐的图像,新建一个p,在p上设置居中对齐', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello

    ' ); + range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); + editor.execCommand( 'insertimage', {src:'http://img.baidu.com/hi/jx2/j_0001.gif', width:50, height:51, floatStyle:'center'} ); + ua.manualDeleteFillData( editor.body ); + + var img = body.getElementsByTagName( 'img' )[0]; + equal( body.childNodes.length, 2, '2个p' ); + var p = body.firstChild; + equal( p.style['textAlign'], 'center', '居中对齐' ); + ok( p.nextSibling.innerHTML.indexOf( 'hello' ) > -1, '第二个p里面是hello' ); //1.2版本在FF中,hello前有不可见字符 + if ( baidu.editor.browser.ie ) + equal( img.style['styleFloat'], '', 'float为空' ); + else + equal( img.style['cssFloat'], '', 'float为空' ); + equal( img.getAttribute( 'src' ), 'http://img.baidu.com/hi/jx2/j_0001.gif', '比较src' ); + equal( img.getAttribute( 'width' ), '50', '比较width' ); + equal( img.getAttribute( 'height' ), '51', '比较height' ); +} ); + +test( '修改已有图片的属性', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello

    ' ); + range.selectNode( body.firstChild.firstChild ).select(); + editor.execCommand( 'insertimage', {src:'http://img.baidu.com/hi/jx2/j_0018.gif'} ); + equal( ua.getChildHTML( body.firstChild ), 'hello', '检查插入的图像地址' ); + equal( body.firstChild.childNodes.length, 3, '2个img孩子' ); +} ); + + +test( '选区不闭合插入图像', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello1

    hello2

    ' ); + setTimeout(function(){ + range.setStart( body.firstChild.firstChild, 2 ).setEnd( body.lastChild, 2 ).select(); + editor.execCommand( 'insertimage', {src:'http://img.baidu.com/hi/jx2/j_0016.gif', width:'100', height:'100'} ); + ua.manualDeleteFillData( editor.body ); + equal( body.childNodes.length, 1, '只有一个p' ); + ua.clearWhiteNode(body.firstChild); + var img = body.firstChild.lastChild; + equal( img.getAttribute( 'src' ), 'http://img.baidu.com/hi/jx2/j_0016.gif', '比较src' ); + equal( img.getAttribute( 'width' ), '100', '比较width' ); + equal( img.getAttribute( 'height' ), '100', '比较height' ); + start(); + },50); + stop(); +} ); + +test( '图像设置左右浮动', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello1

    hello2

    ' ); + range.selectNode( body.lastChild.lastChild ).select(); + editor.execCommand( 'imagefloat', 'left' ); + equal( body.getElementsByTagName( 'img' )[0].style['cssFloat'] || body.getElementsByTagName( 'img' )[0].style['styleFloat'], 'left', '左浮动' ); +// equal( body.getElementsByTagName( 'img' )[0].style['float'], 'left', '左浮动' ); + equal( editor.queryCommandValue( 'imagefloat' ), 'left' ); + + editor.execCommand( 'imagefloat', 'right' ); + equal( body.getElementsByTagName( 'img' )[0].style['cssFloat'] || body.getElementsByTagName( 'img' )[0].style['styleFloat'], 'right', '右浮动' ); + equal( editor.queryCommandValue( 'imagefloat' ), 'right' ); + equal( editor.queryCommandState( 'imagefloat' ), 0, '图片被选中,因此图片菜单高亮' ); + range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); + equal( editor.queryCommandState( 'imagefloat' ), -1, '光标闭合,因此图片菜单高不高亮' ); + equal( editor.queryCommandValue( 'justify' ), 'left', '段落的对齐方式为左对齐' ); + equal( editor.queryCommandValue( 'imagefloat' ), 'none', '图片对齐方式在闭合情况获取为空' ) + range.selectNode( body.firstChild.firstChild ).select(); + equal( editor.queryCommandValue( 'imagefloat' ), 'none', '选中文本,因此图片菜单高不高亮' ); +} ); + +test( '左浮动变为默认的样式和居中', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello1

    hello2

    ' ); + range.selectNode( body.lastChild.lastChild ).select(); + editor.execCommand( 'imagefloat', 'none' ); + equal( ua.getFloatStyle( body.getElementsByTagName( 'img' )[0] ), '', '没有浮动方式' ); + equal( editor.queryCommandValue( 'imagefloat' ), 'none' ); + $( body.getElementsByTagName( 'img' )[0] ).css( 'float' ); + range.selectNode( body.getElementsByTagName( 'img' )[0] ).select(); + editor.execCommand( 'imagefloat', 'center' ); + equal( editor.queryCommandValue( 'imagefloat' ), 'center' ); + equal( body.childNodes.length, 3, '3个p,image被切出一个p出来了' ); + var p = body.childNodes[2]; + equal( p.tagName.toLowerCase(), 'p', '第2个是p' ); + equal( p.firstChild.tagName.toLowerCase(), 'img', 'p的孩子为image' ); + equal( ua.getFloatStyle( p.firstChild ), '', 'image对齐方式float为空' ); + equal( editor.queryCommandValue( 'justify' ), 'center', '段落的对齐方式为居中' ); +} ); + +test( ' 带有超链接的图片', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello1

    hello2

    ' ); + range.selectNode( body.lastChild.lastChild ).select(); + editor.execCommand( 'imagefloat', 'center' ); + var p = body.childNodes[2]; + equal( p.firstChild.tagName.toLowerCase(), 'a', 'p的孩子为a' ); + equal( ua.getFloatStyle( p.firstChild ), '', 'image对齐方式float为空' ); + equal( editor.queryCommandValue( 'justify' ), 'center', '段落的对齐方式为居中' ); + + editor.execCommand( 'imagefloat', 'left' ); + equal( p.firstChild.tagName.toLowerCase(), 'a', 'p的孩子为a' ); + equal( ua.getFloatStyle( p.firstChild.firstChild ), 'left', 'image对齐方式float为left' ); + + editor.execCommand( 'imagefloat', 'none' ); + equal( p.firstChild.tagName.toLowerCase(), 'a', 'p的孩子为a' ); + equal( ua.getFloatStyle( p.firstChild.firstChild ), '', 'image对齐方式float为空' ); +} ); + +test( ' 默认样式切换到居中再切换回默认,会把居中导致的3个p合并', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello2hello3

    ' ); + setTimeout( function () { + range.selectNode( body.getElementsByTagName( 'a' )[0] ).select(); + editor.execCommand( 'imagefloat', 'center' ); + var p = body.childNodes[1]; + equal( p.firstChild.tagName.toLowerCase(), 'a', 'p的孩子为a' ); + equal( ua.getFloatStyle( p.firstChild ), '', 'image对齐方式float为空' ); + equal( editor.queryCommandValue( 'justify' ), 'center', '段落的对齐方式为居中' ); + editor.execCommand( 'imagefloat', 'none' ); + equal( body.childNodes.length, 1, '3个p合并为1个' ); + + var a = body.firstChild.firstChild.nextSibling; + equal( a.tagName.toLowerCase(), 'a', 'p的孩子为a' ); + equal( a.firstChild.tagName.toLowerCase(), 'img', 'a的孩子是img' ); + equal( ua.getFloatStyle( a.firstChild ), '', 'image对齐方式float为空' ); + start(); + }, 50 ); + stop(); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/indent.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/indent.js new file mode 100644 index 000000000..daa2acaa5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/indent.js @@ -0,0 +1,233 @@ +module( 'plugins.indent' ); + +/*trace 1030*/ +test( '同时加缩进和段前距', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    hello1

    hello2

    '); + /*selectNode不能直接选body,否则在ff下回冒到外面去了,一直回冒到外面的html上去了*/ +// range.selectNode( editor.body ).select(); + setTimeout(function () { + range.setStart(editor.body.firstChild, 0).setEnd(editor.body.lastChild, 1).select(); + editor.execCommand('rowspacing', 15, 'top'); + editor.execCommand('indent'); +// stop() + + equal(editor.body.firstChild.style['textIndent'], '2em', '查看缩进量'); + equal(editor.queryCommandValue('rowspacing', 'top'), 15, '查询段前距'); + start(); + }, 50); + stop(); +} ); + +test( 'trace1241--首行缩进的状态反射', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello1

    ' ); + setTimeout(function(){ + range.setStart( editor.body.firstChild, 1 ).collapse( 1 ).select(); + equal( editor.queryCommandState( 'indent' ), 0, '开始没有缩进' ); + editor.execCommand( 'indent' ); + equal( editor.queryCommandState( 'indent' ), 1, '有缩进' ); + editor.execCommand( 'indent' ); + equal( editor.queryCommandState( 'indent' ), 0, '没有缩进' ); + start(); + },50); + stop(); +} ); + +/*trace 1031*/ +test( '缩进后再h1', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello1

    hello2

    ' ); + setTimeout(function () { + range.setStart(editor.body.firstChild, 0).setEnd(editor.body.lastChild, 1).select(); + editor.execCommand('indent'); + editor.execCommand('paragraph', 'h1'); + equal(editor.queryCommandValue('paragraph'), 'h1', '段落格式为h1'); + equal(editor.body.firstChild.style['textIndent'], '2em', '查看缩进量'); + start(); + }, 50); + stop(); +} ); + + +test( '先设h1再缩进', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello1

    hello2

    ' ); + setTimeout(function () { + range.setStart(editor.body.firstChild, 0).setEnd(editor.body.lastChild, 1).select(); + editor.execCommand('paragraph', 'h1'); + editor.execCommand('indent'); + equal(editor.queryCommandValue('paragraph'), 'h1', '段落格式为h1'); + equal(editor.body.firstChild.style['textIndent'], '2em', '查看缩进量'); + start(); + }, 50); + stop(); +} ); +/*trace 1479 首行缩进按钮功能有效*/ +test('trace 1479 首行缩进按钮功能有效',function(){ + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    hello

    '); + setTimeout(function () { + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('indent'); + equal(editor.body.firstChild.style['textIndent'], '2em', '选择文字,首行缩进');//text-indent:2em + equal(editor.queryCommandState('indent'), 1, '缩进按钮高亮'); + start(); + }, 50); + stop(); +}); +/*trace 1516 选Heading格式的文字首行缩进按钮高亮*/ +test('trace 1516 选Heading格式的文字首行缩进按钮高亮',function(){ + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello

    ' ); + setTimeout(function(){ + range.setStart(editor.body.firstChild,0).collapse(true).select(); + editor.execCommand( 'indent' ); + equal(editor.body.firstChild.style['textIndent'], '2em', '选Heading格式的文字首行缩进');//text-indent:2em + equal(editor.queryCommandState('indent'), 1, '缩进按钮高亮'); + start(); + },50); + stop(); +}); +test( '先对齐方式再缩进', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello1

    hello2

    ' ); + setTimeout(function () { + range.setStart(editor.body.firstChild, 0).setEnd(editor.body.lastChild, 1).select(); + editor.execCommand('justify', 'right'); + editor.execCommand('indent'); + equal(editor.queryCommandValue('justify'), 'right', '段落格式为h1'); + equal(editor.body.firstChild.style['textIndent'], '2em', '查看缩进量'); + start(); + }, 50); + stop(); +} ); + +test( '先缩进再对齐方式', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello1

    hello2

    ' ); + setTimeout(function () { + range.setStart(editor.body.firstChild, 0).setEnd(editor.body.lastChild, 1).select(); + editor.execCommand('indent'); + editor.execCommand('justify', 'right'); + equal(editor.queryCommandValue('justify'), 'right', '段落格式为h1'); + equal(editor.body.firstChild.style['textIndent'], '2em', '查看缩进量'); + start(); + }, 50); + stop(); +} ); + +/*trace 1033*/ +test( '非闭合取消缩进', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    hello1

    hello2

    '); + setTimeout(function () { + range.setStart(editor.body.firstChild, 0).setEnd(editor.body.lastChild, 1).select(); + editor.execCommand('indent'); + equal(editor.body.firstChild.style['textIndent'], '2em', '查看缩进量'); + editor.execCommand('indent'); + equal(editor.body.firstChild.style['textIndent'], '0em', '查看缩进量'); + start(); + }, 50); + stop(); +} ); + +test( '闭合取消缩进', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello1

    hello2

    ' ); + setTimeout(function () { + range.setStart(editor.body.firstChild, 0).setEnd(editor.body.lastChild, 1).select(); + editor.execCommand('indent'); + equal(editor.body.firstChild.style['textIndent'], '2em', '查看缩进量'); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + ua.manualDeleteFillData(editor.body); + editor.execCommand('indent'); + equal(editor.body.firstChild.style['textIndent'], '0em', '查看缩进量'); + start(); + }, 50); + stop(); +} ); + +//test( '表格内闭合缩进和取消缩进', function() { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// editor.setContent( '

    hello

    ' ); +// var tds = editor.body.firstChild.getElementsByTagName( 'td' ); +// range.setStart( tds[0], 0 ).collapse( true ).select(); +// editor.execCommand( 'indent' ); +// ua.manualDeleteFillData( editor.body ); +// equal( tds[0].firstChild.tagName.toLowerCase(), 'p', '插入一个p标签' ); +// equal( tds[0].firstChild.style['textIndent'], '2em', '查看缩进量' ); +// range.setStart( tds[0].firstChild, 0 ).collapse( true ).select(); +// te.presskey( '', 'h' ); +// setTimeout( function() { +// equal( tds[0].firstChild.style['textIndent'], '2em', '插入文本节点后查看缩进量' ); +// range.setStart( tds[0].firstChild, 0 ).collapse( true ).select(); +// editor.execCommand( 'indent' ); +// ua.manualDeleteFillData( editor.body ); +// equal( tds[0].firstChild.style['textIndent'], '0em', '取消缩进' ); +// /*选中一个单元格设置缩进*/ +// range.selectNode( tds[2] ).select(); +// editor.execCommand( 'indent' ); +// ua.manualDeleteFillData( editor.body ); +// equal( tds[2].firstChild.style['textIndent'], '2em', '查看缩进量' ); +// start(); +// }, 30 ); +// stop(); +//} ); + +test( '多个单元格缩进和取消缩进', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '
    hello1hello2
    hello3

    hello4

    ' ); + setTimeout(function () { + var tds = editor.body.firstChild.getElementsByTagName('td'); + range.selectNode(editor.body.firstChild).select(); + editor.execCommand('indent'); + ua.manualDeleteFillData(editor.body); + /*会自动在非block元素外面套p*/ + equal(tds[0].firstChild.tagName.toLowerCase(), 'p', '插入一个p标签'); + for (var index = 0; index < tds.length; index++) { + equal(tds[index].firstChild.style['textIndent'], '2em', '查看第' + (index + 1) + '个单元格的缩进量'); + } + range.selectNode(editor.body.firstChild).select(); + editor.execCommand('indent'); + for (index = 0; index < tds.length; index++) { + equal(tds[index].firstChild.style['textIndent'], '0em', '查看第' + (index + 1) + '个单元格的缩进是否被取消'); + } + start(); + }, 50); + stop(); +} ); + +/*trace 1097*/ +test( '列表中缩进', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '
    • nihao
    • hello
    ' ); + setTimeout(function () { + range.setStart(editor.body.firstChild.firstChild, 0).collapse(true).select(); + editor.execCommand('indent'); + var p = editor.body.firstChild.firstChild.firstChild; + equal(p.tagName.toLowerCase(), 'p', '自动创建一个p'); + equal(p.style['textIndent'], '2em', '设置缩进为2em'); + /*在有文本的列表中缩进*/ + range.setStart(editor.body.firstChild.lastChild.firstChild, 1).collapse(true).select(); + editor.execCommand('indent'); + p = editor.body.firstChild.lastChild.firstChild; + equal(p.tagName.toLowerCase(), 'p', '自动创建一个p'); + equal(p.style['textIndent'], '2em', '设置缩进为2em'); + start(); + }, 50); + stop(); +} ) \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/insertcode.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/insertcode.js new file mode 100644 index 000000000..4098c526e --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/insertcode.js @@ -0,0 +1,283 @@ +module('plugins.insertcode'); +//test('',function(){stop();}) +test('trace 3343:插入代码中有空行', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('hello'); + ua.keydown(editor.body, {'keyCode':65, 'ctrlKey':true}); + editor.execCommand('insertcode', 'Java'); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + ua.keydown(editor.body, {'keyCode':13}); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + ua.keydown(editor.body, {'keyCode':13}); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + range.insertNode(editor.document.createTextNode('hello')); + var br = ua.browser.ie ? '' : '
    '; + if (ua.browser.ie) + ua.checkSameHtml(editor.body.innerHTML, '

    hello​​
    ​​hello

    ', '插入代码'); + else if (ua.browser.gecko||ua.browser.webkit) + ua.checkSameHtml(editor.body.innerHTML, '
    hello

    hello
    ', '插入代码'); + else + ua.checkSameHtml(editor.body.innerHTML, '
    hello

    hello

    ' + br + '

    ', '插入代码'); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + var br = ua.browser.ie ? '' : '
    '; + if (ua.browser.ie&&ua.browser.ie<9) + ua.checkSameHtml(editor.body.innerHTML, "
    hello
    hello

     

    ", '样式不变'); + + else if (ua.browser.gecko||ua.browser.webkit) + ua.checkSameHtml(editor.body.innerHTML, '
    hello

    hello
    ', '样式不变'); + start(); + }, 20); + }, 20); + stop(); +}); + +test('trace 3355:不闭合选区插入代码', function () { + var editor = te.obj[0]; + var code = '<div id="upload" style="display: none" ><img id="uploadBtn"></div>'; + editor.setContent(code); + setTimeout(function () { + ua.keydown(editor.body, {'keyCode': 65, 'ctrlKey': true}); + editor.execCommand('insertcode', 'html'); + var br = ua.browser.ie ? '' : '
    '; + if (ua.browser.gecko || ua.browser.opera ||ua.browser.webkit) + ua.checkSameHtml(editor.body.innerHTML, '
    <div id=\"upload\" style=\"display: none\" ><img id=\"uploadBtn\"></div>
    ', '检查插入了html'); + else + ua.checkSameHtml(editor.body.innerHTML, '
    <div id=\"upload\" style=\"display: none\" ><img id=\"uploadBtn\"></div>

    ' + br + '

    ', '检查插入了html'); + start(); + }, 50); + stop(); +}); + +test('trace 3395:插入代码为空时,清空编辑器', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent(''); + editor.execCommand('insertcode', 'html'); + var br = ua.browser.ie ? ' ' : '
    '; + if (ua.browser.gecko||ua.browser.ie > 10) + ua.checkSameHtml(editor.body.firstChild.outerHTML, '

    ', '检查插入了html'); + else if (ua.browser.ie > 8) + ua.checkSameHtml(editor.body.firstChild.outerHTML, '
    ', '检查插入了html');
    +        else
    +            ua.checkSameHtml(editor.body.firstChild.outerHTML, '
    ' + br + '
    ', '检查插入了html'); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + range.insertNode(editor.document.createTextNode('hello'));//TODO bug修复把此行删除 + ua.keydown(editor.body, {'keyCode':65, 'ctrlKey':true}); + ua.keydown(editor.body, {'keyCode':8}); + br = ua.browser.ie ? '' : '
    '; + ua.checkSameHtml(editor.body.innerHTML, '

    ' + br + '

    ', '检查编辑器清空'); +}); + +test('trace 3396:多次切换源码,不会产生空行', function () { + var editor = te.obj[0]; + + editor.setContent('

    <body>

    </body>

    '); + ua.keydown(editor.body, {'keyCode':65, 'ctrlKey':true}); + editor.execCommand('insertcode', 'html'); + var br = (ua.browser.ie==9||ua.browser.ie==10) ? '\n' : '
    '; + var p = editor.body.firstChild.outerHTML.toLowerCase(); + var x ='\"'; + if(ua.browser.ie<9&&ua.browser.ie)x=''; + equal(p, '
    <body>'+br+'</body>
    ', '检查插入了html') + ua.checkSameHtml(editor.body.firstChild.outerHTML, '
    <body>'+br+'</body>
    ', '检查插入了html'); + + //todo 1.3.6 3853 + + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + var end = (ua.browser.ie==9||ua.browser.ie==10) ?'':'
    '; + br =(ua.browser.ie==9||ua.browser.ie==10) ?'\n':'
    '; + var Bbr =( ua.browser.ie&&ua.browser.ie<9)?'\n':''; + ua.checkSameHtml(editor.body.firstChild.innerHTML, '<body>'+Bbr+br+'</body>'+end, '切回源码无影响'); +// setTimeout(function() {//TODO bug修复后去掉注释 +// editor.execCommand('source'); +// setTimeout(function() { +// editor.execCommand('source'); +// ua.checkSameHtml(editor.body.firstChild.innerHTML,'<body>
    </body>
    ','切回源码无影响'); +// setTimeout(function () { +// UE.delEditor('ue'); +// document.getElementById('ue')&&te.dom.push(document.getElementById('ue')); + start(); + }, 20); + }, 20); + + stop(); +}); + +test('trace 3407:表格中插入代码', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent(''); + editor.execCommand('inserttable'); + stop(); + setTimeout(function () { + var tds = editor.body.getElementsByTagName('td'); + tds[1].innerHTML = 'asd'; + range.setStart(tds[1], 0).setEnd(tds[1], 1).select(); + editor.execCommand('insertcode', 'Javascript'); + var br = ua.browser.ie ? ' ' : '
    '; + ua.checkSameHtml(tds[1].innerHTML, '
    asd
    ', '检查插入了html'); +// stop(); +// setTimeout(function() {//TODO bug +// editor.execCommand('source'); +// setTimeout(function() { +// editor.execCommand('source'); +// ua.checkSameHtml(tds[1].innerHTML,'
    asd

    ','切回源码无影响'); +// start(); +// },20); +// },20); + start(); + }, 50); +}); + + +test('test-beforeInsertHTML', function(){ + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + //闭合 + range.setStart(editor.body.firstChild,0).collapse(true).select(); + var insert = 'text'; + editor.execCommand('inserthtml', insert); + if(ua.browser.ie==9||ua.browser.ie==10) + ua.checkSameHtml(editor.body.innerHTML, '
    '+insert+'
    ', '插入IE'); + else + ua.checkSameHtml(editor.body.innerHTML, '
    '+insert+'
    ', '插入chrome/ff/ie11+'); + ua.manualDeleteFillData(editor.body); + + //插入非br element + range.setStart(editor.body.firstChild.firstChild,0).collapse(true).select(); + insert='

    I

    '; + editor.execCommand('inserthtml', insert); + if(ua.browser.ie==9||ua.browser.ie==10) + ua.checkSameHtml(editor.body.innerHTML, '
    Itext
    ', '插入IE'); + else + ua.checkSameHtml(editor.body.innerHTML, '
    Itext
    ', '插入chrome/ff/ie11+'); + ua.manualDeleteFillData(editor.body); + + //插入br element + range.setStart(editor.body.firstChild.firstChild,1).collapse(true).select(); + insert='
    br'; + editor.execCommand('inserthtml', insert); + if(ua.browser.ie==9||ua.browser.ie==10){ + ua.checkSameHtml(editor.body.innerHTML, '
    \nbrItext
    ', '插入IE'); + + } + else if(ua.browser.ie>10){ + ua.checkSameHtml(editor.body.innerHTML, '
    I\nbrtext
    ', '插入IE11+'); + } + else{ + ua.checkSameHtml(editor.body.innerHTML, '
    I​
    brtext
    ', '插入chrome/ff');} + ua.manualDeleteFillData(editor.body); + + //混合标签 + range.setStart(editor.body.firstChild,0).collapse(true).select(); + insert='

    PPP

    222

    SSS
    BBB

    '; + editor.execCommand('inserthtml', insert); + if(ua.browser.ie==9||ua.browser.ie==10){ +// if(ua.browser.ie<11){ + ua.checkSameHtml(editor.body.innerHTML, '
    PPP222SSS\nBBB\nbrItext
    ', '插入IE'); +// }else{ +// ua.checkSameHtml(editor.body.innerHTML, '
    PPP222SSS\nBBBI\nbrtext
    ', '插入IE'); +// } + } + else if(ua.browser.ie>10){ + ua.checkSameHtml(editor.body.innerHTML, '
    PPP222SSS\nBBBI\nbrtext
    ', '插入IE11+'); + } + else{ + ua.checkSameHtml(editor.body.innerHTML, '
    PPP222SSS
    BBBI
    brtext
    ', '插入chrome/ff/ie11+'); + } + ua.manualDeleteFillData(editor.body); + + //非闭合 + //插入非element + range.setStart(editor.body.firstChild, 0).setEnd(editor.body.firstChild, 4).select(); + insert = 'replace'; + editor.execCommand('inserthtml', insert); + if(ua.browser.ie==9||ua.browser.ie==10) + ua.checkSameHtml(editor.body.innerHTML, '
    replace
    ', '插入IE'); + else if(ua.browser.ie>10){ + ua.checkSameHtml(editor.body.innerHTML, '
    replace
    ', '插入IE11+'); + + } + else + ua.checkSameHtml(editor.body.innerHTML, '
    replaceBBBI
    brtext
    ', '插入chrome/ff/ie11+'); + ua.manualDeleteFillData(editor.body); + //插入element + range.setStart(editor.body.firstChild, 0).setEnd(editor.body.firstChild, 0).select(); + insert = '

    PPP

    '; + editor.execCommand('inserthtml', insert); + if(ua.browser.ie==9||ua.browser.ie==10) + ua.checkSameHtml(editor.body.innerHTML, '
    PPPreplace
    ', '插入IE'); + else if(ua.browser.ie>10){ + ua.checkSameHtml(editor.body.innerHTML, '
    PPPreplace
    ', '插入IE11+'); + + } + else + ua.checkSameHtml(editor.body.innerHTML, '
    PPPreplaceBBBI
    brtext
    ', '插入chrome/ff/ie11+'); + ua.manualDeleteFillData(editor.body); + +}); + +test('关于pre中的tabKey',function(){ + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('
    function a(){var a = true;}
    '); + var text = editor.body.firstChild.firstChild; + range.setStart(text,13).setEnd(text,16).select(); + ua.keydown(editor.body,{'shiftKey':false,'keyCode':9}); + ua.keyup(editor.body,{'shiftKey':false,'keyCode':9}); + if(ua.browser.ie==8||ua.browser.ie==9){ + equal(editor.getContent(),'
        function a(){var a = true;}
    '); + }else if(ua.browser.ie>9){ + equal(editor.getContent(),'
        function a(){var a = true;}
    ','验证pre下tabKey1'); + }else{ + equal(editor.getContent(),'
        function a(){var a = true;}
    ','验证pre下tabKey1'); + } + editor.setContent('

    function a(){var a = true;}
    '); + var text = editor.body.firstChild.firstChild; + range.setStart(text,13).setEnd(text,16).select(); + ua.keydown(editor.body,{'shiftKey':false,'keyCode':9}); + ua.keyup(editor.body,{'shiftKey':false,'keyCode':9}); + if(ua.browser.ie==8||ua.browser.ie==9){ + var x = '\n'; + if(ua.browser.ie==9){ + x = ''; + } + equal(editor.getContent(),'
        '+x+'function a(){var a = true;}
    ','验证pre下tabKey2'); + }else if(ua.browser.ie>9){ + var x2 = ''; + var x3 = '    '; + if(ua.browser.ie==11){ + x2 = '    '; + x3='\n'; + } + equal(editor.getContent(),'
    '+x3+'function a(){var a = true;}
    '+x2,'验证pre下tabKey2'); + }else{ + equal(editor.getContent(),'
    \n        function a(){var a = true;}
    ','验证pre下tabKey2'); + } + editor.setContent('
    function a(){
    var a = true;}
    '); + var text = editor.body.firstChild.firstChild; + range.setStart(text,13).setEnd(text,16).select(); + ua.keydown(editor.body,{'shiftKey':false,'keyCode':9}); + ua.keyup(editor.body,{'shiftKey':false,'keyCode':9}); + if(ua.browser.ie==8){ + equal(editor.getContent(),'
    function a(){    \nvar a = true;}
    ','验证pre下tabKey3'); + }else if(ua.browser.ie>8){ + var xx = '    '; + var xx2 = ''; + if(ua.browser.ie==11){ + xx = ''; + xx2 = '    '; + } + equal(editor.getContent(),'
    '+xx+'function a(){'+xx2+'\nvar a = true;}
    ','验证pre下tabKey3'); + }else{ + equal(editor.getContent(),'
    function a(){    \nvar a = true;}
    ','验证pre下tabKey3'); + } +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/inserthtml.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/inserthtml.js new file mode 100644 index 000000000..f0001799f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/inserthtml.js @@ -0,0 +1,179 @@ +module( "plugins.inserthtml" ); +test( '向span里面插入p', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('
    hello1
    '); + range.setStart(editor.body.firstChild.firstChild, 0 ).collapse(true).select(); + editor.execCommand( 'inserthtml','

    hello3

    ' ); + stop(); + setTimeout(function(){ +// equal(editor.body.innerHTML.toLowerCase(),'

    hello3

    hello1
    ','向span里面插入p'); + ua.checkSameHtml(editor.body.getElementsByTagName('address')[0].innerHTML.toLowerCase(),'

    hello3

    hello1','向span里面插入p'); + start(); + },50); +}); +//列表中插入列表 TODO 1.2.6 trace 3413 +//test( '列表中插入列表 trace 3413', function() { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// editor.setContent('
    1. hello1

    2. hello2

    '); +// var lis = editor.body.getElementsByTagName('li'); +// range.setStart( lis[1], 0 ).collapse(true).select(); +// editor.execCommand( 'inserthtml','
    • hello3

    ' ); +// stop(); +// setTimeout(function(){ +// lis = editor.body.getElementsByTagName('li'); +// equal(lis.length,3,'列表长度'); +// equal(lis[1].innerHTML.toLowerCase(),'

    hello3

    ','列表中插入列表'); +// start(); +// },50); +// +//}); + +test( 'trace 3301:闭合方式插入文本', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '


    ' ); + range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); + editor.execCommand( 'inserthtml', 'hello2' ); + equal( ua.getChildHTML( body ), '

    hello2

    ', '插入文本节点' ); +} ); + +test( '选中多个单元格插入列表', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '
    ' ); + setTimeout(function(){ + + var trs = editor.body.firstChild.getElementsByTagName( 'tr' ); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0],trs[0].cells[1]); + ut.setSelected(cellsRange); + if(ua.browser.ie) + range.setStart( trs[0].cells[0], 0 ).collapse( true ).select(); + var tds = body.firstChild.getElementsByTagName( 'td' ); + editor.execCommand( 'inserthtml', '
    1. hello
    ' ); + equal( tds[0].firstChild.tagName.toLowerCase(), 'ol', '插入列表' ); + equal( ua.getChildHTML( tds[0].firstChild ), '
  • hello

  • ', '查询列表内容' ); + //空的td有br + var br = ua.browser.ie?'':'
    '; + ua.manualDeleteFillData(tds[1]); + equal( tds[1].innerHTML, br, '第二个单元格没有插入任何东西' ); + start(); + },50); + stop(); +} ); + +test( '表格中插入图片', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '
    ' ); + setTimeout(function(){ + var trs = editor.body.firstChild.getElementsByTagName( 'tr' ); + + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[0].cells[1]); + ut.setSelected(cellsRange); + if (ua.browser.ie) + range.setStart( trs[0].cells[0], 0 ).collapse( true ).select(); + var tds = body.firstChild.getElementsByTagName( 'td' ); + editor.execCommand( 'inserthtml', '' ); + equal( tds[0].firstChild.tagName.toLowerCase(), 'img', '插入图片' ); + equal( tds[0].firstChild.style['styleFloat']||tds[0].firstChild.style['cssFloat'], 'left', '查询图片浮动方式' ); + var br = ua.browser.ie?'':'
    '; + ua.manualDeleteFillData(tds[1]); + equal( tds[1].innerHTML, br, '第二个单元格没有插入任何东西' ); + start(); + },50); + stop(); +} ); +//test('',function(){stop()}); +test( '选中多个单元格插入超链接', function() { + if(ua.browser.ie>8)return ;//TODO 1.2.6 + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '
    ' ); + setTimeout(function(){ + var trs = editor.body.firstChild.getElementsByTagName( 'tr' ); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0],trs[0].cells[1]); + ut.setSelected(cellsRange); + if(ua.browser.ie&&ua.browser.ie<9) + range.setStart( trs[0].cells[0], 0 ).collapse( true ).select(); + editor.execCommand( 'link', {href:'http://www.baidu.com/'} ); + var tds = body.firstChild.getElementsByTagName( 'td' ); + equal( tds[0].firstChild.tagName.toLowerCase(), 'a', '插入超链接' ); + var br = ua.browser.ie?'':'
    '; + equal( ua.getChildHTML(tds[0]), 'http://www.baidu.com/'+(ua.browser.ie>8?' ':br), '查询第一个表格插入的超链接' ); + + equal( ua.getChildHTML(tds[1]), br, '第二个单元格也插入超链接' ); + start(); + },50); + stop(); +} ); + +test( 'trace 3297:notSerialize', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '


    ' ); + setTimeout(function(){ + range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); + editor.execCommand( 'inserthtml', '

    b

    _ueditor_page_break_tag_' ,false); + equal( editor.body.childNodes.length, 3, 'notSerialize=false 插入分页符' ); + equal( editor.body.childNodes[1].tagName.toLowerCase(), 'hr', '插入分页符 hr class=\"pagebreak\" ' ); + equal( editor.body.childNodes[1].className.toLowerCase(), "pagebreak", '插入分页符 hr class=\"pagebreak\" ' ); + editor.setContent( '


    ' ); + setTimeout(function(){ + range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); + editor.execCommand( 'inserthtml', '

    b

    _ueditor_page_break_tag_' ,true); + equal( editor.body.childNodes.length, 3, 'notSerialize=true 插入分页符' ); + equal( editor.body.childNodes[1].innerHTML , '_ueditor_page_break_tag_', '插入分页符'); + start(); + },50); + },50); + stop(); +} ); + +//列表中插入表格 +test( '列表中插入表格', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('
    '); + var lis = editor.body.getElementsByTagName('li'); + range.setStart( lis[0], 0 ).collapse(true).select(); + editor.execCommand( 'inserttable', {numCols:2, numRows:2}); + stop(); + setTimeout(function(){ + equal(lis.length,1,'列表长度没有变化'); + equal(lis[0].firstChild.tagName.toLowerCase(),'table','列表中插入表格'); + start(); + },50); +}); +//刘表中插入img +test( '列表中插入img', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('
    '); + var lis = editor.body.getElementsByTagName('li'); + range.setStart( lis[0], 0 ).collapse(true).select(); + editor.execCommand( 'insertimage', {src:'http://img.baidu.com/hi/jx2/j_0001.gif', width:50, height:51} ); + stop(); + setTimeout(function(){ + equal(lis.length,1,'列表长度没有变化'); + ua.manualDeleteFillData(lis[0]); + if(ua.browser.ie){ + equal(lis[0].firstChild.firstChild.tagName.toLowerCase(),'img','列表中插入img'); + equal(lis[0].firstChild.firstChild.attributes['src'].nodeValue,'http://img.baidu.com/hi/jx2/j_0001.gif','列表中插入img'); + } + else{ + equal(lis[0].firstChild.tagName.toLowerCase(),'img','列表中插入img'); + equal(lis[0].firstChild.attributes['src'].nodeValue,'http://img.baidu.com/hi/jx2/j_0001.gif','列表中插入img'); + } + start(); + },50); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/insertparagraph.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/insertparagraph.js new file mode 100644 index 000000000..815c357e8 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/insertparagraph.js @@ -0,0 +1,15 @@ +module( 'plugins.insertparagraph' ); + +test( '插入空行', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( 'hello' ); + range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); + editor.execCommand( 'insertparagraph', true ); + var br = ua.browser.ie?'':'
    ' + equal( ua.getChildHTML( body ), '

    '+br+'

    hello

    ', '插入空行' ); + range.setStart( body.firstChild.nextSibling, 0 ).collapse( 1 ).select(); + editor.execCommand( 'insertparagraph', false ); + equal( ua.getChildHTML( body ), '

    '+br+'

    hello

    '+br+'

    ', '' ); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/justify.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/justify.js new file mode 100644 index 000000000..235a54167 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/justify.js @@ -0,0 +1,88 @@ +module( "plugins.justify" ); + +test( '闭合在段落中设置对齐方式', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello1

    ' ); + setTimeout(function(){ + range.setStart( body.firstChild.firstChild.firstChild, 3 ).collapse( true ).select(); + editor.execCommand( 'justify', 'center' ); + equal( body.firstChild.style['textAlign'], 'center', 'p对齐方式为居中对齐' ); + start(); + },50); + stop(); +} ); + +test( '不闭合在段落中设置对齐方式', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello1

    hello2hello3

    ' ); + setTimeout(function(){ + range.selectNode( body.firstChild.firstChild.firstChild ).select(); + editor.execCommand( 'justify', 'center' ); + equal( body.firstChild.style['textAlign'], 'center', 'p对齐方式为居中对齐' ); + + range.setStart( body.firstChild, 0 ).setEnd( body.lastChild, 1 ).select(); + editor.execCommand( 'justify', 'right' ); + equal( body.firstChild.style['textAlign'], 'right', 'p对齐方式为居中对齐' ); + equal( body.lastChild.style['textAlign'], 'right', 'p对齐方式为居中对齐' ); + + range.setStart( body.firstChild.firstChild.firstChild, 3 ).collapse( true ).select(); + editor.execCommand( 'justify', 'center' ); + equal( body.firstChild.style['textAlign'], 'center', 'p对齐方式为居中对齐' ); + start(); + },50); + stop(); +} ); + +//test( '对齐方式-参数为json', function() { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// editor.setContent( '

    hello

    ' ); +// setTimeout(function(){ +// var tds = editor.body.getElementsByTagName( 'td' ); +// range.setStart( tds[1].firstChild, 0 ).collapse( true ).select(); +// editor.execCommand( 'justify', 'right' ); +// equal( tds[1].firstChild.style['textAlign'], 'right', 'p对齐方式为右对齐' ); +// equal( editor.queryCommandValue( 'justify' ), 'right', 'querycommand value' ); +// start(); +// },50); +// stop(); +//} ); + +test( 'startContainer是body', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    tell

    ' ); + setTimeout(function(){ + range.setStart( editor.body, 0 ).collapse( true ).select(); + editor.execCommand( 'justify', 'right' ); + + equal( editor.queryCommandValue( 'justify' ), 'right', 'startContainer 是body' ); + equal( editor.queryCommandValue( 'justify' ), 'right', 'querycommand value' ); + /*json格式的参数*/ + range.setStart( editor.body, 0 ).collapse( true ).select(); + editor.execCommand( 'justify', {'text-align':'left'} ); + equal( editor.queryCommandValue( 'justify' ), 'left', 'startContainer 是body--json格式的参数' ); + start(); + },50); + stop(); +} ); + +test( '连续2次设置对齐方式', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    tell

    ' ); + setTimeout(function(){ + range.setStart( editor.body.firstChild.firstChild, 0 ).collapse( 1 ).select(); + editor.execCommand( 'justify', 'right' ); + equal( editor.queryCommandValue( 'justify' ), 'right', 'querycommand value' ); + range.setStart( editor.body.firstChild.firstChild, 0 ).collapse( 1 ).select(); + editor.execCommand( 'justify', 'center' ); + equal( editor.queryCommandValue( 'justify' ), 'center', 'querycommand value' ); + start(); + },50); + stop(); +} ); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/keystrokes.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/keystrokes.js new file mode 100644 index 000000000..fbd747902 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/keystrokes.js @@ -0,0 +1,277 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-10-9 + * Time: 下午6:52 + * To change this template use File | Settings | File Templates. + */ +module( "plugins.keystrokes" ); + +test('trace 3714跨节点输入tab键',function(){ + var editor = te.obj[0]; + editor.setContent( '

    hello

    heoll

    ' ); + var range = te.obj[1]; + setTimeout(function(){ + range.setStart( editor.body.lastChild.firstChild,0 ).setEnd(editor.body.lastChild.firstChild.nextSibling,1).select(); + ua.keydown(editor.body,{'keyCode':9}); + ua.keyup(editor.body,{'keyCode':9}); + setTimeout(function(){ + equal(te.obj[0].undoManger.list.length,1,''); + var html = '

    hello

        oll

    '; + equal(ua.getChildHTML(te.obj[0].body),html,'跨节点输入tab键'); + start(); + },20); + },20); + stop(); +}); + +test('删除块元素,块元素在后',function(){ + var editor = te.obj[0]; + editor.setContent( '

    hello

    ' ); + var range = te.obj[1]; + setTimeout(function(){ + range.setStart( editor.body.lastChild.lastChild,0 ).setEnd(editor.body.lastChild.lastChild,1).select(); + ua.keydown(editor.body,{'keyCode':8}); + ua.keyup(editor.body,{'keyCode':8}); + setTimeout(function(){ + equal(te.obj[0].undoManger.index,1,''); + var html = '

    hello

    '; + if(!ua.browser.opera) + equal(ua.getChildHTML(te.obj[0].body),html,'删除块元素'); + start(); + },20); + },20); + stop(); +}); + +test('删除块元素,块元素在前',function(){ + var editor = te.obj[0]; + editor.setContent( '

    hello

    ' ); + var range = te.obj[1]; + setTimeout(function(){ + range.setStart( editor.body.firstChild,0 ).setEnd(editor.body.firstChild,1).select(); + ua.keydown(editor.body,{'keyCode':8}); + ua.keyup(editor.body,{'keyCode':8}); + setTimeout(function(){ + equal(te.obj[0].undoManger.index,1,''); + var html = '

    hello

    '; + equal(ua.getChildHTML(te.obj[0].body),html,'删除块元素'); + start(); + },20); + },20); + stop(); +}); + +test('trace 2747 普通情况,选中一个节点,输入tab键',function(){ + var editor = te.obj[0]; + editor.setContent( '

    hello

    heoll

    ' ); + var range = te.obj[1]; + setTimeout(function(){ + range.setStart( editor.body.lastChild,1 ).setEnd(editor.body.lastChild,2).select(); + ua.keydown(editor.body,{'keyCode':9}); + ua.keyup(editor.body,{'keyCode':9}); + setTimeout(function(){ + equal(te.obj[0].undoManger.list.length,1,''); + var html = '

    hello

    he    oll

    '; + equal(ua.getChildHTML(te.obj[0].body),html,'普通情况,选中一个节点,输入tab键'); + start(); + },20); + },20); + stop(); +}); + +test('trace 2746 删除自闭合标签',function(){ + var editor = te.obj[0]; + editor.setContent( '

    hello

    heoll

    ' ); + var range = te.obj[1]; + setTimeout(function(){ + range.setStart( editor.body.lastChild,1 ).setEnd(editor.body.lastChild,2).select(); + ua.keydown(editor.body,{'keyCode':8}); + ua.keyup(editor.body,{'keyCode':8}); + setTimeout(function(){ + equal(te.obj[0].undoManger.index,1,''); + var html = '

    hello

    heoll

    '; + equal(ua.getChildHTML(te.obj[0].body),html,'删除自闭合标签'); + start(); + },20); + },20); + stop(); +}); + +test('全选后,退格,剩下空p',function(){ + var editor = te.obj[0]; + editor.setContent( 'hello' ); + var range = te.obj[1]; + range.selectNode( editor.body.firstChild ).select(); + editor.execCommand( 'bold' ); + editor.execCommand('selectall'); + ua.keydown(editor.body,{'keyCode':8}); + ua.keyup(editor.body,{'keyCode':8}); + stop(); + setTimeout(function(){ + var br = ua.browser.ie?'':'
    '; + equal(ua.getChildHTML(te.obj[0].body),'

    '+br+'

    ','全选后,退格,剩下空p'); + start(); + },20); +}); +//TODO 1.2.6 +//test('针对ff下在列表首行退格,不能删除空格行的问题 ',function(){ +// if(ua.browser.gecko){ +// var editor = te.obj[0]; +// editor.body.innerHTML = '

    欢迎使用ueditor!


    '; +// var range = te.obj[1]; +// setTimeout(function(){ +// range.setStartAtFirst(editor.body.firstChild).collapse(true); +// ua.keyup(te.obj[0].body,{'keyCode':8}); +// setTimeout(function(){ +// equal(ua.getChildHTML(editor.body),'

    欢迎使用ueditor!

    ','删除空行 '); +// start(); +// },20); +// },20); +// stop(); +// } +//}); + +test('在列表中,跨行选中第2,3行,输入tab键',function(){ + var editor = te.obj[0]; + editor.setContent( '
    1. 欢迎使用

    2. ueditor

    3. ueditor

    ' ); + var range = te.obj[1]; + setTimeout(function(){ + range.setStart( editor.body.childNodes[0].childNodes[1].firstChild.firstChild,1 ).setEnd(editor.body.childNodes[0].childNodes[2].firstChild.firstChild,1 ).select(); + ua.keydown(editor.body,{'keyCode':9}); + ua.keyup(editor.body,{'keyCode':9}); + setTimeout(function(){ + ua.manualDeleteFillData(te.obj[0].body); + equal(te.obj[0].body.firstChild.tagName.toLowerCase(),'ol','原列表'); + equal($(te.obj[0].body.firstChild).css('list-style-type'),'decimal','原列表类型'); + equal(ua.getChildHTML(te.obj[0].body.firstChild.firstChild),'

    欢迎使用

    ','第一行保持原来的列表样式'); + equal(te.obj[0].body.firstChild.lastChild.tagName.toLowerCase(),'ol','后两行变成第二层列表'); + equal($(te.obj[0].body.firstChild.lastChild).css('list-style-type'),'lower-alpha','第二层列表类型'); + equal(ua.getChildHTML(te.obj[0].body.firstChild.lastChild),'
  • ueditor

  • ueditor

  • ','检查内容'); + start(); + },20); + },50); + stop(); +}); + +//todo 这个检查存在问题,如何检查 evt.preventDefault();? +test('在h1内输入del',function(){ + var editor = te.obj[0]; + editor.setContent( '


    hello

    ' ); + var range = te.obj[1]; + setTimeout(function(){ + range.setStart(editor.body.childNodes[0],0).collapse(true).select(true); + ua.keydown(te.obj[0].body,{'keyCode':46}); + ua.keyup(te.obj[0].body,{'keyCode':46}); + setTimeout(function(){ + equal(ua.getChildHTML(te.obj[0].body),'


    hello

    ','在h1内输入del'); + start(); + },20); + },20); + stop(); +}); + +test('在列表中,跨行选中,输入tab键',function(){ + var editor = te.obj[0]; + editor.setContent( '
    1. 欢迎使用

    2. ueditor

    3. ueditor

    ' ); + var range = te.obj[1]; + setTimeout(function(){ + range.setStart( editor.body.firstChild.firstChild.firstChild.firstChild,1 ).setEnd(editor.body.firstChild.childNodes[1].firstChild.firstChild,1 ).select(); + ua.keydown(editor.body,{'keyCode':9}); + ua.keyup(editor.body,{'keyCode':9}); + setTimeout(function(){ + equal(te.obj[0].undoManger.index,1,'undoManger.index'); + ua.manualDeleteFillData(te.obj[0].body); + equal(te.obj[0].body.firstChild.tagName.toLowerCase(),'ol','外面套了一层ol'); + equal(te.obj[0].body.firstChild.childNodes.length,2,''); + equal(te.obj[0].body.firstChild.firstChild.tagName.toLowerCase(),'ol','原列表'); + equal($(te.obj[0].body.firstChild).css('list-style-type'),'decimal','原列表类型'); + equal(ua.getChildHTML(te.obj[0].body.firstChild.firstChild),'
  • 欢迎使用

  • ueditor

  • ','检查内容'); + start(); + },20); + },50); + stop(); +}); + +test(' 光标定位到列表前,输入tab键',function(){ + var editor = te.obj[0]; + editor.setContent( '
    1. 欢迎使用

    2. ueditor

    ' ); + var range = te.obj[1]; + setTimeout(function(){ + range.setStart( editor.body.firstChild.firstChild.firstChild,0 ).collapse(true).select(); + ua.keydown(editor.body,{'keyCode':9}); + ua.keyup(editor.body,{'keyCode':9}); + setTimeout(function(){ + equal(te.obj[0].undoManger.list.length,1,'undoManger.index'); + ua.manualDeleteFillData(te.obj[0].body); + equal($(te.obj[0].body.firstChild).css('list-style-type'),'decimal','原列表类型'); + equal(te.obj[0].body.firstChild.childNodes.length,2,'列表有两个子节点'); + equal($(te.obj[0].body.firstChild.firstChild).css('list-style-type'),'lower-alpha','第一个节点是另一类型的列表'); + equal(ua.getChildHTML(te.obj[0].body.firstChild.firstChild),'
  • 欢迎使用

  • ','检查内容'); + equal(te.obj[0].body.firstChild.lastChild.tagName.toLowerCase(),'li','第一个节点是原列表的li'); + equal(ua.getChildHTML(te.obj[0].body.firstChild.lastChild),'

    ueditor

    ','检查内容'); + start(); + },20); + },50); + stop(); +}); + +test( '删除inline的标签', function() { + var editor = te.obj[0]; + editor.setContent( '

    hello worldwasai

    ' ); + var range = te.obj[1]; + setTimeout(function(){ + var strong = editor.body.firstChild.firstChild; + range.selectNode( strong ).select(); + ua.keydown(editor.body,{'keyCode':8}); + ua.keyup(editor.body,{'keyCode':8}); + setTimeout(function(){ + ua.manualDeleteFillData( editor.body ); + equal( editor.body.firstChild.tagName.toLowerCase(), 'p', 'strong 以及子inline节点都被删除' ); + if ( !baidu.editor.browser.ie ) + equal( editor.body.lastChild.innerHTML, '
    ', '内容被删除了' ); + else + equal( editor.body.lastChild.innerHTML, '', '内容被删除了' ); + start(); + },20); + },20); + stop(); +} ); + +/*trace 1089*/ +test( '跨行选择2个块元素', function() { + var editor = te.obj[0]; + editor.setContent( '

    hello worldwasai

    hello 2
    ' ); + var range = te.obj[1]; + setTimeout(function(){ + var body = editor.body; + range.setStart( body.firstChild, 0 ).setEnd( body.lastChild,1 ).select(); + ua.keydown(editor.body,{'keyCode':8}); + ua.keyup(editor.body,{'keyCode':8}); + setTimeout(function(){ + ua.manualDeleteFillData( editor.body ); + range = editor.selection.getRange(); + equal( body.childNodes.length, 1, 'div被删除,保留p' ); + var br = baidu.editor.browser.ie?"":"
    "; + equal( ua.getChildHTML( body ), '

    '+br+'

    ' ); + start(); + },20); + },20); + stop(); +} ); + +//test('删除空节点 ',function(){ +// var editor = te.obj[0]; +// editor.setContent('


    ') ; +// var range = te.obj[1]; +// setTimeout(function(){ +// range.setStartAtFirst(editor.body.getElementsByTagName('span')[0]).collapse(true).select(true); +// ua.keyup(te.obj[0].body,{'keyCode':8}); +// setTimeout(function(){ +// var br = ua.browser.ie?'':'
    '; +// equal(ua.getChildHTML(editor.body),'

    '+br+'

    ','删除空节点'); +// start(); +// },20); +// },20); +// stop(); +//}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/lineheight.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/lineheight.js new file mode 100644 index 000000000..520dcb71b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/lineheight.js @@ -0,0 +1,164 @@ +module( 'plugins.lineheight' ); +//test( '', function() { +// equal('','',''); +//} ); +/* + * + *利用pict工具生成的用例设计结果,有微调。3to1表示先设置行距为3再设置为1,选区“singlePara”表示选中一个段落, + * “multiPara”表示选中多个段落,“字号统一”表示所有的字号都是一样大,“16to36To16”表示先设置大小为16px,再设置为36,再设置为16 + 设置行距顺序 选区 选区内字号顺序 +
  • 3to1 collapse 字号统一
  • +
  • 1 multiPara 36To16To36
  • +
  • 1to3to1 singlePara 字号统一
  • +
  • 1 collapse 16to36To16
  • +
  • 1to3to1 multiPara 16to36To16
  • +
  • 3to1 singlePara 36To16To16
  • +
  • 3 multiPara 字号统一
  • +
  • 1to3to1 collapse 36To16To16
  • +
  • 3to1 multiPara 16to36To16
  • +
  • 3 singlePara 16to36To16
  • + * */ +// +//var compareLineHeight = function ( node, value,fontSize, descript ) { +// var currLineHeight = $(node).css('lineHeight').replace(/px/,''); +// var spans = node.getElementsByTagName('') +// value = value.replace( /px/, '' ); +// var baseLineHeight = (ua.browser.ie ? domUtils.getComputedStyle( node, 'font-size' ).replace( /px/, '' ) : node.offsetHeight); +// var fontSize = $( node ).css( 'font-size' ).replace( /px/, '' ); +// if ( value >= fontSize && value >= baseLineHeight ) { +// ok( true, descript ); +// } else { +// ok( false, descript + '--- "lineHeight应取fontSize和baseLineHeight*倍数的最大值":lineHeight=' + value + ' ;font-sze=' + fontSize + ';baseLineHeight=' + baseLineHeight ); +// } +// +//} +// +///*
  • 3to1 collapse 字号统一
  • */ +test( '闭合情况,字号统一', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello

    ' ); + range.setStart(body.firstChild, 1).collapse(1).select(); + editor.execCommand('lineheight', 3); + setTimeout( function () { + var p = body.firstChild; + equal( editor.queryCommandValue('lineheight'), "3", '行间距为3'); + editor.execCommand('lineheight', 1); + p = body.firstChild; + equal( editor.queryCommandValue('lineheight'), "1", '行间距为1'); + equal( p.style['lineHeight'], 'normal', '检查行高' ); + equal( $( p ).css('font-size'), '36px', '检查字体'); + start(); + }, 20 ); + stop(); +} ); + +/*
  • 1 multiPara 36To16To36
  • */ +//test( '多个段落设置多倍行距,段落中字体大小各不相同', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '

    hello

    hello

    hello

    ' ); +// range.setStart( body.firstChild, 0 ).setEnd( body.lastChild, 1 ).select(); +// editor.execCommand( 'lineheight', 1 ); +// setTimeout( function () { +// var ps = body.childNodes; +// equal( $( ps[0] ).css( 'line-height' ), '36px', '第1个p行高为36px' ); +// equal( $( ps[1] ).css( 'line-height' ), '16px', '第2个p行高为36px' ); +// equal( $( ps[2] ).css( 'line-height' ), '36px', '第3个p行高为36px' ); +// range.selectNode( ps[0] ).select(); +// equal( editor.queryCommandValue( 'lineheight' ), "1", '第1个p行间距为1' ); +// range.selectNode( ps[0] ).select(); +// equal( editor.queryCommandValue( 'lineheight' ), "1", '第2个p行间距为1' ); +// range.selectNode( ps[0] ).select(); +// equal( editor.queryCommandValue( 'lineheight' ), "1", '第3个p行间距为1' ); +// start(); +// }, 20 ); +// stop(); +//} ); +// +///*
  • 1 collapse 16to36To16
  • */ +//test( '多个段落设置多倍行距,段落中字体大小各不相同', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '

    hello

    hello

    hello

    ' ); +// range.setStart( body.firstChild, 0 ).setEnd( body.lastChild, 1 ).select(); +// editor.execCommand( 'lineheight', 1 ); +// setTimeout( function () { +// var ps = body.childNodes; +// compareLineHeight( ps[0], $( ps[0] ).css( 'line-height' ), '行距为1,第1个p行高' ); +// compareLineHeight( ps[1], $( ps[1] ).css( 'line-height' ), '行距为1,第2个p行高' ); +// compareLineHeight( ps[2], $( ps[2] ).css( 'line-height' ), '行距为1,第3个p行高' ); +// range.selectNode( ps[0] ).select(); +// equal( editor.queryCommandValue( 'lineheight' ), "1", '第1个p行间距为1' ); +// range.selectNode( ps[0] ).select(); +// equal( editor.queryCommandValue( 'lineheight' ), "1", '第2个p行间距为1' ); +// range.selectNode( ps[0] ).select(); +// equal( editor.queryCommandValue( 'lineheight' ), "1", '第3个p行间距为1' ); +// start(); +// }, 20 ); +// stop(); +//} ); +// +///*
  • 1to3to1 singlePara 字号统一
  • */ +//test( '1个段落设置多倍行距,字号相同', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '

    hello

    ' ); +// range.selectNode( body.firstChild ).select(); +// editor.execCommand( 'lineheight', 1 ); +// setTimeout( function () { +// var p = body.firstChild; +// equal( $( p ).css( 'line-height' ), '36px', '第1个p行高为36px' ); +// editor.execCommand( 'lineheight', 3 ); +// p = body.firstChild; +// compareLineHeight( p, $( p ).css( 'line-height' ), '行距为1,第1个p行高' ); +// editor.execCommand( 'lineheight', 1 ); +// var p = body.firstChild; +// equal( $( p ).css( 'line-height' ), '36px', '第1个p行高为36px' ); +// start(); +// }, 20 ); +// stop(); +//} ); +// +///*
  • 1to3to1 multiPara 16to36To16
  • */ +//test( '多个段落设置多倍行距,字号不同', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '

    hello

    hello

    hello

    ' ); +// range.setStart( body.firstChild.firstChild, 1 ).setEnd( body.lastChild.firstChild, 2 ).select(); +// editor.execCommand( 'lineheight', 1 ); +// setTimeout( function () { +// var ps = body.childNodes; +// compareLineHeight( ps[0], $( ps[0] ).css( 'line-height' ), '行距为1,第1个p行高' ); +// compareLineHeight( ps[1], $( ps[1] ).css( 'line-height' ), '行距为1,第2个p行高' ); +// compareLineHeight( ps[2], $( ps[2] ).css( 'line-height' ), '行距为1,第3个p行高' ); +// range.selectNode( ps[0] ).select(); +// equal( editor.queryCommandValue( 'lineheight' ), "1", '第3个p行间距为1' ); +// +// range.setStart( body.firstChild.firstChild, 1 ).setEnd( body.lastChild.firstChild, 2 ).select(); +// editor.execCommand( 'lineheight', 3 ); +// ps = body.childNodes; +// compareLineHeight( ps[0], $( ps[0] ).css( 'line-height' ), '行距为3,第1个p行高' ); +// compareLineHeight( ps[1], $( ps[1] ).css( 'line-height' ), '行距为3,第2个p行高' ); +// compareLineHeight( ps[2], $( ps[2] ).css( 'line-height' ), '行距为3,第3个p行高' ); +// range.selectNode( ps[0] ).select(); +// equal( editor.queryCommandValue( 'lineheight' ), "3", '第1个p行间距为1' ); +// +// range.setStart( body.firstChild.firstChild, 1 ).setEnd( body.lastChild.firstChild, 2 ).select(); +// editor.execCommand( 'lineheight', 1 ); +// ps = body.childNodes; +// compareLineHeight( ps[0], $( ps[0] ).css( 'line-height' ), '行距为1,第1个p行高' ); +// compareLineHeight( ps[1], $( ps[1] ).css( 'line-height' ), '行距为1,第2个p行高' ); +// compareLineHeight( ps[2], $( ps[2] ).css( 'line-height' ), '行距为1,第3个p行高' ); +// range.selectNode( ps[0] ).select(); +// equal( editor.queryCommandValue( 'lineheight' ), "1", '第1个p行间距为1' ); +// start(); +// }, 20 ); +// stop(); +// +//} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/link.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/link.js new file mode 100644 index 000000000..de40a881e --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/link.js @@ -0,0 +1,216 @@ +module( "plugins.link" ); + +/*trace 879*/ +test( '同时去多个超链接', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hellofirstsecond

    thirdsina

    baidu
    ' ); + stop(); + setTimeout(function () { + range.selectNode( editor.body ).select(); + editor.execCommand( 'unlink' ); + equal( editor.body.firstChild.innerHTML, 'hellofirstsecond', '第一段去掉超链接' ); + equal( editor.body.firstChild.nextSibling.innerHTML, 'thirdsina', '第二段去掉超链接' ); + equal( editor.body.lastChild.getElementsByTagName( 'td' )[0].innerHTML, 'baidu', '表格内的超链接被去掉' ); + start(); + }, 100); +} ); + +test( '光标闭合且没有超链接', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello

    ' ); + range.setStart( editor.body.firstChild, 0 ).collapse( 1 ).select(); + editor.execCommand( 'unlink' ); + equal( ua.getChildHTML( editor.body ), '

    hello

    ', '没有超链接什么都不做' ); +} ); + +/*trace 833*/ +test( '在超链接前加一个超链接', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hellobaidu

    ' ); + range.selectNode( editor.body.firstChild.firstChild ).select(); + editor.execCommand( 'link', {href:'http://www.google.com/'} ); + ua.manualDeleteFillData( editor.body ); + ua.checkSameHtml( editor.getContent(), '

    hellobaidu

    '); +} ); + +/*trace 798*/ +test( '给图片添加超链接', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello

    ' ); + range.selectNode( editor.body.firstChild.firstChild ).select(); + editor.execCommand( 'link', {href:'http://www.baidu.com/'} ); + var html = 'hello'; + ua.checkHTMLSameStyle( html, editor.document, editor.body.firstChild, '给图片添加超链接' ); +// equal(html,editor.body.firstChild.innerHTML); +} ); + +/*trace 758 + *并不是真的选中所有单元格,是假选 + * 先设置startContainer和endContainer为第一个单元格中的文本或占位符 + * 再在editor的currentSelectedArr设置当前选中的内容,使得看上去是选中了所有的td*/ +test( '选中多个单元格插入超链接', function () { + if(ua.browser.ie>8)return ;//TODO 1.2.6 + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '
    hello
    ' ); + setTimeout(function(){ + var trs = editor.body.firstChild.getElementsByTagName( 'tr' ); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0],trs[1].cells[1]); + ut.setSelected(cellsRange); + range.setStart( trs[0].cells[0], 0 ).collapse( true ).select(); + + editor.execCommand( 'link', {href:'http://www.baidu.com/'} ); + var br = ua.browser.ie ? '' : '
    '; + equal( ua.getChildHTML( trs[0].cells[0] ), 'http://www.baidu.com/'+(ua.browser.ie>8?' ':br), '第一个单元格中插入超链接' );//原来空单元格的br不去掉 + equal( ua.getChildHTML( trs[0].cells[1] ), br, '第二个单元格中未插入超链接' ); + equal( ua.getChildHTML( trs[1].cells[0] ), 'hello', '第三个单元格中插入超链接' ); + start(); + },50); + stop(); +} ); + +test( '去除表格中的链接', function () { + if(ua.browser.ie>8)return ;//TODO 1.2.6 + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '
    hello
    ' ); + setTimeout(function(){ + var trs = editor.body.firstChild.getElementsByTagName( 'tr' ); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0],trs[1].cells[0]); + ut.setSelected(cellsRange); + range.setStart( trs[0].cells[0], 0 ).collapse( true ).select(); + + editor.execCommand( 'link', {href:'http://www.baidu.com/'} ); + var br = ua.browser.ie ? '' : '
    '; + equal( editor.queryCommandValue( 'link' ), trs[0].cells[0].firstChild, '查询多个单元格的command value为a' ); + editor.execCommand( 'unlink' ); + equal( ua.getChildHTML( trs[0].cells[0] ), 'http://www.baidu.com/'+(ua.browser.ie>8?' ':br), '第一个单元格中插入超链接' ); + equal( ua.getChildHTML( trs[0].cells[1] ), br, '第二个单元格中未插入超链接' ); + equal( ua.getChildHTML( trs[1].cells[0] ), 'hello', '第三个单元格中插入超链接' ); + equal( editor.queryCommandValue( 'link' ), null, '查询多个单元格的command value为null' ); + start(); + },50); + stop(); +} ); + +/*1.2.5+不支持此功能*/ +//test( 'trace 1728 去除链接--表格第一个单元格没有超链接', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// editor.setContent( '
    google
    ' ); +// var body = editor.body; +// var tds = body.firstChild.getElementsByTagName( 'td' ); +// range.selectNode( body.firstChild ).select(); +// editor.currentSelectedArr = [tds[0], tds[1]]; +// editor.execCommand( 'unlink' ); +// if ( UE.browser.ie ) +// equal( tds[0].childNodes.length, 1, '第一个表格中有一个占位文本节点' ); +// range = editor.selection.getRange(); +// tds = body.firstChild.getElementsByTagName( 'td' ); +// equal( ua.getChildHTML( tds[1] ), 'google', 'a标签被删除' ); +// if ( UE.browser.gecko ) +// ua.checkResult( range, tds[0], tds[0], 0, 0, true, 'check unlink result' ); +// else if(UE.browser.opera) +// ua.checkResult( range, tds[0].firstChild, tds[0].firstChild, 0, 0, true, 'check unlink result' ); +// else{ +// ua.checkResult( range, tds[0].firstChild, tds[0].firstChild, 1, 1, true, 'check unlink result' ); +// } +// var br = ua.browser.ie ? '' : "
    "; +// ua.manualDeleteFillData( tds[0] ); +// equal( ua.getChildHTML( tds[0] ), br, 'td 1 is empty' ); +//} ); + +test( '添加链接--表格第一个单元格没有超链接', function () { + if(!ua.browser.ie){//TODO 1.2.6 + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '
    google
    ' ); + setTimeout(function(){ + var trs = editor.body.firstChild.getElementsByTagName( 'tr' ); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0],trs[0].cells[1]); + ut.setSelected(cellsRange); +// range.setStart( trs[0].cells[0], 0 ).collapse( true ).select(); +// range.selectNode( body.firstChild ).select(); +// var tds = body.firstChild.getElementsByTagName( 'td' ); +// editor.currentSelectedArr = [tds[0], tds[1]]; + editor.execCommand( 'link', {href:'www.baidu.com'} ); + range = editor.selection.getRange(); + equal( ua.getChildHTML( trs[0].cells[1] ), 'google', 'a标签的地址被修改了' ); + var br = ua.browser.ie ? '' : '
    '; + equal( ua.getChildHTML( trs[0].cells[0] ), 'www.baidu.com'+br, 'td 1 被添加了超链接' ); + if ( (!baidu.editor.browser.gecko)&&(!baidu.editor.browser.webkit)) + ua.checkResult( range, trs[0].cells[0].firstChild.firstChild, trs[0].cells[0].firstChild.firstChild, 0, 0, true, 'check link result' ); + else + ua.checkResult( range, trs[0].cells[0].firstChild, trs[0].cells[0].firstChild, 0, 0, true, 'check link result' ); + start(); + },50); + stop(); + } +} ); + +test( '光标在超链接中间去除超链接', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello

    ' ); + var a_text = editor.body.getElementsByTagName( 'a' )[0].firstChild; + range.setStart( a_text, 2 ).collapse( 1 ).select(); + same( editor.queryCommandValue( 'link' ), editor.body.firstChild.firstChild, 'command value is a' ); + editor.execCommand( 'unlink' ); + equal( ua.getChildHTML( editor.body ), '

    hello

    ', '去除超链接后' ); + equal( editor.queryCommandState( 'unlink' ), -1, 'link state is -1' ); +} ); + +test( '去除链接--选中区域包含超链接和非超链接', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello

    hello2famfouhello3

    ' ); + var body = editor.body; + range.setStart( body.firstChild, 0 ).setEnd( body.lastChild, 3 ).select(); + equal( editor.queryCommandValue( 'link' ), body.lastChild.firstChild.nextSibling, 'queryCommandvalue' ); +} ); + +/*trace 1111*/ +test( '插入超链接', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello

    ' ); + range.setStart( editor.body.firstChild, 1 ).collapse( 1 ).select(); + editor.execCommand( 'link', {href:'www.baidu.com'} ); + var a = editor.body.getElementsByTagName( 'a' )[0]; + range.selectNode( a ).select(); + range = editor.selection.getRange(); + same( editor.queryCommandValue( 'link' ), a, 'link value is a' ); + equal( ua.getChildHTML( editor.body ), '

    hellowww.baidu.com

    ' ); + equal( editor.queryCommandState( 'unlink' ), 0, 'link state is 0' ); +} ); + +test( '对现有的超链接修改超链接地址', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    http://www.baidu.comhellogoogle

    ' ); + var a1 = body.firstChild.firstChild; + range.selectNode( a1 ).select(); + + editor.execCommand( 'link', {href:'ueditor.baidu.com'} ); + a1 = body.firstChild.firstChild; + equal( a1.getAttribute( 'href' ), 'ueditor.baidu.com', 'check href' ); + equal( a1.innerHTML, 'ueditor.baidu.com', 'innerHTML也相应变化' ); + + var a2 = body.firstChild.getElementsByTagName( 'a' )[1]; + range.selectNode( a2 ).select(); + editor.execCommand( 'link', {href:'mp3.baidu.com'} ); + a2 = body.firstChild.getElementsByTagName( 'a' )[1]; + + equal( a2.getAttribute( 'href' ), 'mp3.baidu.com', 'check href for second a link' ); + equal( a2.innerHTML, 'google', 'innerHTML不变' ); +} ); + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/list.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/list.js new file mode 100644 index 000000000..1f3fb8785 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/list.js @@ -0,0 +1,961 @@ +module("plugins.list"); +/* + *
  • 有序列表切换到无序 + *
  • 无序列表切换到有序 + *
  • 有序之间相互切换 + *
  • 无序之间相互切换 + *
  • 先引用后列表 + *
  • 表格中插入列表 + *
  • h1套列表 + *
  • 去除链接 + * + * */ + +//test('',function(){stop();}) +test('trace 3859 回车将p转成列表', function () { + if(ua.browser.ie==9||ua.browser.ie==10)return; + var editor = te.obj[0]; + var range = te.obj[1]; + var br = ua.browser.ie ? '' : '
    '; + editor.setContent('

    1. 2

    '); + stop(); + setTimeout(function () { + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + ua.keydown(editor.body, {keyCode:13}); + setTimeout(function () { + ua.checkSameHtml(ua.getChildHTML(editor.body), '
    1. 2

    2. ' + br + '

    ', '回车将p转成列表'); + start() + }, 50); + }, 100); +}); + +//todo bug3418 +test('ol标签嵌套', function () { + var editor = te.obj[0]; + editor.setContent('
    1. a

      1. b

    '); + ua.checkSameHtml(editor.body.innerHTML, '
    1. a

      1. b

    '); +}); + +test('li内添加p标签', function () { + var editor = te.obj[0]; + editor.setContent('
    1. asd

      asd

    '); + ua.manualDeleteFillData(editor.body); + ua.checkSameHtml(editor.body.innerHTML, '
    1. asd

      asd

    ', '添加p标签'); +}); +//todo 1.2.6.1 +test('p转成列表', function () { + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor('ue',{autoTransWordToList:true}); +// var br = ua.browser.ie ? ' ' : ''; + var br = ''; + editor.ready(function () { + setTimeout(function(){ + editor.setContent('

    1.a

    1. b
    '); + ua.manualDeleteFillData(editor.body); + //todo 1.2.6.1 +// ua.checkSameHtml(editor.body.innerHTML,'
    1. a

    2. b

    ','p转成有序列表'); + editor.setContent('

    abc

    '); + ua.manualDeleteFillData(editor.body); + ua.checkSameHtml(editor.body.innerHTML, '
    • ' + br + '

    ', 'p转成无序列表'); +//todo bug3417 +// editor.setContent('

    n

    '); +// ua.manualDeleteFillData(editor.body); +// ua.checkSameHtml(editor.body.innerHTML,'

    ','p转成无序列表'); + UE.delEditor('ue'); + te.dom.push(document.getElementById('ue')); + start(); + },200); + }); + stop(); + +}); + +test('列表复制粘贴', function () { + var editor = te.obj[0]; + + editor.setContent('
    1. a
    2. b
    • a
    • b
    '); + ua.keydown(editor.body, {'keyCode':65, 'ctrlKey':true}); + ua.keydown(editor.body, {'keyCode':67, 'ctrlKey':true}); + /*ctrl+c*/ + + setTimeout(function () { + var html = {html:editor.body.innerHTML}; + editor.fireEvent('beforepaste', html); + /*粘贴*/ +// range.setStart(editor.body,1).collapse(true).select(); +// editor.fireEvent("paste"); +// ua.manualDeleteFillData(editor.body); +// equal(editor.body.innerHTML,'


    ','编辑器清空'); + editor.setContent('
    1. a
    2. b
    • a
    • b
    '); + ua.keydown(editor.body, {'keyCode':65, 'ctrlKey':true}); + ua.keydown(editor.body, {'keyCode':67, 'ctrlKey':true}); + /*ctrl+c*/ + html = {html:editor.body.innerHTML}; + editor.fireEvent('beforepaste', html); + /*粘贴*/ + editor.setContent('
      1. a
      2. b
      • a
      • b
    '); + ua.keydown(editor.body, {'keyCode':65, 'ctrlKey':true}); + ua.keydown(editor.body, {'keyCode':67, 'ctrlKey':true}); + /*ctrl+c*/ + html = {html:editor.body.innerHTML}; + editor.fireEvent('beforepaste', html); + /*粘贴*/ + editor.setContent('
      1. a
      2. b
      • a
      • b
    '); + ua.keydown(editor.body, {'keyCode':65, 'ctrlKey':true}); + ua.keydown(editor.body, {'keyCode':67, 'ctrlKey':true}); + /*ctrl+c*/ + html = {html:editor.body.innerHTML}; + setTimeout(function () { + editor.fireEvent('beforepaste', html); + /*粘贴*/ + start() + }, 50); + }, 50); + stop(); +}); + +//TODO trace-3416 此处只为提高覆盖率 +//test('剪切列表',function(){ +// var editor = te.obj[0]; +// var range = te.obj[1]; +// editor.setContent('

    '); +// range.setStart(editor.body.firstChild.lastChild,0).collapse(true).select(); +// ua.cut(editor.body); +// stop(); +// setTimeout(function(){ +// ua.manualDeleteFillData(editor.body); +// var br = ua.browser.ie?'':'
    '; +// equal(editor.body.innerHTML,'

    '+br+'

    ','编辑器清空'); +// editor.setContent('

    asdf

    '); +// range.setStart(editor.body.firstChild.lastChild,0).collapse(true).select(); +// ua.cut(editor.body); +// setTimeout(function(){ +// ua.manualDeleteFillData(editor.body); +// equal(editor.body.innerHTML,'

    asdf

    ','列表删除'); +// editor.setContent('www.baidu.com

    '); +// range.setStart(editor.body.firstChild.nextSibling.lastChild,0).collapse(true).select(); +// ua.cut(editor.body); +// setTimeout(function(){ +// ua.manualDeleteFillData(editor.body); +// ua.checkSameHtml(editor.body.innerHTML,'

    www.baidu.com

    ','列表删除'); +// start(); +// },20); +// },20); +// },20); +//}); + +test('修改列表再删除列表', function () { + if ((ua.browser.safari && !ua.browser.chrome))return 0; + var editor = te.obj[0]; + var range = te.obj[1]; + var br = baidu.editor.browser.ie ? "" : "
    "; + editor.setContent('
      hello1
    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('insertorderedlist', 'cn2'); + ua.manualDeleteFillData(editor.body); + equal(editor.body.firstChild.tagName.toLowerCase(), 'ol', '查询列表的类型'); + equal(ua.getChildHTML(editor.body.firstChild), '
  • hello1

  • '); + range.setStart(editor.body.lastChild, 0).setEnd(editor.body.lastChild, 1).select(); + editor.execCommand('insertorderedlist', 'cn2'); + ua.manualDeleteFillData(editor.body); + ua.checkSameHtml(editor.body.innerHTML, '

    hello1

    '); +}); + +test('列表内没有列表标号的项后退', function () { + if ((ua.browser.safari && !ua.browser.chrome))return 0; + var editor = te.obj[0]; + var range = te.obj[1]; + + var lis; + var br = ua.browser.ie ? '
    ' : '
    '; + editor.setContent('
    1. hello

      www.baidu.com

    '); + range.setStart(editor.body.firstChild.firstChild.lastChild.lastChild, 0).collapse(true).select(); + ua.manualDeleteFillData(editor.body); + ua.keydown(editor.body, {keyCode:8}); + + setTimeout(function () { + lis = editor.body.getElementsByTagName('li'); + equal(lis.length, '1', '列表长度不变'); + ua.checkSameHtml(ua.getChildHTML(editor.body), '
    1. hello

    www.baidu.com

    ', 'p在列表外'); + start() + }, 50); + stop(); +}); + +test('多个p,选中其中几个变为列表', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    hello1

    hello2

    hello3

    hello4

    '); + setTimeout(function () { + range.setStart(body.firstChild, 0).setEnd(body.firstChild.nextSibling, 1).select(); + editor.execCommand('insertorderedlist'); + equal(ua.getChildHTML(body.firstChild), '
  • hello1

  • hello2

  • ', '检查列表的内容'); + equal(body.firstChild.tagName.toLowerCase(), 'ol', '检查列表的类型'); + equal(body.childNodes.length, 3, '3个孩子'); + equal(body.lastChild.tagName.toLowerCase(), 'p', '后面的p没有变为列表'); + equal(body.lastChild.innerHTML.toLowerCase(), 'hello4', 'p里的文本'); + start(); + }, 50); + stop(); +}); + +//trace 988,有序123切到abc再切到123 +test('有序列表的切换', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    你好

    是的

    '); + setTimeout(function () { + range.setStart(body, 0).setEnd(body, 2).select(); + editor.execCommand('insertorderedlist', 'decimal'); + equal(editor.queryCommandValue('insertorderedlist'), 'decimal', '查询插入数字列表的结果1'); + editor.execCommand('insertorderedlist', 'lower-alpha'); + equal(editor.queryCommandValue('insertorderedlist'), 'lower-alpha', '查询插入字母列表的结果'); + editor.execCommand('insertorderedlist', 'decimal'); + equal(editor.queryCommandValue('insertorderedlist'), 'decimal', '查询插入数字列表的结果2'); + start(); + }, 50); + stop(); +}); + +//trace 988,无序圆圈切到方块再切到圆圈 +test('无序列表之间的切换', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    你好

    是的

    '); + range.setStart(body, 0).setEnd(body, 2).select(); + editor.execCommand('insertunorderedlist', 'circle'); + equal(editor.queryCommandValue('insertunorderedlist'), 'circle', '查询插入圆圈列表的结果1'); + editor.execCommand('insertunorderedlist', 'square'); + equal(editor.queryCommandValue('insertunorderedlist'), 'square', '查询插入正方形列表的结果'); + editor.execCommand('insertunorderedlist', 'circle'); + equal(editor.queryCommandValue('insertunorderedlist'), 'circle', '查询插入圆圈列表的结果1'); +}); + +test('引用中插入列表', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    '); + range.setStart(body.firstChild, 0).collapse(1).select(); + editor.execCommand('blockquote'); + editor.execCommand('insertorderedlist'); + equal(body.firstChild.tagName.toLowerCase(), 'blockquote', 'firstChild of body is blockquote'); + equal(body.childNodes.length, 1, '只有一个孩子'); + equal(body.firstChild.firstChild.tagName.toLowerCase(), 'ol', 'insert an ordered list'); + equal(body.firstChild.childNodes.length, 1, 'blockquote只有一个孩子'); + equal($(body.firstChild.firstChild).css('list-style-type'), 'decimal', '数字列表'); + equal(editor.queryCommandValue('insertorderedlist'), 'decimal', 'queryCommand value is decimal'); +}); + +/*trace 1118*/ +test('去除无序列表', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    '); + range.setStart(body.firstChild, 0).collapse(1).select(); + editor.execCommand('insertunorderedlist'); + equal(body.firstChild.tagName.toLowerCase(), 'ul', 'insert an unordered list'); + equal(body.childNodes.length, 1, 'body只有一个孩子'); + equal(editor.queryCommandValue('insertunorderedlist'), 'disc', 'queryCommand value is disc'); + ok(editor.queryCommandState('insertunorderedlist'), 'state是1'); + /*去除列表*/ + editor.execCommand('insertunorderedlist'); + ua.manualDeleteFillData(editor.body); + equal(body.firstChild.tagName.toLowerCase(), 'p', '去除列表'); + equal(body.childNodes.length, 1, 'body只有一个孩子'); + ok(!editor.queryCommandState('insertunorderedlist'), 'state是0'); +}); + +test('闭合方式有序和无序列表之间的切换', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    '); + range.setStart(body.firstChild, 0).collapse(1).select(); + editor.execCommand('insertunorderedlist'); + equal(body.firstChild.tagName.toLowerCase(), 'ul', 'insert an unordered list'); + equal(body.childNodes.length, 1, 'body只有一个孩子'); + equal(editor.queryCommandValue('insertunorderedlist'), 'disc', 'queryCommand value is disc'); + equal(editor.queryCommandValue('insertorderedlist'), null, '有序列表查询结果为null'); + /*切换为有序列表*/ + editor.execCommand('insertorderedlist'); + ua.manualDeleteFillData(editor.body); + equal(body.firstChild.tagName.toLowerCase(), 'ol', '变为有序列表'); + equal(body.childNodes.length, 1, 'body只有一个孩子'); + equal(editor.queryCommandValue('insertorderedlist'), 'decimal', 'queryCommand value is decimal'); + equal(editor.queryCommandValue('insertunorderedlist'), null, '无序列表查询结果为null'); + /*切换为圆圈无序列表*/ + editor.execCommand('insertunorderedlist', 'circle'); + ua.manualDeleteFillData(editor.body); + equal(body.firstChild.tagName.toLowerCase(), 'ul', '变为无序列表'); + equal(body.childNodes.length, 1, 'body只有一个孩子'); + equal(editor.queryCommandValue('insertunorderedlist'), 'circle', '无序列表是圆圈'); + equal(editor.queryCommandValue('insertorderedlist'), null, '有序列表查询结果为null'); +}); + +test('非闭合方式切换有序和无序列表', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + /*如果只选中hello然后切换有序无序的话,不同浏览器下表现不一样*/ + editor.setContent('
    1. hello
    2. hello3

    hello2

    '); + range.selectNode(body.firstChild).select(); + editor.execCommand('insertunorderedlist', 'square'); + equal(body.firstChild.tagName.toLowerCase(), 'ul', '有序列表变为无序列表'); + equal(editor.queryCommandValue('insertunorderedlist'), 'square', '无序列表是方块'); + equal(ua.getChildHTML(body.firstChild), '
  • hello

  • hello3

  • ', 'innerHTML 不变'); + /*切换为有序列表*/ + editor.execCommand('insertorderedlist', 'upper-alpha'); + equal(body.firstChild.tagName.toLowerCase(), 'ol', '无序列表变为有序列表'); + equal(editor.queryCommandValue('insertorderedlist'), 'upper-alpha', '有序列表是A'); + equal(ua.getChildHTML(body.firstChild), '
  • hello

  • hello3

  • ', '变为有序列表后innerHTML 不变'); +}); + +test('将列表下的文本合并到列表中', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('
    • hello1

    是的

    '); + setTimeout(function () { + range.setStart(body.firstChild, 0).setEnd(body.lastChild, 1).select(); + /*将无序的变为有序,文本也相应变成无序列表的一部分*/ + editor.execCommand('insertorderedlist'); + ua.manualDeleteFillData(editor.body); + equal(body.firstChild.tagName.toLowerCase(), 'ol', 'ul变为了ol'); + equal(ua.getChildHTML(body.firstChild), '
  • hello1

  • 是的

  • '); + equal(body.childNodes.length, 1, '只有一个孩子是ol'); + start(); + }, 50); + stop(); +}); + +test('多个列表', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('
    1. hello1
    • hello2
    '); + range.selectNode(body.lastChild).select(); + /*将无序的变为有序*/ + editor.execCommand('insertorderedlist'); + equal(body.firstChild.tagName.toLowerCase(), 'ol', '仍然是ol'); + equal(body.childNodes.length, 1, 'body只有1个孩子ol'); + equal(body.firstChild.childNodes.length, 2, '下面的列表合并到上面'); + equal(ua.getChildHTML(body.lastChild), '
  • hello1

  • hello2

  • ', '2个li子节点'); +}); + +test('修改列表中间某一段列表为另一种列表', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('
    1. hello
    2. hello2
    3. hello3
    4. hello4
    '); + var lis = body.firstChild.getElementsByTagName('li'); + range.setStart(lis[1], 0).setEnd(lis[2], 1).select(); + editor.execCommand('insertunorderedlist'); + equal(body.childNodes.length, 3, '3个列表'); + equal(ua.getChildHTML(body.firstChild), '
  • hello

  • ', '第一个列表只有一个li'); + equal(ua.getChildHTML(body.lastChild), '
  • hello4

  • ', '最后一个列表只有一个li'); + equal(body.childNodes[1].tagName.toLowerCase(), 'ul', '第二个孩子是无序列表'); + equal(ua.getChildHTML(body.childNodes[1]), '
  • hello2

  • hello3

  • ', '检查第二个列表的内容'); +}); + +test('两个列表,将下面的合并上去', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('
    1. hello3
    1. hello1
    • hello2
    '); + range.selectNode(body.lastChild).select(); + /*将无序的变为有序,有序上面的有序不会合并在一起了*/ + editor.execCommand('insertorderedlist'); + equal(body.firstChild.tagName.toLowerCase(), 'ol', '仍然是ol'); + equal(body.childNodes.length, 2, 'body有两个孩子ol'); + equal(body.lastChild.childNodes.length, 2, '下面和上面的列表合并到上面去了'); +//TODO 1.2.6不严重bug注释 空style未删除 +// equal( ua.getChildHTML( editor.body ), '
    1. hello3

    1. hello1

    2. hello2

    ', '3个li子节点' ); +}); + +test('trace 3293:列表下的文本合并到列表中', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('
    1. hello3
    2. hello1

    文本1

    文本2

    '); + range.setStart(body, 1).setEnd(body, 3).select(); + /*选中文本变为有序列表,和上面的列表合并了*/ + editor.execCommand('insertorderedlist'); + var ol = body.firstChild; + equal(body.childNodes.length, 1, '所有合并为一个列表'); + equal(ol.tagName.toLowerCase(), 'ol', '仍然是ol'); + equal(ol.childNodes.length, 4, '下面和上面的列表合并到上面去了'); + equal(ua.getChildHTML(body.firstChild), '
  • hello3

  • hello1

  • 文本1

  • 文本2

  • ', '4个li子节点'); +}); + +test('2个相同类型的列表合并', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('
    1. hello3
    2. hello1
    1. 文本1

    2. 文本2

    '); + range.selectNode(body.lastChild).select(); + editor.execCommand('insertorderedlist'); + var ol = body.firstChild; + equal(body.childNodes.length, 1, '所有合并为一个列表'); + equal(ol.tagName.toLowerCase(), 'ol', '仍然是ol'); + equal(ol.childNodes.length, 4, '下面和上面的列表合并到上面去了'); + equal(ua.getChildHTML(body.firstChild), '
  • hello3

  • hello1

  • 文本1

  • 文本2

  • ', '4个li子节点'); +}); + +test('不闭合情况h1套列表', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    hello1

    hello2

    '); + range.setStart(body.firstChild, 0).setEnd(body.lastChild, 1).select(); + /*对h1添加列表*/ + editor.execCommand('insertorderedlist'); + equal(body.firstChild.tagName.toLowerCase(), 'ol', '仍然是ol'); + equal(ua.getChildHTML(body.firstChild), '
  • hello1

  • hello2

  • ', '查看插入列表后的结果'); + equal(body.childNodes.length, 1, 'body只有一个孩子ol'); + equal(body.firstChild.childNodes.length, 2, '2个li'); +}); + +test('闭合情况h1套列表', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    hello1

    '); + range.setStart(body.firstChild, 0).collapse(1).select(); + /*对h1添加列表*/ + editor.execCommand('insertorderedlist'); + equal(body.firstChild.tagName.toLowerCase(), 'ol', '仍然是ol'); + equal(ua.getChildHTML(body.firstChild), '
  • hello1

  • ', '查看插入列表后的结果'); + equal(body.childNodes.length, 1, 'body只有一个孩子ol'); + equal(body.firstChild.childNodes.length, 1, '1个li'); +}); + +test('列表内后退', function () { + /*实际操作没问题,取range时会在将文本节点分为两个节点,后退操作无法实现*/ + if ((ua.browser.safari && !ua.browser.chrome)) + return 0; + var editor = te.obj[0]; + var range = te.obj[1]; + + var lis; + var br = ua.browser.ie ? '
    ' : '
    '; +//////标签空格的处理 + editor.setContent('

    1. hello2


    2. hello3
    3. hello4

    4. hello5

    '); +// editor.setContent('

    1. hello2

    2. hello3
    3. hello4

    4. hello5

    '); + range.setStart(editor.body.firstChild.lastChild.firstChild.firstChild, 0).collapse(1).select(); + ua.manualDeleteFillData(editor.body); + ua.keydown(editor.body, {keyCode:8}); + + var ol = editor.body.getElementsByTagName('ol'); + lis = editor.body.getElementsByTagName('li'); + equal(lis.length, '5', '变成5个列表项'); + equal(ua.getChildHTML(editor.body.firstChild), '
  • ' + br + '

  • hello2

  • ' + br + '

  • hello3
  • hello4

    hello5

  • ', '最后一个列表项'); + range.setStart(lis[0].firstChild, 0).collapse(1).select(); + ua.keydown(editor.body, {keyCode:8}); + + lis = editor.body.getElementsByTagName('li'); + equal(lis.length, '4', '变成4个列表项'); + equal(ua.getChildHTML(editor.body.lastChild), '
  • hello2

  • ' + br + '

  • hello3
  • hello4

    hello5

  • ', '第一个列表项且为空行'); + range.setStart(lis[1].firstChild, 0).collapse(1).select(); + ua.keydown(editor.body, {keyCode:8}); + + lis = editor.body.getElementsByTagName('li'); + equal(lis.length, '3', '变成3个列表项'); + equal(ua.getChildHTML(editor.body.lastChild), '
  • hello2

    ' + br + '

  • hello3
  • hello4

    hello5

  • ', '中间列表项且为空行'); + if (!ua.browser.ie) { + range.setStart(lis[1].firstChild.firstChild, 0).collapse(1).select(); + ua.manualDeleteFillData(editor.body); + ua.keydown(editor.body, {keyCode:8}); +//TODO 1.2.6不严重bug注释 空style未删除 +// equal(ua.getChildHTML(editor.body),'


    1. hello2


      hello3
    2. hello4

      hello5

    ','自定义标签后退'); + } + +}); + +test('列表内回车', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + var lis; + var br = ua.browser.ie ? '' : '
    '; + editor.setContent('
    '); + lis = editor.body.getElementsByTagName('li'); + range.setStart(lis[0], 0).collapse(1).select(); + ua.keydown(editor.body, {keyCode:13}); + var spa = ua.browser.opera ? '
    ' : ''; + equal(ua.getChildHTML(editor.body), spa + '

    ', '空列表项回车--无列表'); + + editor.setContent('
    1. hello1

      hello2

    '); + lis = editor.body.getElementsByTagName('li'); + range.setStart(lis[0].lastChild, 0).collapse(1).select(); + ua.keydown(editor.body, {keyCode:13}); + equal(ua.getChildHTML(editor.body.firstChild), '
  • hello1

  • hello2

  • ', '单个列表项内回车'); +//////标签空格的处理 +// editor.setContent('

    1. hello5



    '); + editor.setContent('

    1. hello5



    '); + lis = editor.body.getElementsByTagName('li'); + range.setStart(lis[2].firstChild.firstChild, 0).setEnd(lis[2].lastChild.firstChild, 0).select(); + ua.keydown(editor.body, {keyCode:13}); +//TODO 1.2.6不严重bug注释 空style未删除 +// equal(ua.getChildHTML(editor.body),'
    1. '+br+'

    2. hello5

    '+br+'

    ','最后一个列表项为空行回车'); + + /*trace 2652*/ + range.setStart(editor.body.firstChild.firstChild.firstChild, 0).collapse(1).select(); + ua.keydown(editor.body, {keyCode:13}); +//TODO 1.2.6不严重bug注释 空style未删除 +// equal(ua.getChildHTML(editor.body),'

    '+br+'

    1. hello5

    '+br+'

    ','第一个列表项为空行下回车'); + + /*trace 2653*/ + editor.setContent('
    1. hello2

    2. hello3


    3. hello5

    '); + lis = editor.body.getElementsByTagName('li'); + range.setStart(lis[0].firstChild.firstChild, 2).setEnd(lis[1].firstChild.firstChild, 4).select(); + ua.keydown(editor.body, {keyCode:13}); + equal(ua.getChildHTML(editor.body.firstChild), '
  • he

  • o3


  • hello5

  • ', '非闭合回车'); + + editor.setContent('
    1. hello

      hello4

    2. hello5

    '); + lis = editor.body.getElementsByTagName('li'); + range.setStart(lis[0].lastChild.firstChild, 1).setEnd(lis[0].lastChild.firstChild, 2).select(); + ua.keydown(editor.body, {keyCode:13}); + equal(ua.getChildHTML(editor.body.firstChild), '
  • hello

    h

  • llo4

  • hello5

  • ', '一个列表项内两行'); + +}); + +test('tab键', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + var lis; + editor.setContent('
    1. hello1

    2. hello2

    '); + lis = editor.body.getElementsByTagName('li'); + range.setStart(lis[1], 0).collapse(1).select(); + ua.keydown(editor.body, {keyCode:9}); + ua.keydown(editor.body, {keyCode:9}); + var str = '
  • hello1

      1. hello2

    '; + ua.checkSameHtml(str, editor.body.firstChild.innerHTML.toLowerCase(), '有序列表---tab键'); + +}); + +test('回车后产生新的li-选区闭合', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    hello1

    hello2

    '); + setTimeout(function () { + range.setStart(body.firstChild, 0).setEnd(body.firstChild.nextSibling, 1).select(); + editor.execCommand('insertorderedlist'); + var lastLi = body.firstChild.lastChild.firstChild.firstChild; + range.setStart(lastLi, lastLi.length).collapse(1).select(); + setTimeout(function () { + ua.keydown(editor.body, {'keyCode':13}); + equal(body.firstChild.childNodes.length, 3, '回车后产生新的li'); + equal(body.firstChild.lastChild.tagName.toLowerCase(), 'li', '回车后产生新的li'); + var br = ua.browser.ie ? '' : '
    '; + equal(ua.getChildHTML(body.firstChild), '
  • hello1

  • hello2

  • ' + br + '

  • ', '检查内容'); + var lastLi = body.firstChild.lastChild.firstChild.firstChild; + range.setStart(lastLi, lastLi.length).collapse(1).select(); + setTimeout(function () { + ua.keydown(editor.body, {'keyCode':13}); + equal(body.firstChild.childNodes.length, 2, '空li后回车,删除此行li'); + equal(body.lastChild.tagName.toLowerCase(), 'p', '产生p'); + br = ua.browser.ie ? '' : '
    '; + ua.manualDeleteFillData(body.lastChild); + equal(body.lastChild.innerHTML.toLowerCase().replace(/\r\n/ig, ''), br, '检查内容'); + start() + }, 20); + }, 20); + }, 50); + stop(); +}); + +/*trace 3074*/ +test('trace 1622:表格中插入列表', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('

    你好
    hello2你好2
    '); + /*必须加br,否则没办法占位*/ + stop() + setTimeout(function () { + var tds = body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(1).select(); + /*选中一个单元格*/ + editor.execCommand('insertorderedlist'); + /*插入有序列表*/ + equal(tds[0].firstChild.tagName.toLowerCase(), 'ol', '查询列表的类型'); + equal(tds[0].firstChild.style['listStyleType'], 'decimal', '查询有序列表的类型'); + var br = baidu.editor.browser.ie ? "
    " : "
    "; + equal(ua.getChildHTML(tds[0].firstChild), '
  • ' + '

    ' + br + '

    ' + '
  • '); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + /*选中多个单元格*/ + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[1]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + tds = body.getElementsByTagName('td'); + editor.execCommand('insertunorderedlist', 'circle'); + /*插入无序列表*/ + equal(tds[1].firstChild.tagName.toLowerCase(), 'ul', '查询无序列表'); + equal(tds[1].firstChild.style['listStyleType'], 'circle', '查询无序列表的类型'); + equal(ua.getChildHTML(tds[1].firstChild), '
  • 你好
  • '); + equal(ua.getChildHTML(tds[3].firstChild), '
  • 你好2
  • '); + start(); + }, 50); + }, 50); +}); + +///*presskey*/ +//test( ' trace 1536:删除部分列表', function () { +// var editor = te.obj[0]; +// editor.setContent( '
    1. hello1
    2. 你好
    3. hello3
    ' ); +// var body = editor.body; +// var range = te.obj[1]; +// stop(); +// expect( 2 ); +// range.setStart( body.firstChild, 1 ).setEnd( body.firstChild, 2 ).select(); +// editor.focus(); +// te.presskey( 'del', '' ); +// editor.focus(); +// setTimeout( function () { +// equal( body.childNodes.length, 1, '删除后只剩一个ol元素' ); +// var br = (baidu.editor.browser.ie || baidu.editor.browser.gecko) ? "" : "
    "; +// //todo 不同浏览器原生选区的差别导致 +//// equal( ua.getChildHTML( body ), '
    1. hello1

    2. hello3' + br + '

    ', '第二个li被删除' ); +// start(); +// }, 30 ); +//} ); +///*presskey*/ +//test( ' trace 1544,1624 :列表中回车后再回退,会产生一个空行', function () { +// var editor = te.obj[0]; +// editor.setContent( '
    1. hello1

    2. 你好

    ' ); +// var body = editor.body; +// var ol = body.firstChild; +// var range = te.obj[1]; +// +// range.setStart( ol.firstChild.firstChild, 1 ).collapse( 1 ).select(); +// editor.focus(); +// te.presskey( 'enter', '' ); +// equal(editor.selection.getRange().startContainer.parentNode.innerHTML,''); +// +// setTimeout( function () { +// range.setStart( ol.childNodes[1], 0 ).collapse( 1 ).select(); +// equal(editor.selection.getRange().startContainer.parentNode.innerHTML,''); +// editor.focus(); +// te.presskey( 'back', '' ); +// setTimeout( function () { +// editor.focus(); +// var br = ua.browser.ie ? "" : "
    "; +// equal( ua.getChildHTML( body ), '
    1. hello1

      ' + br + '

    2. 你好

    ', '第二个li被删除' ); +// range.setStart( body, 0 ).setEnd( body, 1 ).select(); +// editor.execCommand( 'insertorderedlist' ); +// equal( ua.getChildHTML( body ), '

    hello1

    ' + br + '

    你好

    ', '应当变为纯文本' ); +// start(); +// }, 70 ); +// }, 50 ); +// stop(); +//} ); + +test('trace1620:修改上面的列表与下面的列表一致', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    你好

    1. 数字列表1

    2. 数字列表2

    1. 字母列表2

    2. 字母列表2

    '); + range.selectNode(editor.body.firstChild.nextSibling).select(); + editor.execCommand('insertorderedlist', 'lower-alpha'); + var html = '

    你好

    1. 数字列表1

    2. 数字列表2

    3. 字母列表2

    4. 字母列表2

    ' + ua.checkSameHtml(html, editor.body.innerHTML.toLowerCase(), '检查列表结果'); +}); + +test('trace 1621:选中多重列表,设置为相同类型的列表', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent('
    1. 数字列表1

    2. 数字列表2

    1. 字母列表1

    2. 字母列表2

    1. ​大写字母1

    2. 大写字母2

    3. 大写字母3

    '); + range.setStart(body, 1).setEnd(body.lastChild.firstChild.nextSibling, 1).select(); + var html = '
    1. 数字列表1

    2. 数字列表2

    1. 字母列表1

    2. 字母列表2

    3. 大写字母1

    4. 大写字母2

    5. 大写字母3

    '; + editor.execCommand('insertorderedlist', 'upper-alpha'); + ua.checkSameHtml(html, editor.body.innerHTML.toLowerCase(), 'trace 1621'); +}); +//TODO 1.2.6不严重bug注释 空style未删除 +//test( 'trace 3049:列表内有引用', function () { +// var editor = te.obj[0]; +// editor.setContent( '
    1. a

    2. b

    ' ); +// editor.execCommand( 'selectall'); +// editor.execCommand( 'blockquote' ); +// var html = '
    1. a

    2. b

    '; +// equal(ua.getChildHTML(editor.body),html,'检查列表结果'); +//}); + +/*trace 3056:模拟不完全,还需手动测试*/ +test('trace 3056:列表内表格后回车', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + var body = editor.body; + editor.setContent('
    1. a


    2. c

    '); + var lis = editor.body.getElementsByTagName('li'); + range.setStart(lis[1].firstChild, 0).collapse(true).select(); + + setTimeout(function () { + editor.execCommand('inserttable'); + var tds = body.getElementsByTagName('td'); + tds[0].innerHTML = 'asd
    '; + range.setStart(tds[0].firstChild, 3).collapse(true).select(); + setTimeout(function () { + ua.keydown(body, {'keyCode':13}); + equal(body.childNodes.length, 1, 'body只有一个孩子'); + equal(editor.body.getElementsByTagName('li').length, 3, 'ol有3个孩子'); + equal(editor.body.getElementsByTagName('table').length, 1, '只有1个table'); + start() + }, 20); + }, 50); + stop(); +}); + +/*trace 3075:fix in future*/ +//test( 'trace 3075:表格标题行中插入有序列表', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '









    ' ); /*必须加br,否则没办法占位*/ +// var ths = body.getElementsByTagName( 'th' ); +// range.setStart( ths[1], 0 ).collapse( 1 ).select(); /*选中一个单元格*/ +// editor.execCommand( 'insertorderedlist' ); /*插入有序列表*/ +// equal( ths[1].firstChild.tagName.toLowerCase(), 'ol', '查询列表的类型' ); +// equal( ths[1].firstChild.style['listStyleType'], 'decimal', '查询有序列表的类型' ); +// var br = baidu.editor.browser.ie ? "" : "
    "; +// equal( ua.getChildHTML( ths[0].firstChild ), '
  • ' + '

    ' + br + '

    ' + '
  • ' ); +// stop(); +// setTimeout(function() { +// editor.execCommand('source'); +// setTimeout(function() { +// editor.execCommand('source'); +// equal( body.getElementsByTagName('table').length, 1, '只有1个table' ); +// start(); +// },20); +// },20); +//} ); +//test( 'trace 3075:表格标题行中插入无序列表', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// var body = editor.body; +// editor.setContent( '









    ' ); /*必须加br,否则没办法占位*/ +// var trs = editor.body.firstChild.getElementsByTagName( 'tr' ); /*选中多个单元格*/ +// var ut = editor.getUETable(editor.body.firstChild); +// var cellsRange = ut.getCellsRange(trs[0].cells[1],trs[0].cells[2]); +// ut.setSelected(cellsRange); +// range.setStart( trs[0].cells[1], 0 ).collapse( true ).select(); +// var ths = body.getElementsByTagName( 'th' ); +// editor.execCommand( 'insertunorderedlist', 'circle' ); /*插入无序列表*/ +// equal( ths[1].firstChild.tagName.toLowerCase(), 'ul', '查询无序列表' ); +// equal( ths[1].firstChild.style['listStyleType'], 'circle', '查询无序列表的类型' ); +// stop(); +// setTimeout(function() { +// editor.execCommand('source'); +// setTimeout(function() { +// editor.execCommand('source'); +// equal( body.getElementsByTagName('table').length, 1, '只有1个table' ); +// start(); +// },20); +// },20); +//} ); + +test('trace 3117:列表内后退两次', function () { + /*实际操作没问题,取range时会在将文本节点分为两个节点,后退操作无法实现*/ + if ((ua.browser.safari && !ua.browser.chrome))return 0; + var editor = te.obj[0]; + var range = te.obj[1]; + + var br = ua.browser.ie ? '
    ' : '
    '; + editor.setContent('
    1. hello

    '); + + range.setStart(editor.body.firstChild.lastChild.firstChild, 0).collapse(1).select(); + ua.manualDeleteFillData(editor.body); + ua.keydown(editor.body, {keyCode:8}); + var ol = editor.body.getElementsByTagName('ol'); + var lis = editor.body.getElementsByTagName('li'); + equal(lis.length, '1', '变成1个列表项'); + equal(ua.getChildHTML(editor.body.firstChild), '
  • hello

    ' + br + '

  • ', '检查列表内容'); +//TODO 1.2.6不严重bug注释 空style未删除 +// range.setStart(lis[0].lastChild,0).collapse(1).select(); +// ua.keydown(editor.body,{keyCode:8}); +// equal(ua.getChildHTML(editor.body),'
    1. hello

    '+br+'

    ','检查body内容'); + /*模拟不到光标跳到上一行?*/ +// range.setStart(editor.body.lastChild,0).collapse(1).select(); +// ua.keydown(editor.body,{keyCode:8}); +// equal(ua.getChildHTML(editor.body),'
    1. hello

    ','检查body内容'); + +}); + +/*trace 3136*/ +test('trace 3118:全选后backspace', function () { + /*实际操作没问题,取range时会在将文本节点分为两个节点,后退操作无法实现*/ + if ((ua.browser.safari && !ua.browser.chrome))return 0; + var editor = te.obj[0]; + var range = te.obj[1]; + + var br = ua.browser.ie ? '' : '
    '; + editor.setContent('
    1. hello

    '); + ua.keydown(editor.body, {'keyCode':65, 'ctrlKey':true}); + ua.keydown(editor.body, {keyCode:8}); + equal(ua.getChildHTML(editor.body), '

    ' + br + '

    ', ''); + ok(!editor.queryCommandState('insertorderedlist'), 'state是0'); + +}); + +test('trace 3126:1.2.5+列表重构新增标签,tab键', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + var body = editor.body; + editor.setContent('

    hello1

    hello2

    hello3

    hello4

    '); + editor.execCommand('selectAll'); + editor.execCommand('insertorderedlist', 'cn2'); + var lis = body.getElementsByTagName('li'); + range.setStart(lis[1].firstChild, 0).setEnd(lis[2].firstChild, 1).select(); + ua.keydown(editor.body, {keyCode:9}); + var str = '
  • hello1

    1. hello2

    2. hello3

  • hello4

  • '; + ua.checkSameHtml(str, editor.body.firstChild.innerHTML.toLowerCase(), '有序列表---tab键'); + +}); + +test('trace 3132:单行列表backspace', function () { + /*实际操作没问题,取range时会在将文本节点分为两个节点,后退操作无法实现*/ + if ((ua.browser.safari && !ua.browser.chrome))return 0; + var editor = te.obj[0]; + var range = te.obj[1]; + + editor.setContent('

    '); + range.selectNode(editor.body.firstChild.firstChild.firstChild.firstChild).select(); + ua.keydown(editor.body, {keyCode:8}); + var space ='
    '; + equal(ua.getChildHTML(editor.body), '

    '+space+'

    ', ''); + +}); + +test('trace 3133:表格中插入列表再取消列表', function () { + /*实际操作没问题,取range时会在将文本节点分为两个节点,后退操作无法实现*/ + if ((ua.browser.safari && !ua.browser.chrome))return 0; + var editor = te.obj[0]; + var range = te.obj[1]; + + var body = editor.body; + var br = baidu.editor.browser.ie ? "" : "
    "; + editor.setContent('

    '); + /*插入一行一列的表格*/ + var tds = body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(1).select(); + editor.execCommand('insertorderedlist', 'num2'); + /*插入列表*/ + equal(tds[0].firstChild.tagName.toLowerCase(), 'ol', '查询列表的类型'); + equal(ua.getChildHTML(tds[0].firstChild), '

  • '); + editor.execCommand('insertorderedlist', 'num2'); + /*取消列表*/ + equal(ua.getChildHTML(tds[0]), '


    '); + ua.keydown(editor.body, {'keyCode':65, 'ctrlKey':true}); + /*ctrl+a*/ + ua.keydown(editor.body, {keyCode:8}); + /*backspace*/ + equal(ua.getChildHTML(editor.body), '

    ' + br + '

    ', ''); + +}); + +test('trace 3164:添加列表,取消列表', function () { + var editor = te.obj[0]; + var body = editor.body; + editor.setContent('

    hello1

    hello2

    hello3

    hello4

    '); + editor.execCommand('selectAll'); + editor.execCommand('insertunorderedlist', 'dash'); + equal(body.firstChild.tagName.toLowerCase(), 'ul', '检查无序列表'); + equal(body.firstChild.className, 'custom_dash list-paddingleft-1', '查询有序列表的类型'); + equal(editor.queryCommandValue('insertunorderedlist'), 'dash', '查询插入无序列表的结果'); + ok(editor.queryCommandState('insertunorderedlist'), 'state是1'); + editor.execCommand('selectAll'); + editor.execCommand('insertunorderedlist', 'dash'); + ua.checkHTMLSameStyle('

    hello1

    hello2

    hello3

    hello4

    ', editor.document, editor.body, '取消列表'); + equal(editor.queryCommandValue('insertunorderedlist'), null, '查询取消无序列表的结果'); + ok(!editor.queryCommandState('insertunorderedlist'), 'state是0'); +}); + +test('trace 3165:检查表格中列表tab键', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + setTimeout(function () { + editor.execCommand('inserttable'); + var tds = body.getElementsByTagName('td'); + range.setStart(tds[6], 0).collapse(1).select(); + editor.execCommand('insertorderedlist'); + equal(tds[6].firstChild.style['listStyleType'], 'decimal', '查询有序列表的类型'); + tds = body.getElementsByTagName('td'); + range.setStart(tds[5], 0).collapse(1).select(); + range = editor.selection.getRange(); + if(ua.browser.ie==9||ua.browser.ie==10) + equal(range.startContainer.tagName.toLowerCase(), 'td', 'tab键前光标位于td中'); + + else + equal(range.startContainer.parentNode.tagName.toLowerCase(), 'td', 'tab键前光标位于td中'); + ua.keydown(editor.body, {keyCode:9}); + setTimeout(function () { + range = editor.selection.getRange(); + if (!ua.browser.gecko && !ua.browser.ie && !ua.browser.webkit)//TODO 1.2.6 + equal(range.startContainer.parentNode.tagName.toLowerCase(), 'li', 'tab键后光标跳到有列表的单元格中'); + equal(tds[6].firstChild.style['listStyleType'], 'decimal', '检查有序列表的类型不应该被改变'); + start(); + }, 100); + }, 100); + stop(); +}); + +test('trace 3168:表格中列表更改样式', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.execCommand('inserttable'); + var tds = body.getElementsByTagName('td'); + tds[0].innerHTML = 'asdf'; + tds[1].innerHTML = '
    1. asd

    '; + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[0].cells[1]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + + editor.execCommand('insertorderedlist', 'cn1'); + equal(tds[0].firstChild.className, 'custom_cn1 list-paddingleft-1', '查询有序列表的类型'); + equal(tds[1].firstChild.className, 'custom_cn1 list-paddingleft-1', '查询有序列表的类型'); + equal(editor.queryCommandValue('insertorderedlist'), 'cn1', '查询插入有序列表的结果'); + + editor.execCommand('insertunorderedlist', 'dot'); + equal(tds[0].firstChild.className, 'custom_dot list-paddingleft-1', '查询无序列表的类型'); + equal(tds[1].firstChild.className, 'custom_dot list-paddingleft-1', '查询无序列表的类型'); + equal(editor.queryCommandValue('insertunorderedlist'), 'dot', '查询插入无序列表的结果'); + start(); + }, 50); + stop(); +}); +//todo 1.2.6.1 +//test('trace 3213 3499:tab键后更改列表样式', function () { +// var div = document.body.appendChild(document.createElement('div')); +// div.id = 'ue'; +// var editor = UE.getEditor('ue'); +// editor.ready(function () { +// var range = new baidu.editor.dom.Range(editor.document); +// editor.setContent('
    1. hello1

    2. hello2

    3. hello1

    4. hello1

    '); +// var lis = editor.body.getElementsByTagName('li'); +// range.setStart(lis[2], 0).setEnd(lis[3], 1).select(); +// ua.keydown(editor.body, {keyCode:9}); +// ua.keydown(editor.body, {'keyCode':65, 'ctrlKey':true}); +// editor.execCommand('insertorderedlist', 'lower-alpha'); +// var str = '
    1. hello1

    2. hello2

    3. hello1

    4. hello1

    '; +// ua.checkSameHtml(str, editor.body.innerHTML.toLowerCase(), ''); +// UE.delEditor('ue'); +// start(); +// }); +// stop(); +//}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/music.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/music.js new file mode 100644 index 000000000..c155a2d14 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/music.js @@ -0,0 +1,17 @@ +module( 'plugins.music' ); + +test( ' trace 3745 3780 音乐', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello

    ' ); + range.setStart(editor.body.firstChild,0).collapse(true).select(); + editor.execCommand( 'music',{url:"http://box.baidu.com/widget/flash/bdspacesong.swf?from=tiebasongwidget&url=…artist=%E5%BC%A0%E6%B6%A6%E8%B4%9E&extra=Vol.%202&autoPlay=false&loop=true"}); + stop(); + setTimeout(function(){ + ua.manualDeleteFillData(editor.body); + ua.checkSameHtml(editor.getContent(),'

    hello

    ',''); + equal(editor.body.firstChild.firstChild.tagName.toLowerCase(),'img'); + equal(editor.body.firstChild.firstChild.className,'edui-faked-music'); + start(); + },50); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/pagebreak.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/pagebreak.js new file mode 100644 index 000000000..151884868 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/pagebreak.js @@ -0,0 +1,148 @@ +module( 'plugins.pagebreak' ); + +/*trace 1179*/ +//TODO bug没有修复,暂时注释 +test( '对合并过单元格的表格分页', function () { + stop(); + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    ' ); + range.setStart( editor.body.firstChild, 0 ).collapse( true ).select(); + editor.execCommand( 'inserttable', {numCols:5, numRows:5} ); + var trs = editor.body.getElementsByTagName( 'tr' ); + range.setStart( trs[0].firstChild, 0 ).collapse( 1 ).select(); + + editor.currentSelectedArr = [trs[0].firstChild, trs[1].firstChild, trs[2].firstChild, trs[3].firstChild]; + editor.execCommand( 'mergecells' ); + editor.currentSelectedArr = [trs[1].childNodes[2], trs[1].childNodes[3], trs[2].childNodes[2], trs[2].childNodes[3]]; + editor.execCommand( 'mergecells' ); + range.setStart( trs[1].childNodes[1], 0 ).collapse( 1 ).select(); + + editor.execCommand( 'pagebreak' ); + var tables = editor.body.getElementsByTagName( 'table' ); + var tr1 = tables[0].getElementsByTagName( 'tr' ); + equal( tables.length, 2, '应当拆为2个table' ); + equal( tr1.length, 1, '第一个table只有一行' ); +// equal( $( tr1 ).attr( 'rowspan' ), 1, 'rowspan为1' ); +// +// tr1 = tables[1].getElementsByTagName( 'tr' ); +// equal( tr1.length, 3, '第2个table有3行' ); +// equal( $( tr1[0] ).attr( 'rowspan' ), 2, 'rowspan为2' ); + setTimeout( function () { + /*src中有延时操作*/ + start(); + }, 200 ); +} ); + +test( '对第一行的单元格进行分页', function () { + stop(); + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    ' ); + range.setStart( editor.body.firstChild, 0 ).collapse( true ).select(); + editor.execCommand( 'inserttable', {numCols:5, numRows:5} ); + var tds = editor.body.getElementsByTagName( 'td' ); + range.setStart( tds[1], 0 ).collapse( 1 ).select(); + var table = editor.body.getElementsByTagName( 'table' )[0]; + var tablehtml = ua.getChildHTML( table ); + + editor.execCommand( 'pagebreak' ); + var hr = editor.body.firstChild; + equal( ua.getChildHTML( editor.body.getElementsByTagName( 'table' )[0] ), tablehtml, '表格没发生变化' ); + equal( $( hr ).attr( 'class' ), 'pagebreak', '插入一个分页符' ); + equal( hr.tagName.toLowerCase(), 'hr', 'hr' ); + setTimeout( function () { +/*trace 2383*/ +// range.setStart( tds[1], 0 ).collapse( 1 ).select(); +// editor.execCommand( 'pagebreak' ); +// range.setStart( tds[1], 0 ).collapse( 1 ).select(); +// editor.execCommand( 'pagebreak' ); +// editor.execCommand('source'); +// editor.execCommand('source'); +// var hr = editor.body.getElementsByTagName( 'hr' ); +// equal( ua.getChildHTML( editor.body.getElementsByTagName( 'table' )[0] ), tablehtml, '表格没发生变化' ); +// equal( $( hr[0] ).attr( 'class' ), 'pagebreak', '插入一个分页符' ); +// equal( hr.length, 3, 'hr' ); + start(); + }, 200 ); +} ); + +test( '对最后一行的单元格进行分页', function () { + stop(); + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    ' ); + range.setStart( editor.body.firstChild, 0 ).collapse( true ).select(); + editor.execCommand( 'inserttable', {numCols:5, numRows:5} ); + var tds = editor.body.getElementsByTagName( 'td' ); + /*最后一行的单元格*/ + range.setStart( tds[24], 0 ).collapse( 1 ).select(); + editor.execCommand( 'pagebreak' ); + var ts = editor.body.getElementsByTagName( 'table' ); + var hr = editor.body.childNodes[1]; + equal( ts[0].getElementsByTagName( 'tr' ).length, 4, '第一个table 4行' ); + equal( ts[1].getElementsByTagName( 'tr' ).length, 1, '第2个table 1行' ); + equal( $( hr ).attr( 'class' ), 'pagebreak', '插入一个分页符' ); + equal( hr.tagName.toLowerCase(), 'hr', '插入的分页符是hr' ); + setTimeout( function () { + start(); + }, 200 ); +} ); + +test( '在段落中间闭合插入分页符', function () { + stop(); + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    你好Ueditor

    ' ); + range.setStart( editor.body.firstChild.firstChild, 2 ).collapse( true ).select(); + editor.execCommand( 'pagebreak' ); + ua.manualDeleteFillData( editor.body ); + equal( body.childNodes.length, 3, '3个孩子' ); + equal( ua.getChildHTML( body.firstChild ), '你好' ); + equal( body.firstChild.tagName.toLowerCase(), 'p', '第一个孩子是p' ); + equal( $( body.firstChild.nextSibling ).attr( 'class' ), 'pagebreak' ); + equal( ua.getChildHTML( body.lastChild ), 'ueditor' ); + equal( body.lastChild.tagName.toLowerCase(), 'p', '第二个孩子是p' ); + setTimeout( function () { + start(); + }, 100 ); +} ); + +test( '选中部分段落再插入分页符', function () { + stop(); + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    你好Ueditor

    hello编辑器

    ' ); + range.setStart( body.firstChild.firstChild, 2 ).setEnd( body.lastChild.firstChild, 5 ).select(); + editor.execCommand( 'pagebreak' ); + ua.manualDeleteFillData( editor.body ); + equal( body.childNodes.length, 3, '3个孩子' ); + equal( ua.getChildHTML( body.firstChild ), '你好' ); + equal( $( body.firstChild.nextSibling ).attr( 'class' ), 'pagebreak' ); + equal( ua.getChildHTML( body.lastChild ), '编辑器' ); + equal( body.firstChild.tagName.toLowerCase(), 'p', '第一个孩子是p' ); + equal( body.lastChild.tagName.toLowerCase(), 'p', '第二个孩子是p' ); + setTimeout( function () { + start(); + }, 200 ); +} ); + +test( 'trace 1887:连续插入2次分页符,每次插入都在文本后面', function () { + stop(); + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    你好

    ' ); + range.setStart( body.firstChild, 1 ).collapse( 1 ).select(); + editor.execCommand('pagebreak'); + range.setStart( body.firstChild, 1 ).collapse( 1 ).select(); + editor.execCommand('pagebreak'); + equal(body.childNodes.length,3,'3个孩子'); + //trace 1187,chrome和firefox下都会有br,目前的做法是第二次插入就把前一个删除 + equal(body.childNodes[1].childNodes.length,0,'hr没有孩子节点'); + setTimeout( function () { + start(); + }, 200 ); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/paragraph.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/paragraph.js new file mode 100644 index 000000000..30388c9e4 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/paragraph.js @@ -0,0 +1,107 @@ +module( "plugins.paragraph" ); +/** + * h1和p之间的转换 + * 表格中添加p和h1 + * 列表里加h1 + * 传入2个参数,style和attrs + */ + +test( '不闭合h1和p之间的转换', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello

    ' ); + setTimeout(function(){ + range.selectNode( body.firstChild.firstChild ).select(); + /*p===>h1*/ + editor.execCommand( 'paragraph', 'h1' ); + equal( ua.getChildHTML( body ), '

    hello

    ' ); + equal( editor.queryCommandValue( 'paragraph' ), 'h1', '当前的blcok元素为h1' ); + /*h1===>p*/ + range.selectNode( body.firstChild.firstChild ).select(); + editor.execCommand( 'paragraph', 'p' ); + equal( ua.getChildHTML( body ), '

    hello

    ' ); + /*多个段落的部分文本*/ + editor.setContent( '

    hello

    hello2

    ' ); + setTimeout(function(){ + range.setStart( body.firstChild.firstChild, 2 ).setEnd( body.lastChild.firstChild, 1 ).select(); + editor.execCommand( 'paragraph', 'h3' ); + equal( ua.getChildHTML( body ), '

    hello

    hello2

    ' ); + equal( editor.queryCommandValue( 'paragraph' ), 'h3', '当前的blcok元素为h3' ); + start(); + },50); + },50); + stop(); +} ); + +test( '闭合h1和p之间的转换', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello

    hello2

    ' ); + setTimeout(function(){ + range.setStart( body.firstChild.firstChild, 1 ).collapse( 1 ).select(); + /*p===>h1*/ + editor.execCommand( 'paragraph', 'h1' ); + equal( ua.getChildHTML( body ), '

    hello

    hello2

    ' ); + /*h1===>p*/ + range.setStart( body.firstChild.firstChild, 1 ).collapse( 1 ).select(); + editor.execCommand( 'paragraph', 'p' ); + equal( ua.getChildHTML( body ), '

    hello

    hello2

    ' ); + equal( editor.queryCommandValue( 'paragraph' ), 'p', '当前的blcok元素为p' ); + start(); + },50); + +stop(); +} ); + + +/*如果是h1===>p并且传参的话,h1不会变化。因为这段代码的操作是为了indent和justify做的,传入参数p只是为了好处理,所以不支持h1变为p*/ +test( '传入段落的样式', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello

    hello2

    ' ); + setTimeout(function(){ + range.setStart( body.firstChild.firstChild, 1 ).collapse( 1 ).select(); + /*p===>p,但是变化了样式*/ + editor.execCommand( 'paragraph', 'p', {style:'text-indent:2em'} ); + equal( body.firstChild.style.textIndent, '2em', '改变了第一个孩子的缩进量' ); + equal( body.firstChild.tagName.toLowerCase(), 'p', 'tagName仍然是p' ); + + /*p===>h4,但是变化了样式*/ + editor.execCommand( 'paragraph', 'h4', {style:'text-indent:3em'} ); + equal( body.firstChild.style['textIndent'], '3em', '改变了第一个孩子的缩进量' ); + equal( body.firstChild.tagName.toLowerCase(), 'h4', 'tagName是h4' ); + start(); +},50); + +stop(); +} ); + + +test( '对表格设置样式', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello1

    ' ); + setTimeout(function(){ + var tds = body.getElementsByTagName( 'td' ); + range.setStart( tds[0].firstChild, 0 ).collapse( 1 ).select(); + editor.currentSelectedArr = [tds[0]]; + /*h4===>p,但是变化了样式*/ + editor.execCommand( 'paragraph', 'p', {style:'text-indent:3em'} ); + equal( tds[0].firstChild.style['textIndent'], '3em', '改变了第一个孩子的缩进量' ); + equal( tds[0].firstChild.tagName.toLowerCase(), 'h1', 'tagName仍然是h1' ); + range.setStart( tds[1], 0 ).collapse( 1 ).select(); + editor.currentSelectedArr = [tds[1]]; + editor.execCommand( 'paragraph', 'p', {style:'text-indent:3em'} ); +// ua.manualDeleteFillData( editor.body ); + ua.clearWhiteNode(tds[1]); + equal( tds[1].firstChild.style['textIndent'], '3em', '改变了第一个孩子的缩进量' ); + equal( tds[1].firstChild.tagName.toLowerCase(), 'p', 'tagName是p' ); + start(); + },50); + + stop(); +} ); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/paste.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/paste.js new file mode 100644 index 000000000..3dddcaa1d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/paste.js @@ -0,0 +1,78 @@ +module( 'plugins.paste' ); + +//不能模拟出真实的粘贴效果,此用例用于检查中间值 +test( '粘贴', function() { + if(ua.browser.ie || ua.browser.opera)return; + var div = document.body.appendChild( document.createElement( 'div' ) ); + $( div ).css( 'width', '500px' ).css( 'height', '500px' ).css( 'border', '1px solid #ccc' ); + var me = te.obj[2]; + me.render(div); + stop(); + me.ready(function(){ + var range = new baidu.editor.dom.Range( te.obj[2].document ); + me.focus(); + me.setContent('

    hello

    '); + range.setStart(me.body.firstChild,0).collapse(true).select(); + ua.keydown(me.body,{'keyCode':65,'ctrlKey':true}); + ua.keydown(me.body,{'keyCode':67,'ctrlKey':true}); + setTimeout(function(){ + me.focus(); + range.setStart(me.body.firstChild,0).collapse(true).select(); + ua.paste(me.body,{'keyCode':86,'ctrlKey':true}); + equal(me.body.lastChild.id,'baidu_pastebin','检查id'); + equal(me.body.lastChild.style.position,'absolute','检查style'); + div.parentNode.removeChild(div); + start(); + },50); + stop(); + }); +} ); +//me.fireEvent('pasteTransfer','paste');//todo +test( 'getClipboardData--ctrl+v', function() { +// var editor = new baidu.editor.Editor( {'plugins':['paste']} ) +// var div = te.dom[0]; +// editor.render( div ); +// editor.focus(); +// editor.setContent( '

    你好

    ' ) +// var doc = editor.document; +// var r = new baidu.editor.dom.Range( doc ); +// /*从word中粘贴的未经过滤的列表*/ +// var html = '

    l  列表1

    l  列表2

    '; +// te.setClipData( html ); +// r.setStart( editor.body.firstChild, 1 ).collapse( 1 ).select(); +// editor.focus(); +// te.presskey( 'ctrl', 'v' ); +// editor.focus(); +// setTimeout( function() { +// equal( editor.body.firstChild.innerHTML, html ); +// start(); +// } ); +// stop(); + equal('','',''); +} ); + +//需要点击授权弹出框,暂时去除 +//test('检查IE下粘贴命令是否执行正常', function () { +// +// if (browser.ie) { +// var editor = te.obj[0]; +// editor.setContent('

    hello

    '); +// editor.focus(); +// +// editor.execCommand('selectall'); +// editor.body.document.execCommand('copy'); +// editor.setContent('

    test

    '); +// editor.execCommand('selectall'); +// editor.execCommand('paste'); +// +// setTimeout(function(){ +// equal(utils.trim(editor.getContent().replace('

    ', '').replace('

     

    ', '')), '

    hello

    ', '检查html内容,IE下成功粘贴内容'); +// equal(utils.trim(editor.getContentTxt()), 'hello', '检查text内容,IE下成功粘贴内容'); +// start(); +// },100); +// +// stop(); +// } +// +//}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/preview.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/preview.js new file mode 100644 index 000000000..2f50056a6 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/preview.js @@ -0,0 +1,22 @@ +module('plugins.preview'); + +test('插入代码后预览',function(){ +// var editor = te.obj[0]; +// var body = editor.body; +// var html = '
    1.  function addSpace(linenum){
    2.          if(linenum<10){
    3.              return "&nbsp;&nbsp;";
    4.          }else if(linenum>=10 && linenum<100){
    5.              return "&nbsp;";
    6.          }else if(linenum>=100 && linenum<1000){
    7.              return "";
    8.          }
    9.      }
    '; +// editor.setContent(html); +// editor.execCommand('preview'); +// ua.checkSameHtml(body.innerHTML,html,'预览不会对页面代码产生影响'); + equal('',''); +}); +//test('设置内容后后预览',function(){ +// if(ua.browser.gecko)return;//ff总不停打开窗口,实际操作没问题 +// var editor = te.obj[0]; +// var body = editor.body; +// var html = '

    你好,我亲爱的朋

    '; +// var html_ie10 ="

    你好,我亲爱的朋

    "; +// editor.setContent(html); +// editor.focus(); +// editor.execCommand('preview'); +// ua.checkSameHtml(body.innerHTML,(ua.browser.ie>8)?html_ie10:html,'预览不会对页面代码产生影响'); +//}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/print.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/print.js new file mode 100644 index 000000000..f5c47b0c8 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/print.js @@ -0,0 +1,17 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-9-28 + * Time: 下午1:34 + * To change this template use File | Settings | File Templates. + */ +module('plugins.print'); + +test('print',function(){ +// var editor = te.obj[0]; +// var html = '

    for print

    '; +// editor.setContent(html); +// editor.execCommand('print'); +// equal(editor.body.innerHTML,html,'打印不会对页面代码产生影响'); + equal('',''); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/removeformat.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/removeformat.js new file mode 100644 index 000000000..b785e49bc --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/removeformat.js @@ -0,0 +1,97 @@ +module( "plugins.removeformat" ); + +/*trace 860*/ +test( 'trace 860:对包含超链接的段落清除样式', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hellobaidu

    ' ); + range.setStart( editor.body.firstChild.firstChild.nextSibling.firstChild, 2 ).collapse( true ).select(); + editor.execCommand( 'removeformat' ); + equal( editor.getContent(), '

    hellobaidu

    ', '对包含超链接的段落去除样式' ); +} ); + +/*trace 800*/ +test( 'trace 800:清除超链接的颜色', function () { + var editor = te.obj[0]; + var range = te.obj[1]; +// var editor = te.obj[2]; +// var div = document.body.appendChild( document.createElement( 'div' ) ); +// $( div ).css( 'width', '500px' ).css( 'height', '500px' ).css( 'border', '1px solid #ccc' ); +// editor.render(div); +// stop(); +// setTimeout(function(){ +// var range = new baidu.editor.dom.Range( te.obj[2].document ); + editor.setContent('baidu'); + range.selectNode(editor.body.firstChild).select(); + editor.execCommand( 'forecolor', 'rgb(255,0,0)' ); + var html = 'baidu'; + ua.checkHTMLSameStyle( html, editor.document, editor.body.firstChild, '查看加了颜色后超链接的样式' ); + editor.execCommand( 'removeformat' ); + var cl = ua.browser.ie && ua.browser.ie == 8 ? 'class=\"\"' : ""; + html = 'baidu'; + if(!ua.browser.ie)//TODO 1.2.6 + ua.checkHTMLSameStyle( html, editor.document, editor.body.firstChild, '查看清除样式后超链接的样式' ); +// div.parentNode.removeChild(div); +// start(); +// },500); +} ); + +test( '清除颜色的区域有多个inline元素嵌套', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello1

    hello2

    ' ); + var strs = body.getElementsByTagName( 'strong' ); + range.setStart( strs[0].firstChild, 2 ).setEnd( strs[1].firstChild.firstChild, 3 ).select(); + editor.execCommand( 'removeformat' ); + equal( ua.getChildHTML( body ), '

    hello1

    hello2

    ' ); +} ); + +test( '指定删除某一个style', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello1

    hello2

    ' ); + var strs = body.getElementsByTagName( 'strong' ); + range.setStart( strs[0].firstChild, 2 ).setEnd( strs[1].firstChild.firstChild, 3 ).select(); + /*只删除span的color style*/ + editor.execCommand( 'removeformat', 'span', 'color' ); + var html = '

    hello1

    hello2

    '; + ua.checkHTMLSameStyle( html, editor.document, body, '检查去除特定标签的样式的结果' ); +} ); + +test( '指定删除的元素删除属性后是空元素', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello2

    ' ); + range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); + editor.execCommand( 'removeformat', 'span', 'color' ); + ua.checkHTMLSameStyle('hello2',editor.document,body.firstChild,'清除span corlor'); +} ); + +test( '闭合方式清除样式', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    hello1

    hello2

    ' ); + range.setStart( body.firstChild.firstChild, 0 ).collapse( 1 ).select(); + editor.execCommand( 'removeformat' ); + equal( ua.getChildHTML( body ), '

    hello1

    hello2

    ' ); +} ); + +//TODO 1.2.6 fixed in future +//test( 'trace 3294:移除表格中的样式', function () { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// editor.setContent( '
    表格文本1表格文本2
    ' ); +// var trs = editor.body.firstChild.getElementsByTagName( 'tr' ); +// var ut = editor.getUETable(editor.body.firstChild); +// var cellsRange = ut.getCellsRange(trs[0].cells[0],trs[0].cells[1]); +// ut.setSelected(cellsRange); +// range.setStart( trs[0].cells[0], 0 ).collapse( true ).select(); +// editor.execCommand( 'removeformat' ); +// equal( ua.getChildHTML( trs[0].cells[0] ), '表格文本1', '第一个表格的span被清除了' ); +// equal( ua.getChildHTML( trs[0].cells[1] ), '表格文本2', '第二个表格的span被清除了' ); +//} ); + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/rowspacing.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/rowspacing.js new file mode 100644 index 000000000..060295251 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/rowspacing.js @@ -0,0 +1,312 @@ +module( 'plugins.rowspacing' ); + +/*trace 1029*/ +test( '设置段前距查看状态反射', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello1

    hello2

    ' ); + stop(); + setTimeout(function () { + range.setStart( editor.body.firstChild, 0 ).setEnd( editor.body.lastChild, 1 ).select(); + editor.execCommand( 'rowspacing', 15 ,'top'); + equal( editor.queryCommandValue( 'rowspacing' ,'top'), 15, '查看段前距' ); + /*光标闭合时查看状态反射*/ + range.setStart( editor.body.firstChild.firstChild, 1 ).collapse( true ).select(); + equal( editor.queryCommandValue( 'rowspacing','top' ), 15, '查看段前距' ); + start(); + }, 50); +} ); + +/*trace 1035*/ +test( '非闭合清除段前距等样式,查看状态反射', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello1

    hello2

    ' ); + + range.setStart(editor.body.firstChild, 0).setEnd(editor.body.lastChild, 1).select(); + editor.execCommand('rowspacing', 20, 'top'); + equal(editor.queryCommandValue('rowspacing', 'top'), 20, '段前距为2.0'); + +} ); + +test( '闭合清除段前距等样式,查看状态反射', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello1

    hello2

    ' ); + range.setStart( editor.body.firstChild, 0 ).collapse( true ).select(); + editor.execCommand( 'rowspacing', 20 ,'top'); + equal( editor.queryCommandValue( 'rowspacing','top' ), 20, '段前距为2.0' ); + range.setStart( editor.body.firstChild, 0 ).collapse( true ).select(); + editor.execCommand( 'removeformat' ); + equal( editor.queryCommandValue( 'rowspacing' ,'top'), 5, '闭合清除格式后,段前距为5' ); +} ); + +/*trace 1026*/ +test( '设置段后距后设置字体颜色', function () { + var editor = te.obj[0]; + var range = te.obj[1]; +// var editor = te.obj[2]; +// var div = document.body.appendChild( document.createElement( 'div' ) ); +// $( div ).css( 'width', '500px' ).css( 'height', '500px' ).css( 'border', '1px solid #ccc' ); +// editor.render(div); + stop(); +// setTimeout(function(){ +// var range = new baidu.editor.dom.Range( editor.document ); + editor.setContent( '

    hello1hello

    hello2

    ' ); + range.setStart( editor.body.firstChild, 0 ).setEnd( editor.body.lastChild, 1 ).select(); + editor.execCommand( 'rowspacing', 15 ,'bottom'); + setTimeout(function(){ + editor.execCommand( 'forecolor', 'rgb(255,0,0)' ); + equal( editor.queryCommandValue( 'rowspacing' ,'bottom'), 15, '查看段后距' ); + /*闭合的方式去查看行距的状态反射*/ + range.setStart( editor.body.firstChild.firstChild, 1 ).collapse( true ).select(); + equal( editor.queryCommandValue( 'rowspacing' ,'bottom'), 15, '查看段后距' ); +// div.parentNode.removeChild(div); + start(); + },50); +// },50); +} ); + +test( '设置段后距后设置加粗等多种样式', function () { + var editor = te.obj[0]; + var range = te.obj[1]; +// var editor = te.obj[2]; +// var div = document.body.appendChild( document.createElement( 'div' ) ); +// $( div ).css( 'width', '500px' ).css( 'height', '500px' ).css( 'border', '1px solid #ccc' ); +// editor.render(div); + stop(); +// editor.ready(function(){ + setTimeout(function(){ +// var range = new baidu.editor.dom.Range( editor.document ); + editor.setContent( '

    hello1

    hello2

    ' ); + setTimeout(function(){ + range.setStart( editor.body.firstChild, 0 ).setEnd( editor.body.lastChild, 1 ).select(); + editor.execCommand( 'rowspacing', 15 ,'bottom'); + setTimeout(function(){ + editor.execCommand( 'bold' ); + editor.execCommand( 'underline' ); + equal( editor.queryCommandValue( 'rowspacing' ,'bottom'), 15, '查看段后距' ); +// div.parentNode.removeChild(div); + start(); + },50); + },50); + },100); +// }); +} ); + +test( '非闭合去除加粗等样式', function () { + var editor = te.obj[0]; + var range = te.obj[1]; +// var editor = te.obj[2]; +// var div = document.body.appendChild( document.createElement( 'div' ) ); +// $( div ).css( 'width', '500px' ).css( 'height', '500px' ).css( 'border', '1px solid #ccc' ); +// editor.render(div); + stop(); +// editor.ready(function(){ +// setTimeout(function(){ +// var range = new baidu.editor.dom.Range( editor.document ); + editor.setContent( '

    hello1

    hello2

    ' ); + setTimeout(function(){ + range.setStart( editor.body.firstChild, 0 ).setEnd( editor.body.lastChild, 1 ).select(); + editor.execCommand( 'rowspacing', 15 ,'bottom'); + setTimeout(function(){ + editor.execCommand( 'bold' ); + editor.execCommand( 'underline' ); + equal( editor.queryCommandValue( 'rowspacing' ,'bottom'), 15, '查看段后距' ); + editor.execCommand( 'removeformat' ); + equal( editor.queryCommandValue( 'rowspacing' ,'bottom'), 5, '去除样式后查看段后距' ); +// div.parentNode.removeChild(div); + start(); + },50); + },50); +// },100); +// }); +} ); + +test( '闭合去除样式', function () { + var editor = te.obj[0]; + var range = te.obj[1]; +// var editor = te.obj[2]; +// var div = document.body.appendChild( document.createElement( 'div' ) ); +// $( div ).css( 'width', '500px' ).css( 'height', '500px' ).css( 'border', '1px solid #ccc' ); +// editor.render(div); + stop(); +// editor.ready(function(){ +// +// var range = new baidu.editor.dom.Range( editor.document ); + editor.setContent( '

    hello1

    hello2

    ' ); + setTimeout(function(){ + range.setStart( editor.body.firstChild, 0 ).setEnd( editor.body.lastChild, 1 ).select(); + editor.execCommand( 'rowspacing', 15 ,'bottom'); + setTimeout(function(){ + editor.execCommand( 'bold' ); + editor.execCommand( 'underline' ); + /*采用闭合的方式查询段后距, + 介个好像用手选不太能选的出来,总是会选到里面去*/ + range.setStart( editor.body.firstChild, 0 ).collapse( true ).select(); + equal( editor.queryCommandValue( 'rowspacing','bottom' ), 15, '查看段后距' ); + /*闭合方式鼠标放在第二个p中*/ + range.setStart( editor.body.lastChild, 0 ).collapse( true ).select(); + equal( editor.queryCommandValue( 'rowspacing' ,'bottom'), 15, '查看段后距' ); + editor.execCommand( 'removeformat' ); + //1.2后改 + equal( editor.queryCommandValue( 'rowspacing' ,'bottom'), 5, '去除样式后查看段后距' ); + /*第一行的样式应当仍然在*/ + range.setStart( editor.body.firstChild, 0 ).collapse( true ).select(); + equal( editor.queryCommandValue( 'rowspacing' ,'bottom'), 15, '查看段后距' ); +// div.parentNode.removeChild(div); + start(); + },50); + },50); +// }); +} ); + +test( '表格中设置段距', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '
    hello1hello2
    ' ); + stop(); + setTimeout(function () { + var tds = editor.body.firstChild.getElementsByTagName('td'); + /*选中表格中的文本设置段前距*/ + range.selectNode(tds[0].firstChild).select(); + editor.execCommand('rowspacing', 20, 'top'); + equal(editor.queryCommandValue('rowspacing', 'top'), 20, '设置表格中文本段前距为2'); + /*采用闭合的方式查询段前距*/ + setTimeout(function () { + range.setStart(tds[0].firstChild.firstChild, 1).collapse(true).select(); + equal(editor.queryCommandValue('rowspacing', 'top'), 20, '设置表格中文本段前距为2'); + + /*闭合在表格中的文本设置段后距*/ + range.setStart(tds[1].firstChild, 1).collapse(true).select(); + editor.execCommand('rowspacing', 15, 'bottom'); + /*选中整个单元格查询段后距*/ + range.selectNode(tds[1]).select(); + equal(editor.queryCommandValue('rowspacing', 'bottom'), 15, '设置表格中文本段后距为1.5'); + /*闭合在空白单元格中设置段后距*/ + range.setStart(tds[2], 0).collapse(true).select(); + editor.execCommand('rowspacing', 25, 'bottom'); + equal(editor.queryCommandValue('rowspacing', 'bottom'), 25, '设置表格中文本段后距为2.5'); + start(); + }, 50); + }, 50); +}); + +test('跨多个单元格设置段前距', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('
    hello1hello2
    hello3

    hello4

    '); + stop(); + setTimeout(function () { + var tds = editor.body.firstChild.getElementsByTagName('td'); + var p = editor.body.getElementsByTagName('p'); + range.selectNode(editor.body.firstChild).select(); + editor.execCommand('rowspacing', 15, 'top'); + for (var index = 0; index < tds.length; index++) { + range.selectNode(tds[index]).select(); + equal(editor.queryCommandValue('rowspacing', 'top'), 15, '设置表格中文本段前距为1.5'); + /*会自动在非block元素外面套p*/ + //1.2版本,加在p上 + equal(p[index].style['marginTop'], '15px', '段前距属性都是加在第一个孩子节点上'); + } + start(); + }, 50); +} ); + +/*trace 1052*/ +test( '对插入的代码设置多倍段前距', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    ' ); + stop(); + setTimeout(function () { + range.setStart( editor.body.firstChild, 0 ).collapse( true ).select(); + var stylecode = "var tds = editor.body.firstChild.getElementsByTagName( 'td' );\n range.selectNode( editor.body.firstChild ).select();"; + editor.execCommand( 'inserthtml', "
    " + stylecode + "
    " ); + equal( editor.body.firstChild.tagName.toLowerCase(), 'pre', '第一个孩子节点为pre' ); + range.selectNode( editor.body.firstChild ).select(); + editor.execCommand( 'rowspacing', 20,'top' ); + var pre = editor.body.firstChild; + equal( pre.tagName.toLowerCase(), 'pre', '不允许将p换成pre' ); + equal( pre.style['borderWidth'], '1px', '宽度' ); + ok( pre.style['borderColor'].toUpperCase() == '#CCCCCC' || pre.style['borderColor'] == 'rgb(204, 204, 204)', '颜色' ); + start(); + }, 50); +} ); + +test( '在合并单元格中设置多倍段前距', function () { + var editor = new baidu.editor.Editor({'autoFloatEnabled':false}); + stop(); + setTimeout( function () { + var div = document.body.appendChild( document.createElement( 'div' ) ); + te.dom.push( div ); + editor.render( div ); + + setTimeout(function () { + editor.setContent('

    '); + var range = new baidu.editor.dom.Range(editor.document); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:3, numRows:3}); + stop(); + /*insertHTML有一个200ms的超时函数*/ + setTimeout(function () { + ua.manualDeleteFillData(editor.body); + var trs = editor.body.getElementsByTagName('tr'); + range.setStart(trs[0].firstChild, 0).setEnd(trs[1].firstChild, 0).select(); + editor.currentSelectedArr = [trs[0].firstChild, trs[1].firstChild]; + editor.execCommand('mergecells'); + /*合并单元格后设置这个单元格多倍段前距*/ + ua.manualDeleteFillData(editor.body); + range.setStart(trs[0].firstChild, 0).collapse(true).select(); + editor.execCommand('rowspacing', 20, 'top'); + ua.manualDeleteFillData(editor.body); + equal(trs[0].firstChild.firstChild.tagName.toLowerCase(), 'p', 'td下面创建了一个p'); + equal(trs[0].firstChild.firstChild.style['marginTop'], '20px', 'p设置了2倍行距'); + trs = editor.body.firstChild.getElementsByTagName('tr'); + equal(trs.length, 3, '3行'); + var tbodyChild = editor.body.getElementsByTagName('tbody')[0].childNodes; + for (var index = 0; index < tbodyChild.length; index++) { + equal(tbodyChild[index].tagName.toLowerCase(), 'tr', 'tbody下面都是tr'); + } + start(); + }, 30); + }, 300); + },50); +} ); + +/*trace 1079*/ +test( '合并单元格后设置多个单元格多倍段前距', function () { + var editor = new baidu.editor.Editor( {'plugins':['table'],'autoFloatEnabled':false} ); + stop(); + setTimeout(function () { + var div = document.body.appendChild(document.createElement('div')); + te.dom.push(div); + editor.render(div); + setTimeout(function () { + editor.setContent('

    '); + var range = new baidu.editor.dom.Range(editor.document); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:3, numRows:3}); + + setTimeout(function () { + ua.manualDeleteFillData(editor.body); + var trs = editor.body.firstChild.getElementsByTagName('tr'); + /*合并第一列前2个单元格*/ + range.setStart(trs[0].firstChild, 0).setEnd(trs[1].firstChild, 0).select(); + editor.currentSelectedArr = [trs[0].firstChild, trs[1].firstChild]; + editor.execCommand('mergecells'); + /*设置多倍段前距*/ + range.setStart(trs[0].firstChild, 0).setEnd(trs[2].firstChild, 0).select(); + editor.currentSelectedArr = [trs[0].firstChild, trs[1].firstChild, trs[2].firstChild]; + editor.execCommand('rowspacing', 20, 'top'); + trs = editor.body.firstChild.getElementsByTagName('tr'); + equal(trs.length, 3, '3行'); + var tbodyChild = editor.body.getElementsByTagName('tbody')[0].childNodes; + for (var index = 0; index < tbodyChild.length; index++) { + equal(tbodyChild[index].tagName.toLowerCase(), 'tr', 'tbody下面都是tr'); + } + start(); + }, 50); + }, 300); + },50); +} ); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/scrawl.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/scrawl.js new file mode 100644 index 000000000..e5afbce85 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/scrawl.js @@ -0,0 +1,18 @@ +/** + * Created with JetBrains PhpStorm. + * User: luqiong + * Date: 12-11-13 + * Time: 下午2:13 + * To change this template use File | Settings | File Templates. + */ + +module( 'plugins.scrawl' ); +test( '检查高亮', function() { + var editor = te.obj[0]; + editor.focus(); + equal( editor.queryCommandState( 'scrawl' ), ( browser.ie && browser.version <= 8 ) ? -1:0, 'check scrawl state' ); +} ); + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/searchreplace.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/searchreplace.js new file mode 100644 index 000000000..871cdc836 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/searchreplace.js @@ -0,0 +1,122 @@ +module('plugins.searchreplace'); + +test('trace 3381:查找',function(){ + if(ua.browser.opera) + return; + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    hello啊

    '); + stop(); + setTimeout(function(){ + range.setStart(editor.body.firstChild,0).collapse(true).select(); + var num = editor.execCommand('searchreplace',{searchStr:'啊'}); + + ua.manualDeleteFillData(editor.body); + equal(editor.body.firstChild.innerHTML,'hello啊'); + + equal(editor.selection.getRange().collapsed,false,'检查选区:不闭合为找到'); + start(); + },20); +}); +// +///*trace 974,先替换再撤销再全部替换,则不会替换 +//* ie下会出现的bug*/ +test(' trace 3697全部替换',function(){ + //todo trace 3697 + if(ua.browser.opera) + return; + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    欢迎回来

    '); + range.setStart(editor.body.firstChild,0).collapse(true).select(); + editor.execCommand('searchreplace',{searchStr:'欢迎',replaceStr:'你好'}); + editor.undoManger.undo(); + editor.execCommand('searchreplace',{searchStr:'欢迎',replaceStr:'你好',all:true}); + ua.manualDeleteFillData(editor.body); + equal(editor.body.firstChild.innerHTML,'你好回来'); +}); + +///*trace 917*/ +///*trace 3288*/todo +//test('替换内容包含查找内容,全部替换',function(){ +// if(ua.browser.opera) +// return; +// var editor = te.obj[0]; +// var range = te.obj[1]; +// editor.setContent('

    hello回来

    '); +// range.setStart(editor.body.firstChild,0).collapse(true).select(); +// /*searchreplace文件里是一个闭包,闭包中有一个全局变量currentRange,在上一次用例执行结束后仍然会保存这个值,导致下一次用例受影响*/ +// editor.execCommand('searchreplace',{searchStr:'hello',replaceStr:'hello啊',all:true}); +// ua.manualDeleteFillData(editor.body); +// equal(editor.body.firstChild.innerHTML,'hello啊回来'); +//}); + +/*trace 973*/ +test(' trace 3697替换内容包含查找内容',function(){ + if(ua.browser.opera) + return; + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    欢迎回来

    '); + range.setStart(editor.body.firstChild,0).collapse(1).select(); + editor.execCommand('searchreplace',{searchStr:'欢迎',replaceStr:'欢迎啊'}); + ua.manualDeleteFillData(editor.body); + equal(editor.body.firstChild.innerHTML,'欢迎啊回来'); + editor.undoManger.undo(); + ua.manualDeleteFillData(editor.body); + equal(editor.body.firstChild.innerHTML,'欢迎回来'); +}); +// +///*trace 1286*/todo +//test('连续2次全部替换',function(){ +// if(ua.browser.opera) +// return; +// var editor = te.obj[0]; +// editor.setContent('

    欢迎回来

    '); +// editor.execCommand('searchreplace',{searchStr:'欢迎',replaceStr:'欢迎啊',all:true}); +// ua.manualDeleteFillData(editor.body); +// equal(editor.body.firstChild.innerHTML,'欢迎啊回来'); +// editor.execCommand('searchreplace',{searchStr:'欢迎',replaceStr:'欢迎啊',all:true}); +// ua.manualDeleteFillData(editor.body); +// equal(editor.body.firstChild.innerHTML,'欢迎啊啊回来'); +//}); +// +test('替换内容为空',function(){ + if(ua.browser.opera) + return; + var editor = te.obj[0]; + editor.setContent('

    欢迎回来

    '); + stop(); + setTimeout(function(){ + editor.focus(); + editor.execCommand('searchreplace',{searchStr:'欢迎',replaceStr:''}); + ua.manualDeleteFillData(editor.body); + equal(editor.body.firstChild.innerHTML,'回来'); + start(); + },50); +}); +// +test('全部替换内容为空',function(){ + if(ua.browser.opera) + return; + var editor = te.obj[0]; + editor.setContent('

    欢迎回来 欢迎啊

    '); + editor.execCommand('searchreplace',{searchStr:'欢迎',replaceStr:'',all:true}); + ua.manualDeleteFillData(editor.body); + equal(editor.body.firstChild.innerHTML,'回来 啊'); +}); + +//test('查找替换支持正则',function(){ +// if(ua.browser.opera) +// return; +// var editor = te.obj[0]; +// editor.setContent('

    sd2323fasdfasd3434f

    '); +// //因为是字符表示的正则要做转换 +// editor.execCommand('searchreplace',{searchStr:'/\\d+/',replaceStr:'',all:true}); +// ua.manualDeleteFillData(editor.body); +// equal(editor.body.firstChild.innerHTML,'sdfasdfasdf'); +// editor.setContent('

    sd2323fasdfasd3434f

    首都发生地2323方

    '); +// editor.execCommand('searchreplace',{searchStr:'/\\d+/',replaceStr:'',all:true}); +// ua.manualDeleteFillData(editor.body); +// equal(editor.body.innerHTML.toLowerCase().replace(/>\s+<'),'

    sdfasdfasdf

    首都发生地方

    '); +//}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/section.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/section.js new file mode 100644 index 000000000..d444f7dcb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/section.js @@ -0,0 +1,65 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-9-28 + * Time: 下午1:34 + * To change this template use File | Settings | File Templates. + */ +module('plugins.section'); + +test('getsections命令',function(){ + var editor = te.obj[0]; + var html = '

    一级标题1

    段落a

    二级标题2

    段落

    二级标题3

    段落

    三级标题4

    段落

    一级标题5

    段落

    '; + editor.setContent(html); + var sectionTree = editor.execCommand('getsections'); + + equal(sectionTree.children.length, 2, '内容里有两个一级标题'); + equal(sectionTree.children[1].title, '一级标题5', '验证章节内容'); + same(sectionTree.children[1].startAddress, [8], '验证章节开始位置'); + same(sectionTree.children[1].endAddress, [9], '验证章节结束位置'); +}); + +test('deletesection命令',function(){ + var editor = te.obj[0]; + var html = '

    一级标题1

    段落a

    二级标题2

    段落

    二级标题3

    段落

    三级标题4

    段落

    一级标题5

    段落b

    '; + + editor.setContent(html); + var sectionTree = editor.execCommand('getsections'); + editor.execCommand('deleteSection', sectionTree.children[1]); + equal(sectionTree.children[1].parentNode, null, '验证章节标题是否已删除'); + notEqual(editor.body.children[0].innerHTML, '段落a', '不传入keepChild参数时,验证章节内容是否已删除'); + + editor.setContent(html); + sectionTree = editor.execCommand('getsections'); + editor.execCommand('deleteSection', sectionTree.children[0], true); + equal(editor.body.children[0].innerHTML, '段落a', '传入keepChild参数为true时,验证章节内容是否已保留'); +}); + +test('movesection命令',function(){ + var editor = te.obj[0]; + var html = '

    一级标题1

    段落a

    二级标题2

    段落

    二级标题3

    段落

    三级标题4

    段落

    一级标题5

    段落b

    '; + + editor.setContent(html); + var sectionTree = editor.execCommand('getsections'); + editor.execCommand('movesection', sectionTree.children[1], sectionTree.children[0]); + equal(editor.body.children[0].innerHTML, '一级标题5', ' 移动章节移动到目标章节之前,验证章节是否移动正确'); + equal(editor.body.children[1].innerHTML, '段落b', ' 验证移动章节移动到目标章节之前,验证章节内容是否移动正确'); + + editor.setContent(html); + sectionTree = editor.execCommand('getsections'); + editor.execCommand('movesection', sectionTree.children[0], sectionTree.children[1], true); + var len = editor.body.children.length; + equal(editor.body.children[len-2].innerHTML, '一级标题1', ' 移动章节移动到目标章节之前,验证章节是否移动正确'); + equal(editor.body.children[len-1].innerHTML, '段落a', ' 验证移动章节移动到目标章节之前,验证章节内容是否移动正确'); +}); + +test('selectsection命令',function(){ + var editor = te.obj[0]; + var html = '

    一级标题1

    段落a

    二级标题2

    段落

    二级标题3

    段落

    三级标题4

    段落

    一级标题5

    段落b

    '; + + editor.setContent(html); + var sectionTree = editor.execCommand('getsections'); + editor.execCommand('selectsection', sectionTree.children[1]); + var range = editor.selection.getRange(); + ua.checkSameHtml($('
    ').append(range.cloneContents()).html(), '

    一级标题5

    段落b

    ', '判断选区内容是否正确'); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/selectall.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/selectall.js new file mode 100644 index 000000000..406544356 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/selectall.js @@ -0,0 +1,76 @@ +module( "plugins.selectall" ); +test( 'normal', function () { + var editor = te.obj[0], db = editor.body; + editor.setContent( '

    xxxx

    ssss' ); + editor.focus(); + editor.execCommand( 'selectAll' ); + //equal( UE.plugins['selectall'].notNeedUndo, 1, "notNeedUndo==1" ); + editor.execCommand( "bold" ); + equal( ua.getChildHTML( db ), "

    xxxx

    ssss

    ", "after calling selectAll command" ); +} ); + +test( 'a part of the content is selected', function () { + var editor = te.obj[0], d = editor.document, range = te.obj[1], db = editor.body; + editor.setContent( '

    xxxx

    ssss' ); + range.selectNode( db.lastChild.firstChild ).select(); + editor.execCommand( "bold" ); + equal( ua.getChildHTML( db ), "

    xxxx

    ssss

    ", "before calling selectAll command" ); + editor.execCommand( 'selectAll' ); + //equal( UE.plugins['selectall'].notNeedUndo, 1, "notNeedUndo==1" ); + editor.execCommand( "bold" ); + equal( ua.getChildHTML( db ), "

    xxxx

    ssss

    ", "after calling selectAll command" ); +} ); + +test( 'trace1743 :content is null', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '


    ' ); + //TODO 现在必须先focus再selectall,trace1743 + editor.execCommand( 'selectAll' ); + equal( ua.getChildHTML( editor.body ), "


    ", "content is null" ); + //equal(UE.plugins['selectall'].notNeedUndo, 1, "notNeedUndo==1" ); + range.setStart( editor.body.firstChild, 0 ).collapse( 1 ).select(); + editor.execCommand( "bold" ); + ua.manualDeleteFillData( editor.body ); + equal( ua.getChildHTML( editor.body ), "


    ", "after calling command bold" ); +} ); + +test( 'ctrl+a', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '

    全选的文本1

    全选的文本2

    ' ); + range.selectNode( body.firstChild ).select(); + var p = body.firstChild; + ua.keydown(editor.body,{'keyCode':65,'ctrlKey':true}); + setTimeout( function() { + var range = editor.selection.getRange(); +// if ( ua.browser.gecko||ua.browser.ie>8 ) +// ua.checkResult( range, body, body, 0, 2, false, '查看全选后的range' ); +// else + if(ua.browser.gecko||ua.browser.webkit){ + ua.checkResult( range, body, body, 0, 2, false, '查看全选后的range' ); + }else{ + ua.checkResult( range, body.firstChild.firstChild, body.lastChild.firstChild, 0, 6, false, '查看全选后的range' ); + } + start(); + }, 150 ); + stop(); +} ); +test('contextmenu 右键全选', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + stop(); + editor.setContent('asdfg'); + ua.contextmenu(editor.body); + var lang = editor.getLang("contextMenu"); + var menuBody = document.getElementsByClassName("edui-menu-body")[0]; + equal(editor.selection.getRange().collapsed, true, '检查选区--闭合'); + ua.click(menuBody.childNodes[0]); + setTimeout(function () { + equal(editor.selection.getRange().collapsed, false, '检查选区--非闭合'); + document.getElementById('edui_fixedlayer').parentNode.removeChild(document.getElementById('edui_fixedlayer')); + te.dom.push(editor.container); + start(); + }, 50); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/serverparam.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/serverparam.js new file mode 100644 index 000000000..845e0ae76 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/serverparam.js @@ -0,0 +1,17 @@ +module( 'plugins.serverparam' ); + +test( '检查是否能正常设置参数', function () { + var editor = te.obj[0]; + + editor.execCommand('serverparam', {"a": 1, "b": 2}); + same( editor.queryCommandValue('serverparam'), {"a": 1, "b": 2}, '传入对象设置参数'); + + editor.execCommand('serverparam', "c", 3); + same( editor.queryCommandValue('serverparam'), {"a": 1, "b": 2, "c": 3}, '传入键和值设置参数'); + + editor.execCommand('serverparam', "c"); + same( editor.queryCommandValue('serverparam'), {"a": 1, "b": 2}, '传入键删除参数'); + + editor.execCommand('serverparam'); + same( editor.queryCommandValue('serverparam'), {}, '不传参数,清空参数表'); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/shortcutkeys.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/shortcutkeys.js new file mode 100644 index 000000000..298605d52 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/shortcutkeys.js @@ -0,0 +1,139 @@ +module( 'plugins.shortcutkeys' ); +//键盘操作取不到range,定不到位,尤其ie里ctrl+b把收藏夹打开了。。。 + +test( 'ctrl+i', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; +// setTimeout( function() { + editor.setContent( '

    没有加粗的文本

    ' ); + range.selectNode( body.firstChild ).select(); + var p = body.firstChild; + editor.focus(); + setTimeout( function() { +// te.presskey( 'ctrl', 'i' ); + ua.keydown(editor.body,{'keyCode':73,'ctrlKey':true}); + editor.focus(); + setTimeout( function() { + equal( ua.getChildHTML( p ), '没有加粗的文本' ); + start(); + }, 150 ); + }, 100 ); + +// }, 100 ); + stop(); +} ); +// +test( 'ctrl+u', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + stop(); + + editor.setContent( '

    没有加粗的文本

    ' ); + setTimeout( function() { + range.selectNode( body.firstChild ).select(); + var p = body.firstChild; + + editor.focus(); +// setTimeout( function() { +// editor.focus(); + setTimeout( function() { + var html = '没有加粗的文本'; + ua.checkHTMLSameStyle( html, editor.document, body.firstChild, '文本被添加了下划线' ); + start(); + }, 150 ); +// }, 100 ); +// te.presskey( 'ctrl', 'u' ); + ua.keydown(editor.body,{'keyCode':85,'ctrlKey':true}); + }, 150 ); +} ); +// +test( 'ctrl+z/y', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; +// setTimeout( function() { + editor.setContent( '

    没有加粗的文本

    ' ); + range.selectNode( body.firstChild ).select(); + var p = body.firstChild; + + editor.focus(); + setTimeout( function() { +// te.presskey( 'ctrl', 'b' ); +// editor.focus(); + ua.keydown(editor.body,{'keyCode':66,'ctrlKey':true}); + setTimeout( function() { + equal( ua.getChildHTML( p ), '没有加粗的文本' ); +// editor.focus(); +// te.presskey( 'ctrl', 'z' ); + ua.keydown(editor.body,{'keyCode':90,'ctrlKey':true}); +// editor.focus(); + setTimeout( function() { + editor.focus(); + equal( ua.getChildHTML( body.firstChild ), '没有加粗的文本' ); +// setTimeout( function() { +// te.presskey( 'ctrl', 'y' ); + ua.keydown(editor.body,{'keyCode':89,'ctrlKey':true}); + editor.focus(); + setTimeout( function() { +// editor.focus(); + equal( ua.getChildHTML( body.firstChild ), '没有加粗的文本' ); + start(); + }, 100 ); +// }, 100 ); + }, 100 ); + }, 150 ); + }, 100 ); + +// }, 150 ); + stop(); +} ); +// +test( 'ctrl+a', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; +// setTimeout( function() { + editor.setContent( '

    全选的文本1

    全选的文本2

    ' ); + range.selectNode( body.firstChild ).select(); + var p = body.firstChild; + ua.keydown(editor.body,{'keyCode':65,'ctrlKey':true}); +// setTimeout( function() { +// editor.focus(); +// te.presskey( 'ctrl', 'a' ); +// editor.focus(); + setTimeout( function() { + var range = editor.selection.getRange(); + if ( ua.browser.gecko ) + ua.checkResult( range, body, body, 0, 2, false, '查看全选后的range' ); + else + ua.checkResult( range, body.firstChild.firstChild, body.lastChild.firstChild, 0, 6, false, '查看全选后的range' ); + start(); + }, 150 ); +// }, 100 ); +// }, 100 ); + + stop(); +} ); +// +test( 'ctrl+b', function() { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; +// setTimeout( function() { + editor.setContent( '

    没有加粗的文本

    ' ); + range.selectNode( body.firstChild ).select(); + editor.focus(); + setTimeout( function() { + ua.keydown(editor.body,{'keyCode':66,'ctrlKey':true}); +// te.presskey( 'ctrl', 'b' ); +// editor.focus(); + setTimeout( function() { + equal( ua.getChildHTML( body.firstChild ), '没有加粗的文本' ); + start(); + }, 150 ); + }, 150 ); +// } ,50); + stop(); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/shortcutmenu.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/shortcutmenu.js new file mode 100644 index 000000000..eeedfad2e --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/shortcutmenu.js @@ -0,0 +1,86 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 13-6-13 + * Time: 下午12:38 + * To change this template use File | Settings | File Templates. + */ +module( 'plugins.contextmenu' ); + +test( '基本的shortcutmenu', function() { +//设置菜单内容\ + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor("ue", { shortcutMenu: ["fontfamily", "fontsize", "bold", "italic", "underline", "forecolor", "backcolor", "insertorderedlist", "insertunorderedlist"]}); + stop(); + editor.ready(function () { + ua.contextmenu(editor.body); + setTimeout(function () { + var menu = document.getElementsByClassName("edui-shortcutmenu")[0]; + equal(!!menu, true, '右键检查菜单是否存在'); + + ok(menu.style.display == "" || menu.style.display == "block", '右键检查菜单是否显示'); + + ua.mousedown(editor.body.firstChild); + + equal(menu.style.display, "none", '鼠标按下检查菜单是否隐藏'); + + UE.delEditor('ue'); + + te.dom.push(document.getElementById('ue')); + te.dom.push(document.getElementById('edui_fixedlayer')); + start() + + }, 100); + }); +}); +test( '键盘操作,隐藏shortcutmenu', function() { +//设置菜单内容\ + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor("ue" ,{ shortcutMenu: ["fontfamily", "fontsize", "bold", "italic", "underline", "forecolor", "backcolor", "insertorderedlist", "insertunorderedlist"]}); + stop(); + editor.ready(function () { + ua.contextmenu(editor.body); + setTimeout(function(){ + var menu=document.getElementsByClassName("edui-shortcutmenu")[0]; + equal(!!menu,true,'右键检查菜单是否存在'); + ok(menu.style.display==""||menu.style.display=="block",'右键检查菜单是否显示'); + ua.keydown(editor.body.firstChild); + equal(menu.style.display,"none",'键盘按下检查菜单是否隐藏'); + UE.delEditor('ue'); + te.dom.push(document.getElementById('ue')); + te.dom.push(document.getElementById('edui_fixedlayer')); + start() + },100); + }); +} ); +test( '框选内容', function() { +//设置菜单内容\ + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor("ue" ,{ shortcutMenu: ["fontfamily", "fontsize", "bold", "italic", "underline", "forecolor", "backcolor", "insertorderedlist", "insertunorderedlist"]}); + stop(); + editor.ready(function () { + editor.setContent('

    hello

    '); + var range = new baidu.editor.dom.Range(editor.document); + range.setStart(editor.body.firstChild.firstChild,0).setEnd(editor.body.firstChild.firstChild,2).select(); + var sc =editor.selection.getRange().startContainer; + var ec =editor.selection.getRange().endContainer; + var so =editor.selection.getRange().startOffset; + var eo =editor.selection.getRange().endOffset; + var collapsed =editor.selection.getRange().collapsed; + ua.contextmenu(editor.body); + setTimeout(function(){ + var menu=document.getElementsByClassName("edui-shortcutmenu")[0]; + equal(!!menu,true,'右键检查菜单是否存在'); + ok(menu.style.display==""||menu.style.display=="block",'右键检查菜单是否显示'); + ua.checkResult(editor.selection.getRange(), sc, ec, so, eo, collapsed,'检查range不变'); + ua.keydown(editor.body.firstChild); + UE.delEditor('ue'); + te.dom.push(document.getElementById('ue')); + te.dom.push(document.getElementById('edui_fixedlayer')); + start() + },100); + }); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/snapscreen.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/snapscreen.js new file mode 100644 index 000000000..d8e934691 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/snapscreen.js @@ -0,0 +1,41 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-9-17 + * Time: 下午2:38 + * To change this template use File | Settings | File Templates. + */ +module('plugins.snapscreen'); +test('检查高亮', function () { + var editor = te.obj[0]; + editor.focus(); + equal(editor.queryCommandState('snapscreen'), 0, 'check snapscreen state'); +}); +test('snapscreen', function () { + var div = document.body.appendChild(document.createElement('script')); + div.id = 'ue'; + var editor = UE.getEditor('ue'); + stop(); + editor.ready(function () { + setTimeout(function () { + editor.execCommand('snapscreen'); + editor.container.removeChild(editor.container.lastChild); + setTimeout(function () { + ok($('.edui-dialog .edui-for-snapscreen')[0] != null, ''); + $EDITORUI[$('.edui-dialog .edui-for-snapscreen')[0].parentNode.id].close(); + setTimeout(function () { + + UE.delEditor('ue'); + te.dom.push(document.getElementById('ue')); + start(); + }, 1000); + }, 300); + + + }, 100); + + + } + + ); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/source.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/source.js new file mode 100644 index 000000000..27df7a804 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/source.js @@ -0,0 +1,381 @@ +module('plugins.source'); +//test('初始化进入源码模式',function(){ +// if(ua.browser.ie>0 && ua.browser.ie<8) +// return 0; +// var div = document.createElement('div'); +// document.body.appendChild(div); +// div.id = 'e'; +// var editor = UE.getEditor('e');//,{sourceEditorFirst:true} +// stop(); +//// editor.ready(function(){ +//// setTimeout(function(){ +////// equal(editor.queryCommandState('source'),1,'源码高亮'); +//// equal(editor.queryCommandState('bold'),-1,'加粗灰色'); +//////// start(); +//// },100); +//// }); +//}); +test('chrome删除后切换源码再切换回来,光标没了', function () { + //opera 取不到range值 + if (ua.browser.opera) return 0; + var editor = te.obj[0]; + var div = te.dom[0]; + editor.render(div); + editor.setContent('hello'); + var range = editor.selection.getRange(); + range.selectNode(editor.body.firstChild).select(); + editor.execCommand('cleardoc'); + stop(); + expect(2); + //source 包含超时操作,ie下必须有同步操作,否则会报错 + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + start(); + }, 20); + }, 20); + range = editor.selection.getRange(); + equal(range.startContainer.nodeType, 1, '光标定位在p里'); + equal(range.startContainer.tagName.toLowerCase(), 'p', 'startContainer为p'); + te.dom.push(div); +}); +//TODO 1.2.6 +/*trace 986*/ +//test( '切换源码,视频地址被添加了网站前缀', function () { +// if ( !ua.browser.ie ) { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// editor.setContent( '


    ' ); +// setTimeout(function(){ +// range.setStart( editor.body.firstChild, 0 ).collapse( 1 ).select(); +// /*涉及到video的一些特殊处理,因此直接设置编辑器的html不是很可行,所以这里用了video这个插件*/ +// editor.execCommand( 'insertvideo', {url:'www.baidu.com'} ); +// setTimeout( function () { +// editor.execCommand( 'source' ); +// range.setStart( editor.body.firstChild, 0 ).collapse( 1 ).select(); +// setTimeout( function () { +// editor.execCommand( 'source' ); +// start(); +// }, 50 ); +// }, 50 ); +// +// var img = editor.document.getElementsByTagName( 'img' )[0]; +// equal( $( img ).attr( '_url' ), 'www.baidu.com', '检查超链接前是否添加了网站的路径' ); +// },50); +// stop(); +// } +// else +// ok( true, 'ie里加了视频节点embed,在节点embed后加bookmark会出错' ); +//} ); + +//trace 852 +test('切换源码,源码中多处空行', function () { + var editor = te.obj[0]; + editor.setContent('

    hellobaidu

    '); + stop(); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + var html = editor.getContent(); + equal(html, '

    hellobaidu

    '); + start(); + }, 100); + }, 100); + }, 100); + + // var html = '

    \nhello\n\tbaidu\n\n

    '; + //无奈的验证,有不可见字符 + //多余不可见字符的的bug已经修改了,现在用例字符串长度:53 + + // ok(html.length>=58&&html.length<=60,'切换源码不会多空行'); +}); + +/*trace 710*/ +test('设置源码内容没有p标签,切换源码后会自动添加', function () { + var editor = te.obj[0]; + editor.setContent('helloworld你好啊大家好,你在干嘛呢。谢谢,不用谢~~%199

    hello

    '); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + var childs = editor.body.childNodes; + ok(childs.length, 3, '3个p'); + for (var index = 0; index < 3; index++) { + equal(childs[0].tagName.toLowerCase(), 'p', '第' + index + '个孩子为p'); + } + start(); + }, 100); + }, 100); + }, 100); + }, 100); + stop(); +}); + +test('切换源码去掉空的span', function () { + var editor = te.obj[0]; + editor.setContent('

    切换源码去掉空的span

    '); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + start(); + }, 100); + }, 100); + stop(); + equal(editor.getContent(), '

    切换源码去掉空的span

    '); +}); + +test('b,i标签,切换源码后自动转换成strong和em', function () { + var editor = te.obj[0]; + editor.setContent('

    加粗的内容斜体的内容加粗且斜体

    '); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + start(); + }, 100); + }, 100); + stop(); + equal(editor.getContent(), '

    加粗的内容斜体的内容加粗且斜体

    '); +}); + +test(' trace 3739 trace 1734 range的更新/特殊符号的转换', function () { + var editor = te.obj[0]; + editor.setContent('

    "<>

    '); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + equal(editor.getContent(), '

    "<>

    '); + editor.setContent("

    '

    "); +// var range = te.obj[1]; +// range.setStart(editor.body.firstChild,0).collapse(1).select(); + setTimeout(function () { +// var label = ua.browser.gecko ? 'html' : 'body'; +// var label = 'html'; + ua.manualDeleteFillData(editor.body); + var sc = (ua.browser.ie==11)?editor.selection.getRange().startContainer.parentNode.tagName.toLowerCase():editor.selection.getRange().startContainer.parentNode.parentNode.tagName.toLowerCase(); + equal(sc, 'html', 'range的更新'); + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + equal(editor.getContent(), "

    '

    "); + start(); + }, 100); + }, 100); + }, 100); + }, 100); + stop(); +}); + +/*trace 1234 */ +test('默认插入的占位符', function () { + var editor = te.obj[0]; + editor.setContent(''); + equal(editor.getContent(), ''); +}); + +test('插入分页符,源码中显示:_baidu_page_break_tag_', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('


    '); + setTimeout(function () { + range.setStart(editor.body.firstChild, 0).collapse(1).select(); + editor.execCommand('pagebreak'); + ua.manualDeleteFillData(editor.body); + var pagebreak = editor.body.getElementsByTagName('hr')[0]; + + if (typeof pagebreak.attributes['class'] == "undefined") { + equal(pagebreak.getAttribute('class'), 'pagebreak', 'pagebreak'); + } + else {//适用于ie6,7 + equal(pagebreak.attributes['class'].nodeValue, 'pagebreak', 'pagebreak'); + } + ua.manualDeleteFillData(editor.body); +// var br = baidu.editor.browser.ie ? ' ' : '
    '; + ok(editor.getContent().indexOf('_ueditor_page_break_tag_') >= 0, 'pagebreak被解析'); +// equal( editor.getContent(), '

    ' + br + '

    _baidu_page_break_tag_

    ' + br + '

    ' ); + start(); + }, 200); + stop(); +}); +//TODO 1.2.6 +//test( 'trace 1977 1949 插入代码,源码中对应的标签是pre', function () { +// var div = document.body.appendChild( document.createElement( 'div' ) ); +// $( div ).css( 'width', '500px' ).css( 'height', '500px' ).css( 'border', '1px solid #ccc' ); +// var editor = te.obj[2]; +// editor.render(div); +// var range = new baidu.editor.dom.Range( editor.document ); +// var body = editor.body; +// stop(); +// setTimeout(function(){ +// editor.setContent( '


    ' ); +// range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); +// editor.execCommand( 'highlightcode', '', 'html' ); +// ua.manualDeleteFillData( editor.body ); +// +// var td_gutter = body.getElementsByTagName( 'td' )[0]; +// var td_code = body.getElementsByTagName( 'td' )[1]; +// equal( body.getElementsByTagName( 'td' ).length, 2, '显示代码的table分两列' ); +// if(td_gutter!=''){ +// if ( typeof td_gutter.attributes['class'] == "undefined" ) { +// equal( td_gutter.getAttribute( 'class' ), 'gutter', '第一列class=gutter' ); +// equal( td_code.getAttribute( 'class' ), 'code', '第一列class=code' ); +// } +// else {//适用于ie6,7 +// equal( td_gutter.attributes['class'].nodeValue, 'gutter', '第一列class=gutter' ); +// equal( td_code.attributes['class'].nodeValue, 'code', '第一列class=code' ); +// } +// equal( editor.getContent().substring( 0, 119 ), '
    <a href=\"http://net.tutsplus.com\" class=\"logo\">Nettuts+</a> 
    ' ); +// //highlightcode空格问题 +//// equal( editor.getContent().substring( 0, 116 ), '
    <a href=\"http://net.tutsplus.com\" class=\"logo\">Nettuts+</a>
    ' ); +// te.dom.push( div ); +// } +// start(); +// },50); +//} ); + +test('不以http://开头的超链接绝对路径网址', function () { + if (ua.browser.ie == 9)return 0;//TODO 1.2.6 + var editor = te.obj[0]; + editor.setContent('

    绝对路径网址

    '); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + equal(editor.getContent(), '

    绝对路径网址

    '); + start(); + }, 100); + }, 100); + stop(); +}); + +test('trace 1727:插入超链接后再插入空格,空格不能被删除', function () { + var editor = te.obj[0]; + editor.setContent('

    绝对路径网址 ddd

    '); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + equal(editor.body.innerHTML.toLowerCase(), '

    绝对路径网址  ddd

    ', '查看空格是否被删除'); + start(); + }, 100); + }, 100); + stop(); +}); +//TODO 1.2.6 空style未删除 +//test( '关于空格的问题', function () { +// var editor = te.obj[0]; +// var html = '
    1. dd jj
    2. ll kdkd baidu
    '; +// editor.setContent( html ); +// setTimeout(function(){ +// editor.execCommand( 'source' ); +// setTimeout( function () { +// editor.execCommand( 'source' ); +// setTimeout( function () { +// ua.manualDeleteFillData( editor.body ); +// equal( editor.body.innerHTML.toLowerCase().replace(/[\r\n\t]/g,''), '
    1. dd jj

    2. ll kdkd baidu 

    ' ); +// start(); +// }, 150 ); +// }, 100 ); +// },20); +// stop(); +//} ); +//TODO 1.2.6 +//test('初始化进入源码模式',function(){ +// if(ua.browser.ie>0 && ua.browser.ie<8) +// return 0; +// var div = document.createElement('div'); +// document.body.appendChild(div); +// var editor = UE.getEditor(div);//,{sourceEditorFirst:true} +// stop(); +// editor.ready(function(){ +// setTimeout(function(){ +//// equal(editor.queryCommandState('source'),1,'源码高亮'); +// equal(editor.queryCommandState('bold'),-1,'加粗灰色'); +////// start(); +// },100); +// }); +//}); + +test('在font,b,i标签中输入,会自动转换标签 ', function () { +// if(!ua.browser.gecko){ + var editor = te.obj[0]; + editor.body.innerHTML = '

    x

    '; + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + equal(editor.body.firstChild.firstChild.tagName.toLowerCase(), 'span', 'font转换成span'); + if (ua.browser.gecko || ua.browser.ie) + equal($(editor.body.firstChild.firstChild).css('font-size'), '16px', '检查style'); + else + equal($(editor.body.firstChild.firstChild).css('font-size'), '16px', '检查style'); + var EMstyle = $(editor.body.firstChild.firstChild).css('color'); + ok(EMstyle == 'rgb(255, 0, 0)' || EMstyle == 'red' || EMstyle == '#ff0000', '检查style'); + equal(ua.getChildHTML(editor.body.firstChild.firstChild), 'x', 'b转成strong,i转成em '); + start(); + }, 20); + }, 20); + stop(); +// } +}); + +test('trace 3334:img和a之间不会产生多余空格', function () { + var editor = te.obj[0]; + editor.setContent('

    http://www.baidu.com

    '); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + ua.manualDeleteFillData(editor.body); + var html = '

    http://www.baidu.com

    '; + ua.checkSameHtml(editor.body.innerHTML.toLowerCase(), html, '查看img和a之间是否会产生多余空格'); + start(); + }, 20); + }, 20); + }, 20); + stop(); +}); + +test('trace 3334:table中td不会产生多余空格', function () { + if(ua.browser.ie)return ;//todo 1.3.0 + var editor = te.obj[0]; + editor.execCommand('inserttable'); + var br = ua.browser.ie ? '' : '
    '; + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + ua.manualDeleteFillData(editor.body); + equal(editor.body.getElementsByTagName('table').length, 1, '有1个table'); + equal(editor.body.getElementsByTagName('tr').length, 5, '有5个tr'); + equal(editor.body.getElementsByTagName('td').length, 25, '有25个td'); + equal(editor.body.getElementsByTagName('td')[12].innerHTML, br, '不会产生多余空格'); + start(); + }, 20); + }, 20); + stop(); +}); + +test('trace 3349:带颜色的span切到源码再切回,不会丢失span', function () { + var editor = te.obj[0]; + editor.setContent('


    '); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + ua.checkSameHtml(editor.body.innerHTML, '


    '); + start(); + }, 20); + }, 20); + stop(); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/table.action.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/table.action.js new file mode 100644 index 000000000..55ad46fde --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/table.action.js @@ -0,0 +1,1007 @@ +/** + * Created with JetBrains PhpStorm. + * User: taoqili + * Date: 13-2-25 + * Time: 下午4:40 + * To change this template use File | Settings | File Templates. + */ + +//test('', function () { +// stop() +//}); +test('框选', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + editor.setContent('

    '); + setTimeout(function () { + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + var tds = editor.body.getElementsByTagName('td'); + ua.mousedown(tds[0]); + ua.mouseover(tds[4]); + ua.mouseup(tds[4]); + setTimeout(function () { + var selectedTds = editor.getUETable(editor.body.firstChild).selectedTds; + var tds = editor.body.getElementsByTagName('td'); + equal(selectedTds.length, 4, '框选'); + if ( ua.browser.ie >8 && ua.browser.ie<11) + ua.checkResult(editor.selection.getRange(), tds[0].firstChild, tds[0].firstChild, 1, 1, true, '检查选中的range') + else + ua.checkResult(editor.selection.getRange(), tds[0], tds[0], 0, 0, true, '检查选中的range'); + range.setStart(tds[4], 0).collapse(true).select(); + ua.mousedown(tds[4], {button: 2}); + setTimeout(function () { + var selectedTds = editor.getUETable(editor.body.firstChild).selectedTds; + var tds = editor.body.getElementsByTagName('td'); + equal(selectedTds.length, 4, '右键框选不变'); + if ( ua.browser.ie >8 && ua.browser.ie<11) + ua.checkResult(editor.selection.getRange(), tds[0].firstChild, tds[0].firstChild, 1, 1, true, '检查选中的range') + else + ua.checkResult(editor.selection.getRange(), tds[0], tds[0], 0, 0, true, '检查选中的range'); + start(); + }, 50); + }, 50); + }, 80); + stop(); +}); + +test('tableDragable-显示和消失', function () { + if (browser.ie && browser.version < 8) return; + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor('ue', {tableDragable: true}); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + editor.setContent('

    '); + setTimeout(function () { + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + var tds = editor.body.getElementsByTagName('td'); + ua.mousemove(editor.body.firstChild); + var pos = domUtils.getXY(editor.body.firstChild); + var select = ua.browser.webkit ? '-webkit-user-select: none;' : ua.browser.gecko ? '-moz-user-select: none;' : ua.browser.ie >8?'-ms-user-select: none':'';//-ms-user-select: none + var html = '
    '; + setTimeout(function () { + var button = editor.body.lastChild; + ua.checkSameHtml(button.outerHTML.replace('"', ''), html, 'DragButton显示'); + ua.mouseout(button); + ua.mousemove(editor.body); + setTimeout(function () { + equal(editor.body.getElementsByTagName('div').length, 0, '按钮没有了'); + UE.delEditor('ue'); + te.dom.push(document.getElementById('ue')); + te.dom.push(document.getElementById('edui_fixedlayer')); + start(); + }, 2100); + }, 20); + }, 50); + }); + stop(); +}); +test('tableDragable-单击', function () {//tableClicked + if (browser.ie && browser.version < 8) return; + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor('ue', {tableDragable: true}); + expect(1); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + editor.setContent('

    '); + setTimeout(function () { + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + var tds = editor.body.getElementsByTagName('td'); + ua.mousemove(editor.body.firstChild); + setTimeout(function () { + var button = editor.body.lastChild; + editor.addListener("tableClicked", function (type, table, buttonOn) { + same(table, editor.body.getElementsByTagName('table')[0], 'tableClicked事件,传入的参数正确'); + setTimeout(function () { + UE.delEditor('ue'); + te.dom.push(document.getElementById('ue')); + te.dom.push(document.getElementById('edui_fixedlayer')); + start(); + }, 500); + }); + ua.click(button); + }, 20); + }, 50); + }); + stop(); +}); +test('tableDragable-双击', function () {//tableClicked + if (browser.ie && browser.version < 8) return; + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor('ue', {tableDragable: true}); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + editor.setContent('

    '); + setTimeout(function () { + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + var tds = editor.body.getElementsByTagName('td'); + ua.mousemove(editor.body.firstChild); + setTimeout(function () { + var button = editor.body.lastChild; + ua.dblclick(button); + setTimeout(function () { + var selectedTds = editor.getUETable(editor.body.firstChild).selectedTds; + var tds = editor.body.getElementsByTagName('td'); + equal(selectedTds.length, 9, '全选'); + if (ua.browser.ie > 8 && ua.browser.ie<11) + ua.checkResult(editor.selection.getRange(), tds[0].firstChild, tds[0].firstChild, 1, 1, true, '检查选中的range'); + else + ua.checkResult(editor.selection.getRange(), tds[0], tds[0], 0, 0, true, '检查选中的range'); + setTimeout(function () { + UE.delEditor('ue'); + te.dom.push(document.getElementById('ue')); + te.dom.push(document.getElementById('edui_fixedlayer')); + start(); + }, 500); + }, 100); + }, 100); + }, 100); + }); + stop(); +}); +test('从外面粘贴表格', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + var html = {html: '
    hello1
    hello2

    hello2

    '}; + editor.fireEvent('beforepaste', html); + //**//*粘贴*//**//* + stop(); + setTimeout(function () { + var space = ua.browser.ie ? '' : '
    '; + var border = (ua.browser.ie && ua.browser.ie < 9) ? 'border-bottom-color: rgb(247,150,70); border-top-color: rgb(247,150,70); border-right-color: rgb(247,150,70); border-left-color: rgb(247,150,70)' : 'border-color: rgb(247, 150, 70)'; + var resultHtml = '
    hello1' + space + '
    hello2' + space + '

    hello2

    '; + ua.checkSameHtml(html.html.toLowerCase(), resultHtml.toLowerCase(), '粘贴的表格规范格式'); + start(); + }, 50); +}); +test('从外面粘贴表格到表格-表格中不能粘完整的表格', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent(''); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + //**//*插入表格*//**//* + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(true).select(); + var html = {html: '
    hello1
    hello2

    hello2

    '}; + editor.fireEvent('beforepaste', html); + //**//*粘贴*//**//* + stop(); + setTimeout(function () { + equal(html.html, '

    hello2

    ', '表格中不能粘完整的表格'); + start(); + }, 50); +}); +test(' trace 3729 从外面粘贴表格到表格-在caption中粘贴,只粘贴文本内容', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent(''); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + //**//*插入表格*//**//* + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('insertcaption'); + range.setStart(editor.body.getElementsByTagName('caption')[0], 0).collapse(true).select(); + var html = {html: '
    hello1
    '}; + editor.fireEvent('beforepaste', html); + //**//*粘贴*//**//* + stop(); + setTimeout(function () { + //todo ie9 使用 div[browser.ie ? 'innerText' : 'textContent'] 会多一个换行,用textContent没有 trace 3729 + equal(html.html, 'hello1', '在caption中粘贴,只粘贴文本内容'); + start(); + }, 50); +}); +test('getText,取表格内的文本', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('
    hello1
    hello2
    '); + stop(); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + range.setStart(trs[0].cells[0],0).collapse(true).select(); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[0]); + ut.setSelected(cellsRange); + setTimeout(function () { + ua.manualDeleteFillData(editor.body); + equal(editor.selection.getText(), 'hello1hello2'); + start(); + }, 50); + }, 50); +}); +test('在第一个单元格里最前面回车,且表格前面没有内容', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + + var trs = editor.body.firstChild.getElementsByTagName('tr'); + + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[0]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + ua.keydown(editor.body, {'keyCode': 13}); + stop(); + setTimeout(function () { + ua.manualDeleteFillData(editor.body); + equal(editor.body.firstChild.innerHTML, ua.browser.ie ? ' ' : '
    ', '表格前插入空行'); + equal(editor.body.firstChild.tagName.toLowerCase(), 'p', '表格前插入空行'); + equal(editor.body.childNodes[1].tagName.toLowerCase(), 'table', '表格在空行后面'); + start(); + }, 50); +}); +test('delete 事件', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + expect(4); + editor.addListener('saveScene', function () { + ok(true); + }); + var trs = editor.body.firstChild.getElementsByTagName('tr'); + trs[0].cells[0].innerHTML = 'hello'; + trs[1].cells[0].innerHTML = 'hello'; + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[0]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + ua.keydown(editor.body, {'keyCode': 46}); + stop(); + setTimeout(function () { + ua.manualDeleteFillData(editor.body); + trs = editor.body.firstChild.getElementsByTagName('tr'); + equal(trs[0].cells[0].innerHTML, ua.browser.ie ? '' : '
    ', '内容'); + equal(trs[1].cells[0].innerHTML, ua.browser.ie ? '' : '
    ', '内容'); + start(); + }, 20); +}); +//**//*trace 3047,3545*//**//* +test('trace 3047 ,3545 全屏插入表格', function () { + if (ua.browser.gecko)return;//TODO 1.2.6 + if (ua.browser.ie && ua.browser.ie < 9)return;//TODO 1.2.6 + var div = document.body.appendChild(document.createElement('div')); + $(div).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + var editor = te.obj[2]; + editor.render(div); + stop(); + editor.ready(function () { + editor.setContent('

    '); + editor.ui.setFullScreen(!editor.ui.isFullScreen()); + editor.execCommand('inserttable'); + var width1 = editor.body.getElementsByTagName('td')[0].width; + setTimeout(function () { + editor.ui.setFullScreen(!editor.ui.isFullScreen()); + setTimeout(function () { + var width2 = editor.body.getElementsByTagName('td')[0].width; + ok((width1 - width2) > 10, '页面宽度自适应'); + div.parentNode.removeChild(div); + start(); + }, 500); + }, 500); + }); +}); + +test('backspace事件:删除caption', function () { + if(ua.browser.ie&&ua.browser.ie>8)return ;//todo 1.3.0 + + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + stop(); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('insertcaption'); + ua.keydown(editor.body, {'keyCode': 8}); + setTimeout(function () { + equal(editor.body.getElementsByTagName('caption').length, 0, '删除caption'); + equal(editor.selection.getRange().collapsed, true, '检查光标'); + equal(editor.selection.getRange().startContainer, editor.body.getElementsByTagName('td')[0], '检查光标'); + start(); + }, 500); + }, 50); +}); + +test('backspace事件:deleterow', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + stop(); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[0].cells[2]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + ua.keydown(editor.body, {'keyCode': 8}); + setTimeout(function () { + equal(editor.body.getElementsByTagName('tr').length, 2, '删除整行'); + if(!ua.browser.ie||ua.browser.ie<9){//todo + equal(editor.selection.getRange().collapsed, true, '检查光标'); + equal(editor.selection.getRange().startContainer, editor.body.getElementsByTagName('td')[0], '检查光标'); + } + start(); + }, 100); + }, 50); +}); + +test('backspace事件:deletecol', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + stop(); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[2].cells[0]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + setTimeout(function () { + ua.keydown(trs[0].cells[0], {'keyCode': 8}); + setTimeout(function () { + equal(editor.body.getElementsByTagName('tr')[0].getElementsByTagName('td').length, 2, '删除整列'); + if(!ua.browser.ie||ua.browser.ie<9){//todo + equal(editor.selection.getRange().collapsed, true, '检查光标'); + equal(editor.selection.getRange().startContainer, editor.body.getElementsByTagName('td')[0], '检查光标'); + } + start(); + }, 100); + }, 50); + }, 100); +}); + +//test('backspace事件:delcells', function () { +// //TODO +//}); +test('表格名称中backspace键', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + stop(); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('insertcaption'); + range.setStart(editor.body.getElementsByTagName('caption')[0], 0).collapse(true).select(); + ua.keydown(editor.body, {'keyCode': 8}); + setTimeout(function () { + equal(editor.body.getElementsByTagName('caption').length, 0, '删除caption'); + equal(editor.body.getElementsByTagName('table').length, 1, '不会增加表格数量'); + equal(editor.body.getElementsByTagName('tr').length, 3, '不会增加表格行数量'); + equal(editor.body.getElementsByTagName('tr')[0].cells.length, 3, '不会增加表格列数量'); + if(!ua.browser.ie||ua.browser.ie<9){//todo + equal(editor.selection.getRange().collapsed, true, '检查光标'); + equal(editor.selection.getRange().startContainer, editor.body.getElementsByTagName('td')[0], '检查光标'); + } + start(); + }, 100); + }, 200); +}); +test('trace 3097 标题行中backspace键', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + var trs = editor.body.firstChild.getElementsByTagName('tr'); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('insertcaption'); + range.setStart(editor.body.getElementsByTagName('caption')[0], 0).collapse(true).select(); + var x = range.cloneRange(); + editor.execCommand('inserttitle'); + range.setStart(editor.body.getElementsByTagName('th')[0], 0).collapse(true).select(); + ua.keydown(editor.body, {'keyCode': 8}); + stop(); + setTimeout(function () { + editor = te.obj[0]; + equal(editor.body.getElementsByTagName('caption').length, 1, '不会删除caption'); + equal(editor.body.getElementsByTagName('th').length, 3, '不会误删除标题行'); + equal(editor.body.getElementsByTagName('table').length, 1, '不会增加表格数量'); + equal(editor.body.getElementsByTagName('tr').length, 4, '不会增加表格行数量'); + equal(editor.body.getElementsByTagName('tr')[0].cells.length, 3, '不会增加表格列数量'); + equal(editor.selection.getRange().collapsed, true, '检查光标'); + trs[0].cells[0].innerHTML = 'hello'; +// equal(editor.selection.getRange().startContainer, te.obj[0].body.getElementsByTagName('th')[0], '检查光标'); + equal(trs[0].cells[0].innerHTML,'hello', '检查光标'); + start(); + }, 50); +}); + +test('拖拽', function () { + if (ua.browser.ie && ua.browser.ie < 8) return; + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable'); + ua.manualDeleteFillData(editor.body); + var tds = te.obj[0].body.getElementsByTagName('td'); + var width1 = tds[1].width; + ua.mousemove(tds[1], {clientX: 199, clientY: 100}); + equal(editor.body.style.cursor, 'col-resize', '检查鼠标显示'); + ua.mousedown(tds[1], {clientX: 199, clientY: 100}); + setTimeout(function () { + ua.mousemove(tds[1], {clientX: 299, clientY: 100}); + ua.mouseup(tds[1], {clientX: 299, clientY: 100}); + var p = ua.getMousePosition; + setTimeout(function () { + var width2 = tds[1].width; + ok(width2 - width1 > 50, '拖拽后单元格宽度改变'); + start(); + }, 50); + }, 400); + stop(); +}); +test('拖拽_row-resize鼠标显示', function () { + if (ua.browser.ie && ua.browser.ie < 8) return; + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable'); + ua.manualDeleteFillData(editor.body); + var tds = te.obj[0].body.getElementsByTagName('td'); + var width1 = tds[1].width; + ua.mousemove(tds[4], {clientX: 450, clientY: 39}); + equal(editor.body.style.cursor, 'row-resize', 'row-resize鼠标显示'); + + expect(3); + setTimeout(function () { + editor.addListener("tablemouseout", function (type, table, buttonOn) { + same(table, editor.body.getElementsByTagName('table')[0], 'tablemouseout事件,传入的参数正确'); + }); + ua.mouseout(tds[1], {clientX: 299, clientY: 35}); + setTimeout(function () { + equal(editor.body.style.cursor, 'text', '焦点转移,row-resize不显示'); + start(); + }, 50); + }, 20); + stop(); +}); +test('拖拽-最右边的单元格', function () { + if (ua.browser.ie && ua.browser.ie < 8) return; + + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable'); + ua.manualDeleteFillData(editor.body); + var tds = te.obj[0].body.getElementsByTagName('td'); + var width1 = tds[4].width; + ua.mousemove(tds[4], {clientX: 492, clientY: 21}); + equal(editor.body.style.cursor, 'col-resize', '检查鼠标显示'); + + ua.mousedown(tds[4], {clientX: 492, clientY: 21}); + setTimeout(function () { + ua.mousemove(tds[4], {clientX: 481, clientY: 21}); + ua.mouseup(tds[4], {clientX: 481, clientY: 21}); + setTimeout(function () { + var width2 = te.obj[0].body.getElementsByTagName('td')[4].width; + ok(width1 != width2 , '拖拽后单元格宽度改变'); + start(); + }, 50); + }, 400); + stop(); +}); +test('拖拽-最下边的单元格', function () { +// if (ua.browser.ie ) return;//todo 1.3.0 + + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable'); + var tds = te.obj[0].body.getElementsByTagName('td'); + var height1 = tds[20].height; + ua.mousemove(tds[24], {clientX: 439, clientY: 512}); + ua.mousedown(tds[24], {clientX: 439, clientY: 512}); + equal(editor.body.style.cursor, 'row-resize', '检查鼠标显示'); + + setTimeout(function () { + ua.mousemove(tds[24], {clientX: 439, clientY: 562}); + ua.mouseup(tds[24], {clientX: 439, clientY: 562}); + setTimeout(function () { + var height2 = te.obj[0].body.getElementsByTagName('td')[20].height; + ok(height2 - height1 > 10, '拖拽后单元格宽度改变'); + start(); + }, 50); + }, 400); + stop(); +}); +test('trace 3022 表格名称中backspace、ctrl+z、enter', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); +// expect(9); + editor.addListener('saveScene', function () { + ok(true); + }); + stop(); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('insertcaption'); + ua.keydown(editor.body, {'keyCode': 8}); + setTimeout(function () { + + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + ua.keydown(editor.body, {'keyCode': 90, 'ctrlKey': true}); + setTimeout(function () { + ua.keydown(editor.body, {'keyCode': 13}); + equal(te.obj[0].body.getElementsByTagName('caption').length, 1, '撤销删除caption'); + equal(te.obj[0].body.getElementsByTagName('th').length, 0, '不会误插入标题行'); + equal(te.obj[0].body.getElementsByTagName('table').length, 1, '不会增加表格数量'); + equal(te.obj[0].body.getElementsByTagName('tr').length, 3, '不会增加表格行数量'); + equal(te.obj[0].body.getElementsByTagName('tr')[0].cells.length, 3, '不会增加表格列数量'); + equal(te.obj[0].selection.getRange().collapsed, true, '检查光标'); + + if(!ua.browser.gecko && !ua.browser.webkit)//todo 1.3.6 ff 回退后光标找不好 + equal(te.obj[0].selection.getRange().startContainer.parentNode, te.obj[0].body.getElementsByTagName('td')[0], '检查光标'); + start(); + }, 20); + }, 20); + }, 50); +}); + + + +/*trace 3067*/ +test('trace 3067 向右合并--tab键', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 2, numRows: 2}); + ua.manualDeleteFillData(editor.body); + + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('mergeright'); + range.setStart(tds[0], 0).collapse(true).select(); + range = editor.selection.getRange(); + var common = range.getCommonAncestor(true, true); + equal(common.colSpan, 2, 'tab键前光标位于合并后的单元格中'); + ua.keydown(editor.body, {'keyCode': 9}); + setTimeout(function () { + range = editor.selection.getRange(); + common = range.getCommonAncestor(true, true); + equal(common.colSpan, 1, 'tab键前光标跳到合并后单元格的下一个单元格中'); + start(); + }, 20); + stop(); +}); + +/*trace 3100*/ +test('trace 3100 表格名称中tab键', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + var trs = editor.body.firstChild.getElementsByTagName('tr'); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('insertcaption'); + range.setStart(editor.body.getElementsByTagName('caption')[0], 0).collapse(true).select(); + ua.keydown(editor.body, {'keyCode': 9}); + stop(); + setTimeout(function () { + editor = te.obj[0]; + equal(editor.body.getElementsByTagName('caption').length, 1, '不会删除caption'); + equal(editor.body.getElementsByTagName('th').length, 0, '不会误插入标题行'); + equal(editor.body.getElementsByTagName('table').length, 1, '不会增加表格数量'); + equal(editor.body.getElementsByTagName('tr').length, 3, '不会增加表格行数量'); + equal(editor.body.getElementsByTagName('tr')[0].cells.length, 3, '不会增加表格列数量'); + equal(editor.selection.getRange().collapsed, true, '检查光标'); + if (!ua.browser.ie) //ie8下会导致堆栈溢出,奇葩的bug,以后不溢出再检查ie8 + equal(editor.selection.getRange().startContainer, te.obj[0].body.getElementsByTagName('td')[0], '检查光标'); + start(); + }, 50); +}); + +/*trace 3059*/ +test('trace 3059 表格右浮动', function () { + if (ua.browser.ie)return;//TODO 1.2.6 + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable'); + ua.manualDeleteFillData(editor.body); + var tds = te.obj[0].body.getElementsByTagName('td'); + var oldWidth = tds[0].offsetWidth; + ua.mousemove(tds[0], {clientX: 105, clientY: 20}); + ua.mousedown(tds[0], {clientX: 105, clientY: 20}); + ua.mouseup(tds[0], {clientX: 105, clientY: 20}); + setTimeout(function () { + + ua.mousedown(tds[0], {clientX: 105, clientY: 20}); + ua.mouseup(tds[0], {clientX: 105, clientY: 20}); + + setTimeout(function () { + tds = editor.body.firstChild.getElementsByTagName('td'); + ok(tds[0].offsetWidth < oldWidth, '第一列宽度变小'); + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('tablealignment', 'right'); + var table = te.obj[0].body.getElementsByTagName('table')[0]; + equal(table.align, 'right', '表格右浮动'); + + start(); + + }, 500); + + }, 50); + + stop(); + +}); + +test('trace 3378:拖拽后tab,不影响表格样式', function () { + if (ua.browser.ie && ua.browser.ie < 8) return; + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable'); + ua.manualDeleteFillData(editor.body); + var tds = te.obj[0].body.getElementsByTagName('td'); + var width1 = tds[1].width; + ua.mousemove(tds[1], {clientX: 199, clientY: 100}); + ua.mousedown(tds[1], {clientX: 199, clientY: 100}); + setTimeout(function () { + ua.mousemove(tds[1], {clientX: 299, clientY: 100}); + ua.mouseup(tds[1], {clientX: 299, clientY: 100}); + var width2 = tds[1].width; + ok(width2 - width1 > 50, '拖拽后单元格宽度改变'); + range.setStart(tds[24], 0).collapse(true).select(); + ua.keydown(editor.body, {'keyCode': 9}); + setTimeout(function () { + equal(tds[1].width, width2, 'tab键不影响单元格宽度'); + start(); + }, 20); + }, 400); + stop(); +}); + +//超时,暂时注掉 +test('表格粘贴', function () { + var div = document.body.appendChild(document.createElement('div')); + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent(''); + editor.execCommand('inserttable'); + /*插入表格*/ + var tds = editor.body.getElementsByTagName('td'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(tds[0], tds[24]); + ut.setSelected(cellsRange); + /*确定选区*/ + range.setStart(tds[0], 0).collapse(true).select(); + /*定光标*/ + ua.keydown(editor.body, {'keyCode': 67, 'ctrlKey': true}); + /*ctrl+c*/ + var html = {html: editor.body.innerHTML}; + range.setStart(editor.body.lastChild, 0).collapse(true).select(); + equal(editor.body.getElementsByTagName('table').length, '1', '触发粘贴事件前有1个table'); + editor.fireEvent('beforepaste', html); + /*粘贴*/ + editor.fireEvent("afterpaste"); + equal(editor.body.getElementsByTagName('table').length, '2', '触发粘贴事件后有2个table'); +}); +// +//test('trace 3104 粘贴后合并单元格',function(){ +// var div = document.body.appendChild(document.createElement('div')); +// var editor = te.obj[0]; +// var range = te.obj[1]; +// editor.setContent(''); +// editor.execCommand('inserttable'); +// var trs = editor.body.getElementsByTagName('tr'); +// var ut = editor.getUETable(editor.body.firstChild); +// var cellsRange = ut.getCellsRange(trs[0].cells[0],trs[4].cells[0]); +// ut.setSelected(cellsRange); +// range.setStart( trs[0].cells[0], 0 ).collapse( true ).select(); +// ua.keydown(editor.body,{'keyCode':67,'ctrlKey':true}); +// ut.clearSelected(); +// var html ={html:editor.body.innerHTML}; +// range.setStart(editor.body.lastChild,0).collapse(true).select(); +// editor.fireEvent('beforepaste',html); +// editor.fireEvent("afterpaste"); +// var table = editor.body.getElementsByTagName('table'); +// equal(table.length,'2','触发粘贴事件后有2个table'); +// equal(table[1].firstChild.childNodes.length,'5','5行'); +// equal(table[1].firstChild.firstChild.childNodes.length,'1','1列'); +// +// var tds = editor.body.getElementsByTagName('td'); +// ut = editor.getUETable(editor.body.firstChild.nextSibling); +// cellsRange = ut.getCellsRange(tds[25],tds[29]); +// ut.setSelected(cellsRange); +// range.setStart(tds[25], 0 ).collapse( true ).select(); +// editor.execCommand('mergecells'); +// table = editor.body.getElementsByTagName('table'); +// equal(table[1].firstChild.childNodes.length,'1','1行'); +// equal(table[1].firstChild.firstChild.childNodes.length,'1','1列'); +//}); +// +test('trace 3105 在表格名称中粘贴', function () { + var div = document.body.appendChild(document.createElement('div')); + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent(''); + editor.execCommand('inserttable', {numCols: 2, numRows: 2}); + range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); + editor.execCommand('insertcaption'); + var str = ua.getChildHTML(editor.body); + var ut = editor.getUETable(editor.body.firstChild); + var tds = editor.body.getElementsByTagName('td'); + var cellsRange = ut.getCellsRange(tds[0], tds[1]); + ut.setSelected(cellsRange); + range.setStart(tds[0], 0).collapse(true).select(); + + ua.keydown(editor.body, {'keyCode': 67, 'ctrlKey': true}); + var html = {html: editor.body.innerHTML}; + range.setStart(editor.body.getElementsByTagName('caption')[0], 0).collapse(true).select(); + editor.fireEvent('beforepaste', html); + editor.fireEvent("afterpaste"); + ut.clearSelected(); + equal(editor.body.getElementsByTagName('table').length, '1', '触发粘贴事件后有1个table'); + equal(ua.getChildHTML(editor.body), str, '粘贴无效'); +}); + +test('trace 3106 粘贴标题行', function () { + var div = document.body.appendChild(document.createElement('div')); + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent(''); + editor.execCommand('inserttable'); + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('inserttitle'); + var ut = editor.getUETable(editor.body.firstChild); + var ths = editor.body.getElementsByTagName('th'); + var cellsRange = ut.getCellsRange(ths[0], ths[4]); + ut.setSelected(cellsRange); + range.setStart(ths[0], 0).collapse(true).select(); + + ua.keydown(editor.body, {'keyCode': 67, 'ctrlKey': true}); + var html = {html: editor.body.innerHTML}; + range.setStart(editor.body.lastChild, 0).collapse(true).select(); + editor.fireEvent('beforepaste', html); + editor.fireEvent("afterpaste"); + equal(editor.body.getElementsByTagName('table').length, '2', '触发粘贴事件后有2个table'); + if (ua.browser.gecko) { + //这个比较没意义 +// equal(editor.body.firstChild.firstChild.firstChild.firstChild.tagName.toLowerCase(),'td','不是th,是td'); + range.setStart(editor.body.firstChild.firstChild.firstChild.firstChild, 0).collapse(true).select(); + equal(editor.queryCommandState('inserttable'), -1, '应当不可以插入表格'); + equal(editor.queryCommandState('mergeright'), 0, '应当可以右合并单元格'); + } + else { +// equal(editor.body.firstChild.nextSibling.firstChild.firstChild.firstChild.tagName.toLowerCase(),'td','不是th,是td'); + range.setStart(editor.body.firstChild.nextSibling.firstChild.firstChild.firstChild, 0).collapse(true).select(); + equal(editor.queryCommandState('inserttable'), -1, '应当不可以插入表格'); + equal(editor.queryCommandState('mergeright'), 0, '应当可以右合并单元格'); + } +}); + +test('trace 3114 在单元格内粘贴行', function () { + var div = document.body.appendChild(document.createElement('div')); + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent(''); + editor.execCommand('inserttable'); + var tds = editor.body.getElementsByTagName('td'); + + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(tds[0], tds[9]); + ut.setSelected(cellsRange); + range.setStart(tds[0], 0).collapse(true).select(); + ua.keydown(editor.body, {'keyCode': 67, 'ctrlKey': true}); + var html = {html: editor.body.innerHTML}; + range.setStart(tds[0], 0).collapse(true).select(); + editor.fireEvent('beforepaste', html); + editor.fireEvent("afterpaste"); + equal(editor.body.getElementsByTagName('table').length, '1', '触发粘贴事件后有1个table'); + stop(); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + equal(editor.body.getElementsByTagName('tr').length, '7', '触发粘贴事件后有7个tr'); + start(); + }, 50); + }, 50); +}); +test('在单元格中粘贴_粘到最后', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent(''); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + /*插入表格*/ + var tds = editor.body.getElementsByTagName('td'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(tds[0], tds[4]); + ut.setSelected(cellsRange); + /*确定选区*/ + range.setStart(tds[0], 0).collapse(true).select(); + /*定光标*/ + ua.keydown(editor.body, {'keyCode': 67, 'ctrlKey': true}); + /*ctrl+c*/ + var html = {html: editor.body.innerHTML}; + range.setStart(tds[8], 0).collapse(true).select(); + equal(editor.body.getElementsByTagName('tr').length, 3, '触发粘贴事件前有3个tr'); + equal(editor.body.getElementsByTagName('td').length, 9, '触发粘贴事件前有9个td'); + editor.fireEvent('beforepaste', html); + /*粘贴*/ + editor.fireEvent("afterpaste"); + equal(editor.body.getElementsByTagName('tr').length, 4, '触发粘贴事件后有4个tr'); + equal(editor.body.getElementsByTagName('td').length, 16, '触发粘贴事件后有12个td'); +}); +test('在单元格中粘贴_整列', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent(''); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + /*插入表格*/ + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('inserttitle'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(tds[0], tds[6]); + ut.setSelected(cellsRange); + /*确定选区*/ + range.setStart(tds[0], 0).collapse(true).select(); + /*定光标*/ + ua.keydown(editor.body, {'keyCode': 67, 'ctrlKey': true}); + /*ctrl+c*/ + var html = {html: editor.body.innerHTML}; + range.setStart(tds[6], 0).collapse(true).select(); + equal(editor.body.getElementsByTagName('tr').length, 4, '触发粘贴事件前有4个tr'); + equal(editor.body.getElementsByTagName('th').length, 3, '触发粘贴事件前有3个th'); + equal(editor.body.getElementsByTagName('td').length, 9, '触发粘贴事件前有9个td'); + editor.fireEvent('beforepaste', html); + /*粘贴*/ + editor.fireEvent("afterpaste"); + equal(editor.body.getElementsByTagName('tr').length, 4, '触发粘贴事件后有4个tr'); + equal(editor.body.getElementsByTagName('th').length, 4, '触发粘贴事件前有4个th'); + equal(editor.body.getElementsByTagName('td').length, 12, '触发粘贴事件后有12个td'); +}); +test('点击一行的最左边,选中一行', function () { + if (ua.browser.ie && ua.browser.ie < 9)return;//todo click事件模拟有问题 + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent(''); + editor.execCommand('inserttable', {numCols: 2, numRows: 3}); + /*插入表格*/ + setTimeout(function () { + var tds = editor.body.getElementsByTagName('td'); + tds[0].innerHTML = 'hello1'; + tds[1].innerHTML = 'hello2'; + ua.mousemove(tds[0], {clientX: 8, clientY: 24}); + ua.click(tds[0], {clientX: 8, clientY: 24}); + setTimeout(function () { + var space = ua.browser.ie ? '' : ' '; + var quot = ua.browser.gecko ? '\"' : ''; + equal(editor.body.style.cursor, 'url(' + quot + editor.options.cursorpath + 'v.png' + quot + '),' + space + 'pointer'); +// //me.body.style.cursor + var selectedTds = editor.getUETable(editor.body.firstChild).selectedTds; + equal(selectedTds.length, 2, '选中一行'); + equal(selectedTds[0].className, 'selectTdClass', '检查样式'); + equal(selectedTds[1].className, 'selectTdClass', '检查样式'); + equal(selectedTds[0].innerHTML, 'hello1', '检查内容'); + equal(selectedTds[1].innerHTML, 'hello2', '检查内容'); + //todo trace 3571 +// ua.click(tds[2],{clientX:12,clientY:24,shiftKey:true}); +// equal(editor.getUETable(editor.body.firstChild).selectedTds.length,6,''); + start(); + }, 50); + }, 50); + stop(); +}); + +test('点击一行的最左边,但是每行只有一列,这时选中单元格中的内容', function () { + if (ua.browser.ie && ua.browser.ie < 9)return;//todo click事件模拟有问题 + var editor = te.obj[0]; + editor.setContent(''); + editor.execCommand('inserttable', {numCols: 1, numRows: 1}); + /*插入表格*/ + var tds = editor.body.getElementsByTagName('td'); + tds[0].innerHTML = 'hello'; + setTimeout(function () { + window.scrollTo(0,0);//保证位置准确 + + ua.click(tds[0], {clientX: 10, clientY: 23}); + setTimeout(function () { + var selectedTds = editor.getUETable(editor.body.firstChild).selectedTds; + equal(selectedTds.length, 0, '不选中行'); + if (ua.browser.ie>8) { + ua.checkResult(editor.selection.getRange(), tds[0].firstChild, tds[0].firstChild, 0, 5, false, '检查选中的range'); + } else { + ua.checkResult(editor.selection.getRange(), tds[0], tds[0], 0, 1, false, '检查选中的range'); + } + start(); + }, 500); + }, 500); + stop(); +}); +test('点击一列的最上边,但是每列只有一行,这时选中单元格中的内容', function () { + if (ua.browser.ie && ua.browser.ie < 9)return;//todo click事件模拟有问题 + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent(''); + editor.execCommand('inserttable', {numCols: 1, numRows: 1}); + /*插入表格*/ + stop(); + setTimeout(function () { + var tds = editor.body.getElementsByTagName('td'); + tds[0].innerHTML = 'hello'; + window.scrollTo(0,0);//保证位置准确 + ua.click(tds[0], {clientX: 81, clientY: 9,pageX: 81, pageY: 9}); + setTimeout(function () { + var selectedTds = editor.getUETable(editor.body.firstChild).selectedTds; + equal(selectedTds.length, 0, '不选中列'); + if (ua.browser.ie>8) { + ua.checkResult(editor.selection.getRange(), tds[0].firstChild, tds[0].firstChild, 0, 5, false, '检查选中的range'); + } else { + ua.checkResult(editor.selection.getRange(), tds[0], tds[0], 0, 1, false, '检查选中的range'); + } + start(); + },10); + }, 50); +}); +test('点击一列的最上边,选中一列', function () { + if (ua.browser.ie && ua.browser.ie < 9)return;//todo click事件模拟有问题 + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent(''); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + + /*插入表格*/ + stop(); + setTimeout(function () { + var tds = editor.body.getElementsByTagName('td'); + tds[0].innerHTML = 'hello'; + window.scrollTo(0,0); + ua.mousemove(tds[0], {clientX: 81, clientY: 9}); + var space = ua.browser.ie ? '' : ' '; + var quot = ua.browser.gecko ? '\"' : ''; + equal(editor.body.style.cursor, 'url(' + quot + editor.options.cursorpath + 'h.png' + quot + '),' + space + 'pointer'); + ua.click(tds[0], {clientX: 81, clientY: 9}); + setTimeout(function () { + var selectedTds = editor.getUETable(editor.body.firstChild).selectedTds; + equal(selectedTds.length, 3, '选中一列'); + equal(selectedTds[0].innerHTML, 'hello', '检查内容'); + equal(selectedTds[0].className, 'selectTdClass', '检查样式'); + equal(selectedTds[1].className, 'selectTdClass', '检查样式'); + equal(selectedTds[2].className, 'selectTdClass', '检查样式'); + + //todo trace 3571 +// ua.click(tds[2],{clientX:370,clientY:9,shiftKey:true}); +// equal(editor.getUETable(editor.body.firstChild).selectedTds.length,9,''); + start(); + }, 500); + }, 50); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/table.cmds.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/table.cmds.js new file mode 100644 index 000000000..aca0c18e0 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/table.cmds.js @@ -0,0 +1,1519 @@ +module('plugins.table'); +//test('',function(){stop()}) +/*trace992,合并单元格后多了一个td*/ +test('向右合并--拆分成列', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:2, numRows:2}); + ua.manualDeleteFillData(editor.body); + + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('mergeright'); + range.setStart(tds[1], 0).collapse(true).select(); + editor.execCommand('mergeright'); + tds = editor.body.getElementsByTagName('td'); + equal(tds.length, 2, '2个单元格'); + equal(tds[0].getAttribute('colspan'), 2, '第一行的单元格colspan为2'); + equal(tds[1].getAttribute('colspan'), 2, '第二行的单元格colspan为2'); + ua.manualDeleteFillData(editor.body); + setTimeout(function () { + editor.execCommand('source'); + start(); + }); + stop(); + tds = editor.body.getElementsByTagName('td'); + equal(tds.length, 2, '2个单元格'); + equal(tds[0].getAttribute('colspan'), 2, '切换到源码后第一个的单元格colspan'); + equal(tds[1].getAttribute('colspan'), 2, '切换到源码后第二行第一个的单元格colspan'); + + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('splittocols'); + equal(tds[0].getAttribute('colspan'), 1, '拆分--[0][0]单元格colspan'); + equal(tds[0].rowSpan, 1, '拆分--[0][0]单元格rowspan'); +}); +test('trace 3985 向右合并--拆分成列:th', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:2, numRows:2}); + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0],0).collapse(true).select(); + editor.execCommand('inserttitle'); + var ths = editor.body.getElementsByTagName('th'); + range.setStart(ths[0], 0).collapse(true).select(); + editor.execCommand('mergeright'); + ths = editor.body.getElementsByTagName('th'); + equal(ths.length, 1, '1个th'); + range.setStart(ths[0], 0).collapse(true).select(); + editor.execCommand('splittocols'); + equal(editor.body.getElementsByTagName('th').length, 2, '拆分单元格th'); +}); +test('trace 3985 向下合并-拆分成行', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:2, numRows:2}); + ua.manualDeleteFillData(editor.body); + var tds = editor.body.getElementsByTagName('td'); + + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('mergedown'); + range.setStart(tds[1], 0).collapse(true).select(); + editor.execCommand('mergedown'); + tds = editor.body.getElementsByTagName('td'); + equal(tds.length, 2, '2个单元格'); + equal(tds[0].getAttribute('rowspan'), 2, '合并--[0][0]单元格rowspan'); + equal(tds[1].getAttribute('rowspan'), 2, '合并--[0][1]单元格rowspan'); + + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('splittorows'); + range.setStart(tds[1], 0).collapse(true).select(); + editor.execCommand('splittorows'); + equal(tds[0].colSpan, 1, '拆分--[0][0]单元格colspan'); + equal(tds[0].getAttribute('rowspan'), 1, '拆分--[0][0]单元格rowspan'); +}); + +test('完全拆分单元格', function () { + if (ua.browser.ie&&ua.browser.ie >8)return;//todo ie9,10改range bug trace 单元格不能框选 + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:3, numRows:3}); + ua.manualDeleteFillData(editor.body); + + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[1]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + + editor.execCommand('mergecells'); + ut.clearSelected(); + var tds = editor.body.getElementsByTagName('td'); + equal(tds.length, 6, '单元格数'); + equal(tds[0].getAttribute('colspan'), 2, '合并--[0][0]单元格colspan'); + equal(tds[0].getAttribute('rowspan'), 2, '合并--[0][0]单元格rowspan'); + + editor.execCommand('splittoCells'); + equal(tds.length, 9, '单元格数'); + equal(tds[0].getAttribute('colspan'), 1, '拆分--[0][0]单元格colspan'); + equal(tds[0].getAttribute('rowspan'), 1, '拆分--[0][0]单元格rowspan'); + equal(tds[1].colSpan, 1, '拆分--[0][1]单元格colspan'); + equal(tds[1].getAttribute('rowspan'), 1, '拆分--[0][1]单元格rowspan'); + + editor.undoManger.undo(); + equal(tds[0].getAttribute('colspan'), 2, '撤销--[0][0]单元格colspan'); + equal(tds[0].getAttribute('rowspan'), 2, '撤销--[0][0]单元格rowspan'); + start(); + }, 50); + stop(); +}); + +test('删除table', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable'); + ua.manualDeleteFillData(editor.body); + equal(editor.queryCommandState('deletetable'), -1, '删除按钮灰色'); + + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('deletetable'); + ua.manualDeleteFillData(editor.body); + var table = editor.body.getElementsByTagName('table')[0]; + equal(table, undefined, '删除成功'); +}); + +test('平均分配行列', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var html = '









    '; + editor.setContent(html); + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[1].cells[0], trs[1].cells[2]); + ut.setSelected(cellsRange); + range.setStart(trs[1].cells[0], 0).collapse(true).select(); + editor.execCommand('averagedistributecol'); + ut.clearSelected(); + equal(editor.body.firstChild.getElementsByTagName('td')[1].width, editor.body.firstChild.getElementsByTagName('td')[2].width, '平均分配各列'); + cellsRange = ut.getCellsRange(trs[1].cells[0], trs[3].cells[0]); + ut.setSelected(cellsRange); + range.setStart(trs[1].cells[0], 0).collapse(true).select(); + editor.execCommand('averagedistributerow'); + ut.clearSelected(); + trs = editor.body.firstChild.getElementsByTagName('tr'); + equal(trs[2].cells[0].height, trs[3].cells[0].height, '平均分配各行'); +}); +test('选部分行时,平均分布行/选部分列时,平均分布列', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var html = '









    '; + editor.setContent(html); + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[2]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('averagedistributerow'); + ut.clearSelected(); + trs = editor.body.firstChild.getElementsByTagName('tr'); + equal(trs[1].cells[0].height, trs[0].cells[0].height, '平均分配各行'); + cellsRange = ut.getCellsRange(trs[0].cells[0], trs[2].cells[1]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('averagedistributecol'); + ut.clearSelected(); + equal(editor.body.firstChild.getElementsByTagName('td')[0].width, editor.body.firstChild.getElementsByTagName('td')[1].width, '平均分配各列'); +}); + +test('表格中设置对齐方式', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    hello

    '); + stop(); + setTimeout(function(){ + var caption = editor.body.getElementsByTagName('caption'); + range.setStart(caption[0], 0).collapse(true).select(); + editor.execCommand('cellalignment', {align:'right', vAlign:'top'}); + equal(caption[0].style.textAlign, 'right', 'caption对齐方式为右上对齐'); + equal(caption[0].style.verticalAlign, 'top', 'caption对齐方式为右上对齐'); + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('cellalignment', {align:'right', vAlign:'top'}); + equal(tds[0].align, 'right', 'td对齐方式为右上对齐'); + equal(tds[0].vAlign, 'top', 'td对齐方式为右上对齐'); + //*不闭合设置对齐方式*//* + range.selectNode(tds[1].firstChild, 0).select(); + editor.execCommand('cellalignment', {align:'center', vAlign:'middle'}); + equal(tds[1].align, 'center', 'p对齐方式为居中对齐'); + start(); + },50); + +}); + +test('修改table屬性', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:2, numRows:3}); + range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); + editor.execCommand('tablealignment', 'center'); + var table = editor.body.getElementsByTagName('table')[0]; + equal(table.align, 'center', '对齐方式居中'); + range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); + editor.execCommand('edittable', '#ff0000'); + ua.manualDeleteFillData(editor.body); + var tds = editor.body.getElementsByTagName('td'); + if (ua.browser.ie && ua.browser.ie < 9) { + equal(tds[0].style.borderColor, '#ff0000', '边框颜色:红色'); + } else { + equal(tds[0].style.borderColor, 'rgb(255, 0, 0)', '边框颜色:红色'); + } + equal(editor.queryCommandState('edittable'), 0, 'state'); +}); + +test('修改单元格', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable'); + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[2], 0).collapse(true).select(); + editor.execCommand('edittd', '#9bbb59'); + if (ua.browser.ie && ua.browser.ie < 9) { + equal(tds[2].style.backgroundColor, '#9bbb59', '背景颜色'); + } else { + equal(tds[2].style.backgroundColor, 'rgb(155, 187, 89)', '背景颜色'); + } + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(tds[0], tds[6]); + ut.setSelected(cellsRange); + range.setStart(tds[0], 0).collapse(true).select(); + + editor.execCommand('edittd', '#9bbb59'); + editor.execCommand('cellalignment', {align:'center', vAlign:'bottom'}); + ut.clearSelected(); + tds = editor.body.firstChild.getElementsByTagName('td'); + if (ua.browser.ie && ua.browser.ie < 9) { + equal(tds[5].style.backgroundColor, '#9bbb59', '背景颜色'); + } else { + equal(tds[5].style.backgroundColor, 'rgb(155, 187, 89)', '背景颜色'); + } + equal(tds[5].align, 'center', '水平居中'); + equal(tds[5].vAlign, 'bottom', '下方'); + equal(editor.queryCommandState('edittd'), 0, 'state'); + equal(editor.queryCommandState('cellalignment'), 0, 'state'); +}); + +test('表格前插行', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable'); + var tds = editor.body.firstChild.getElementsByTagName('td'); + range.setStart(tds[1], 0).collapse(true).select(); + editor.execCommand('insertparagraphbeforetable'); + ua.manualDeleteFillData(editor.body); + var br = ua.browser.ie ? ' ' : '
    '; + equal(editor.body.firstChild.innerHTML, br, '表格前插行'); +}); + +test('插入行', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:3, numRows:3}); + ua.manualDeleteFillData(editor.body); + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('mergedown'); + range.setStart(tds[4], 0).collapse(true).select(); + editor.execCommand('insertrow'); + tds = editor.body.getElementsByTagName('td'); + equal(tds[0].getAttribute('rowspan'), 3, '[0][0]单元格rowspan'); + editor.undoManger.undo(); + equal(tds[0].getAttribute('rowspan'), 2, '[0][0]单元格rowspan'); +}); +test('选中两行,插入行', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('
    hello
    '); + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[0]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('insertrow'); + ut.clearSelected(); + equal(editor.body.getElementsByTagName('tr').length, 5, '选中两行,前插行,3行变5行'); + trs = editor.body.firstChild.getElementsByTagName('tr'); + ua.manualDeleteFillData(trs[2]); + equal(trs[2].cells[0].innerHTML,'hello','原来的第1行变成第3行'); + ut = editor.getUETable(editor.body.firstChild); + cellsRange = ut.getCellsRange(trs[2].cells[0], trs[3].cells[0]); + ut.setSelected(cellsRange); + range.setStart(trs[2].cells[0], 0).collapse(true).select(); + editor.execCommand('insertrownext'); + ut.clearSelected(); + equal(editor.body.getElementsByTagName('tr').length, 7,'选中两行,前插行,5行变7行'); + trs = editor.body.firstChild.getElementsByTagName('tr'); + ua.manualDeleteFillData(trs[2]); + equal(trs[2].cells[0].innerHTML,'hello',''); +}); +test('选中两列,插入列', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('
    hello
    '); + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[0].cells[1]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('insertcol'); + ut.clearSelected(); + equal(editor.body.getElementsByTagName('tr')[0].childNodes.length, 5, '选中两列,前插列,3行变5列'); + trs = editor.body.firstChild.getElementsByTagName('tr'); + ua.manualDeleteFillData(trs[0]); + equal(trs[0].cells[2].innerHTML,'hello','原来的第1列变成第3列'); + ut = editor.getUETable(editor.body.firstChild); + cellsRange = ut.getCellsRange(trs[0].cells[2], trs[0].cells[3]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[2], 0).collapse(true).select(); + editor.execCommand('insertcolnext'); + ut.clearSelected(); + equal(editor.body.getElementsByTagName('tr')[0].childNodes.length, 7,'选中两列,前插列,5列变7列'); + trs = editor.body.firstChild.getElementsByTagName('tr'); + ua.manualDeleteFillData(trs[0]); + equal(trs[0].cells[2].innerHTML,'hello',''); +}); +test('trace 3986 插入列', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:3, numRows:3}); + ua.manualDeleteFillData(editor.body); + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('mergeright'); + range.setStart(tds[3], 0).collapse(true).select(); + editor.execCommand('insertcol'); + tds = editor.body.getElementsByTagName('td'); + equal(tds[0].getAttribute('colspan'), 3, '[0][0]单元格colspan'); + editor.undoManger.undo(); + equal(tds[0].getAttribute('colspan'), 2, '[0][0]单元格colspan'); + range.setStart(tds[1], 0).setCursor(); + editor.execCommand("insertcol"); + equal(tds[0].parentNode.cells.length, 3, "插入了一列") +}); +test('带th的表格,插入列', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:2, numRows:3}); + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0],0).collapse(true).select(); + editor.execCommand('inserttitle'); + stop(); + setTimeout(function(){ + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('insertcol'); + var ths = editor.body.getElementsByTagName('tr')[0].childNodes; + equal(ths.length,3,'第一行有3个单元'); + for(var i=0;i'); + stop(); + setTimeout(function(){ + var trs = editor.body.getElementsByTagName('tr'); + range.setStart(trs[1].cells[0], 0).collapse(true).select(); + editor.execCommand('insertcolnext'); + trs = editor.body.getElementsByTagName('tr'); + equal(trs[1].childNodes.length, 3, '插入一列'); + equal(trs[1].cells[1].tagName.toLowerCase(), 'td', '除第一行以外,插入的不能是th'); + start(); + }, 20); +}); + +test('删除行', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('
    12
    34
    56
    '); + // + + stop(); + setTimeout(function () { + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(1).select(); + editor.execCommand('deleterow'); + equal(editor.body.getElementsByTagName('tr').length, 2, '删除行'); + editor.undoManger.undo(); + setTimeout(function () { + equal(editor.body.getElementsByTagName('tr').length, 3, '撤销后的行数'); + tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[5], 0).collapse(1).select(); + editor.execCommand('deleterow'); + setTimeout(function () { + equal(editor.body.getElementsByTagName('tr').length, 2, '删除行'); + var table = editor.document.getElementsByTagName("table")[0]; + var cell = table.rows[0].cells[0]; + setTimeout(function () { + range.setStart(cell, 0).setCursor(); + editor.execCommand("mergeDown"); + equal(cell.rowSpan, 2, "合并了一行"); + editor.execCommand("deleterow"); + equal(table.rows.length, 1, "在合并的单元格中删除行后,表格变成了一行"); + start(); + }, 50); + }, 50); + }, 50); + }, 50); +}); +test('选中部分单元格,删除行列', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[0].cells[1]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('deleterow'); + ut.clearSelected(); + equal(editor.body.getElementsByTagName('tr').length, 2, '选中部分单元格,删除行'); + trs = editor.body.firstChild.getElementsByTagName('tr'); + ut = editor.getUETable(editor.body.firstChild); + cellsRange = ut.getCellsRange(trs[0].cells[0], trs[0].cells[1]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).setEnd(trs[0].cells[1], 1).select(); + editor.execCommand('deletecol'); + ut.clearSelected(); + equal(trs[0].childNodes.length, 1, '选中部分单元格,删除列'); + trs = editor.body.firstChild.getElementsByTagName('tr'); + ut = editor.getUETable(editor.body.firstChild); + cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[0]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + ut.clearSelected(); + editor.execCommand('deletecol'); + equal(editor.body.getElementsByTagName('table').length, 0, '删除列至表格删空'); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + trs = editor.body.firstChild.getElementsByTagName('tr'); + ut = editor.getUETable(editor.body.firstChild); + cellsRange = ut.getCellsRange(trs[0].cells[0], trs[2].cells[0]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('deleterow'); + ut.clearSelected(); + equal(editor.body.getElementsByTagName('table').length, 0, '删除列至表格删空'); + start(); + }, 50); + stop(); +}); +test('settablebackground', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    ' ); + range.setStart( editor.body.firstChild, 0 ).collapse( true ).select(); + editor.execCommand( 'inserttable', {numCols:2,numRows:2} ); + var tds = editor.body.firstChild.getElementsByTagName('td'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(tds[0], tds[2]); + ut.setSelected(cellsRange); + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand("settablebackground",{repeat:true,colorList:["#bbb","#ccc"]}); + setTimeout(function(){ + var br = ua.browser.ie?'':'
    '; + var tds = editor.body.firstChild.getElementsByTagName('td'); + if(ua.browser.ie&&ua.browser.ie<9){ + ok( tds[0].style.backgroundColor === '#bbb', '选区隔行变色, 第一列第一行颜色匹配' ); + ok( tds[2].style.backgroundColor === '#ccc', '选区隔行变色, 第一列第二行颜色匹配' ); + } + else{ + ok( tds[0].style.backgroundColor === 'rgb(187, 187, 187)', '选区隔行变色, 第一列第一行颜色匹配' ); + ok( tds[2].style.backgroundColor === 'rgb(204, 204, 204)', '选区隔行变色, 第一列第二行颜色匹配' ); + } + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('cleartablebackground'); + setTimeout(function(){ + ok( tds[0].style.backgroundColor === '', '取消选区隔行变色, 第一列第一行颜色匹配' ); + ok( tds[2].style.backgroundColor === '', '取消选区隔行变色, 第一列第二行颜色匹配' ); + start(); + },20); + },20); + stop(); +}); +test('interlacetable', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:2, numRows:2}); + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(1).select(); + editor.execCommand('interlacetable'); + stop(); + setTimeout(function () { + equal(editor.body.firstChild.attributes['interlaced'].nodeValue, 'enabled', ''); + equal(editor.body.getElementsByTagName('tr')[0].className, 'ue-table-interlace-color-single firstRow', ''); + equal(editor.body.getElementsByTagName('tr')[1].className, 'ue-table-interlace-color-double', ''); + tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(1).select(); + editor.execCommand('uninterlacetable'); + setTimeout(function () { + equal(editor.body.firstChild.attributes['interlaced'].nodeValue, 'disabled', ''); + equal(editor.body.getElementsByTagName('tr')[0].className, 'firstRow', ''); + start(); + }, 20); + }, 20); +}); +// +//*trace 750,1308*//* +//test( 'trace1308:前插入行的样式和原先不同', function() { +// var editor = te.obj[0]; +// var range = te.obj[1]; +// editor.setContent( '

    ' ); +// range.setStart( editor.body.firstChild, 0 ).collapse( true ).select(); +// editor.execCommand( 'inserttable', {numCols:2,numRows:2} ); +// ua.manualDeleteFillData( editor.body ); +// range.setStartAfter( editor.body.firstChild ).collapse( true ).select(); +// //cellborder:2,不支持了 +// editor.execCommand( 'inserttable', {border:2,numCols:2,numRows:2} ); +// var table2 = editor.body.getElementsByTagName( 'table' )[1]; +// range.setStart( table2.getElementsByTagName( 'td' )[0], 0 ).collapse( true ).select(); +// editor.execCommand( 'insertrow' ); +// var tds = table2.getElementsByTagName( 'td' ); +//*//*firefox下用jquery的方式去不到border-width*//* +// for(var index = 0;index

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:2, numRows:2}); + ua.manualDeleteFillData(editor.body); + var tds = editor.body.getElementsByTagName('td'); + tds[1].innerHTML = 'hello'; + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('mergeright'); + var tr = editor.body.getElementsByTagName('tr')[0]; + equal($(tr.firstChild).attr('colspan'), '2', '跨度2列'); + editor.execCommand('splittocols'); + ua.manualDeleteFillData(editor.body); + tds = editor.body.getElementsByTagName('td'); + //1.2版本,合并拆分之后hello前多了空的占位符 + ok(tds[0].innerHTML, '第一个单元格中有内容'); + ok(tds[1].innerHTML == '' || tds[1].innerHTML == '
    ', '第二个单元格中有内容'); +}); + +//*trace 743*//* +test('trace 743:合并单元格后删除列再撤销', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:4, numRows:4}); + ua.manualDeleteFillData(editor.body); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[0].cells[3]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + + editor.execCommand('mergecells'); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('deleterow'); + trs = editor.body.getElementsByTagName('tr'); + equal(trs.length, 3, '删除后只剩3个tr'); + editor.undoManger.undo(); + trs = editor.body.getElementsByTagName('tr'); + equal(trs.length, 4, '撤销后有4个tr'); + equal($(trs[0].cells[0]).attr('colspan'), 4, '第一行的第一个单元格colspan为4'); + start(); + }, 50); + stop(); +}); + +//*trace 726*//* +test('trace 726:选中合并过的单元格和普通单元格,查看完全拆分单元格菜单是否高亮', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:4, numRows:4}); + ua.manualDeleteFillData(editor.body); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[1]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + + editor.execCommand('mergecells'); + equal(editor.queryCommandState('splittocells'), 0, '应当可以拆分单元格'); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[3].cells[3]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.queryCommandState('splittocells'); + equal(editor.queryCommandState('splittocells'), -1, '应当不可以拆分单元格'); + start(); + }, 50); + }, 50); + stop(); +}); + +//*trace 718*//* +test('trace 718:2次撤销删除列', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:4, numRows:4}); + ua.manualDeleteFillData(editor.body); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[1].cells[1], trs[2].cells[2]); + ut.setSelected(cellsRange); + range.setStart(trs[1].cells[1], 0).collapse(true).select(); + + editor.execCommand('mergecells'); + equal(trs[1].cells[1].rowSpan, 2, 'rowspan 为2'); + equal(trs[1].cells[1].colSpan, 2, 'colspan 为2'); + editor.execCommand('deletecol'); + equal(trs[1].cells.length, 3, '3个td'); + editor.undoManger.undo(); + + trs = editor.body.firstChild.getElementsByTagName('tr'); + equal(trs[1].cells.length, 3, '3个td'); + equal(trs[1].cells[1].rowSpan, 2, 'rowspan 为2'); + equal(trs[1].cells[1].colSpan, 2, 'colspan 为2'); + + range.setStart(trs[1].cells[1], 0).collapse(1).select(); + editor.execCommand('deletecol'); + equal(trs[1].cells.length, 3, '3个td'); + equal(trs[1].cells[1].rowSpan, 2, 'rowspan 为2'); + ok(trs[1].cells[1].colSpan == undefined || trs[1].cells[1].colSpan == 1, 'colspan为1或者undefined'); + start(); + }, 50); + stop(); +}); + +//*trace 1098 *//* +test('trace 1098:多次合并单元格偶切换到源码再切回来', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:3, numRows:3}); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[2].cells[0]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('mergecells'); + + setTimeout(function () { + trs = editor.body.firstChild.getElementsByTagName('tr'); + ut = editor.getUETable(editor.body.firstChild); + cellsRange = ut.getCellsRange(trs[0].cells[1], trs[2].cells[0]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[1], 0).collapse(true).select(); + editor.execCommand('mergecells'); +// + setTimeout(function () { + trs = editor.body.firstChild.getElementsByTagName('tr'); + ut = editor.getUETable(editor.body.firstChild); + cellsRange = ut.getCellsRange(trs[0].cells[2], trs[1].cells[0]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[2], 0).collapse(true).select(); + editor.execCommand('mergecells'); + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + trs = editor.body.firstChild.getElementsByTagName('tr'); + equal(trs.length, 3, '3个tr'); + equal(trs[0].cells[0].rowSpan, 3, '第一个单元格rowspan 3'); + equal(trs[0].cells[1].rowSpan, 3, '第二个单元格rowspan 3'); + equal(trs[0].cells.length, 3, '3个td'); + equal(trs[1].cells.length, 0, '0个td'); + equal(trs[2].cells.length, 1, '1个td'); + start(); + }, 50); + }, 50); + }, 50); + }, 50); + }, 50); + stop(); +}); + +//*trace 1307*//* +test('trace 1307:adjustTable--多次合并单元格切换到源码再切回来--选中单元格浏览器会假死', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:4, numRows:4}); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[1].cells[0], trs[3].cells[1]); + ut.setSelected(cellsRange); + range.setStart(trs[1].cells[0], 0).collapse(true).select(); + + editor.execCommand('mergecells'); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[2], trs[2].cells[0]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[2], 0).collapse(true).select(); + editor.execCommand('mergecells'); + editor.execCommand('source'); + setTimeout(function () { + editor.execCommand('source'); + setTimeout(function () { + trs = editor.body.getElementsByTagName('tr'); + equal(trs[1].rowIndex, 1, '(1,1)行索引'); + equal(trs[1].cells[0].cellIndex, 0, '(1,0)列索引'); + equal(trs[1].cells[1].cellIndex, 1, '(1,1)列索引'); + equal(trs[2].rowIndex, 2, '(2,2)行索引'); + equal(trs[2].cells[0].cellIndex, 0, '(2,0)列索引'); + + equal(trs[1].cells[0].rowSpan, 3, '第二行第一个单元格rowspan 3'); + equal(trs[1].cells[0].colSpan, 2, '第二行第一个单元格colspan 2'); + equal(trs[0].cells[2].rowSpan, 3, '第一行第三个单元格rowspan 3'); + equal(trs.length, 4, '4个tr'); + equal(trs[0].cells.length, 4, '4个td'); + equal(trs[1].cells.length, 2, '2个td'); + equal(trs[2].cells.length, 1, '1个td'); + equal(trs[3].cells.length, 2, '2个td'); + start(); + }, 50); + }, 50); + }, 50); + }, 50); + stop(); +}); +//*//*trace 2378*//* +//test('不覆盖原来的class',function(){ +// var editor = te.obj[0]; +// editor.setContent('
    '); +// editor.execCommand('source'); +// editor.execCommand('source'); +// var table = editor.body.getElementsByTagName('table'); +// equal($(table).attr('class'),'asdf noBorderTable','table的class'); +//}); + +//*trace 3121*//* +//*trace 3195*//* +test('单元格对齐方式-align', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:3, numRows:3}); + ua.manualDeleteFillData(editor.body); + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[0].cells[2]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + + editor.execCommand('mergecells'); + ut.clearSelected(); + range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); + editor.execCommand('cellalign', 'center'); + ua.manualDeleteFillData(editor.body); + var tds = editor.body.getElementsByTagName('td'); + equal(tds[0].align, 'center', '第一个单元格居中对齐'); + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('splittocols'); + tds = editor.body.getElementsByTagName('td'); + equal(tds[0].align, 'center', '第一个单元格居中对齐'); + equal(tds[1].align, 'center', '第二个单元格居中对齐'); + equal(tds[2].align, 'center', '第二个单元格居中对齐'); +}); + +test('单元格对齐方式-vAlign', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:2, numRows:2}); + ua.manualDeleteFillData(editor.body); + + range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); + editor.execCommand('mergedown'); + range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); + editor.execCommand('cellvalign', 'middle'); + ua.manualDeleteFillData(editor.body); + var tds = editor.body.getElementsByTagName('td'); + equal(tds[0].vAlign, 'middle', '第一个单元格居中对齐'); + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('splittorows'); + tds = editor.body.getElementsByTagName('td'); + equal(tds[0].vAlign, 'middle', '第一个单元格居中对齐'); + equal(tds[2].vAlign, 'middle', '第二个单元格居中对齐'); +}); + +test('adaptbytext,adaptbywindow', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:2, numRows:2}); + range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); + if(ua.browser.ie!=8) + ok( editor.body.offsetWidth === editor.body.getElementsByTagName('table')[0].offsetWidth ,'默认按窗口计算宽度');//数值不具体计算了 + editor.execCommand('adaptbytext');//parseInt + stop(); + setTimeout(function(){ + equal(editor.body.firstChild.width,'','按内容自适应') + editor.execCommand('adaptbywindow'); + setTimeout(function(){ + ok((parseInt(editor.body.firstChild.width)-editor.body.offsetWidth/2)>0,'默认按窗口计算宽度'); + start(); + },20); + },20); +}); + +test('deletetitle', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    ' ); + range.setStart( editor.body.firstChild, 0 ).collapse( true ).select(); + editor.execCommand( 'inserttable', {numCols:2, numRows:2}); + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0],0).collapse(true).select(); + editor.execCommand('inserttitle'); + stop(); + setTimeout(function(){ + var trs = editor.body.firstChild.getElementsByTagName('tr'); + equal(trs.length,3,'表格增加一行'); + for(var i = 0; i< trs[0].childNodes.length;i++){ + equal(trs[0].childNodes[i].tagName.toLowerCase(),'th','增加的th'); + } + range.setStart(tds[0],0).collapse(true).select(); + editor.execCommand('deletetitle'); + setTimeout(function(){ + equal(editor.body.firstChild.getElementsByTagName('tr').length,2,'表格减少一行'); + equal(editor.body.firstChild.getElementsByTagName('tr')[0].firstChild.tagName.toLowerCase(),'td','第一行不是标题'); + start(); + },20); + },20); +}); + +/*trace 3222*/ +test('trace 3222:在合并后的单元格中按tab键', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable'); + ua.manualDeleteFillData(editor.body); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[1].cells[1], trs[2].cells[1]); + ut.setSelected(cellsRange); + range.setStart(trs[1].cells[1], 0).collapse(true).select(); + + editor.execCommand('mergecells'); + trs[1].cells[2].innerHTML = 'asd'; + range.setStart(trs[1].cells[1], 0).collapse(true).select(); + ua.keydown(editor.body, {'keyCode':9}); + if (ua.browser.gecko||ua.browser.webkit) + equal(editor.selection.getRange().startContainer.innerHTML, 'asd', '第一次tab键'); + else + equal(editor.selection.getRange().startContainer.data, 'asd', '第一次tab键'); + range.setStart(trs[1].cells[1], 0).collapse(true).select(); + ua.keydown(editor.body, {'keyCode':9}); + if (ua.browser.gecko||ua.browser.webkit) + equal(editor.selection.getRange().startContainer.innerHTML, 'asd', '第二次tab键'); + else + equal(editor.selection.getRange().startContainer.data, 'asd', '第二次tab键'); + start(); + }, 50); + stop(); +}); + +/*trace 3191*/ +test('trace 3191:删除表格名称', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable'); + setTimeout(function () { + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(true).select(); + editor.execCommand('insertcaption'); + range.setStart(editor.body.getElementsByTagName('caption')[0], 0).collapse(true).select(); + editor.execCommand('deletecaption'); + equal(editor.body.getElementsByTagName('caption').length, '0', '表格名称被删除'); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + ua.keydown(editor.body, {keyCode: 90, ctrlKey: true}); + equal(editor.body.getElementsByTagName('caption').length, '1', '表格名称被还原'); + start(); + }, 50); + stop(); +}); + +/*trace 3195*/ +test('trace 3195:合并单元格后删除列再撤销', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:4, numRows:4}); + ua.manualDeleteFillData(editor.body); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + trs[0].cells[1].innerHTML = 'asd'; + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[2].cells[2]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + + editor.execCommand('mergecells'); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('splittocols'); + trs = editor.body.getElementsByTagName('tr'); + equal(trs.length, 4, '4个tr'); + equal(trs[0].cells.length, 4, '4个td'); + equal(trs[1].cells.length, 1, '1个td'); + equal(trs[2].cells.length, 1, '1个td'); + equal(trs[3].cells.length, 4, '4个td'); + equal(trs[0].cells[0].vAlign, 'top', '单元格[0][0]的vAlign'); + equal(trs[0].cells[0].align, '', '单元格[0][0]的align'); + equal(trs[0].cells[1].vAlign, 'top', '单元格[0][1]的vAlign'); + equal(trs[0].cells[2].vAlign, 'top', '单元格[0][2]的vAlign'); + if (ua.browser.ie) { + equal(trs[0].cells[1].align, '', '单元格[0][1]的align'); + equal(trs[0].cells[2].align, '', '单元格[0][2]的align'); + } else { + equal(trs[0].cells[1].align, 'null', '单元格[0][1]的align'); + equal(trs[0].cells[2].align, 'null', '单元格[0][2]的align'); + } + start(); + }, 50); + stop(); +}); + +/*trace 3231*/ +test(' trace 3779 trace 3231:向右合并--拆分成列', function () { + if(ua.browser.ie&& ua.browser.ie>8)return;//todo + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:2, numRows:2}); + setTimeout(function () { + ua.manualDeleteFillData(editor.body); + var tds = editor.body.getElementsByTagName('td'); + tds[1].innerHTML = 'asd'; + range.setStart(tds[1], 0).collapse(true).select(); + editor.execCommand('insertcolnext'); + ua.manualDeleteFillData(editor.body); + equal(editor.body.getElementsByTagName('tr')[0].cells.length, '3', '3列'); + equal(editor.body.getElementsByTagName('td')[1].innerHTML, 'asd', '后插入行'); + var br = ua.browser.ie ? '' : '
    '; + equal(editor.body.getElementsByTagName('td')[2].innerHTML, br, '后插入行'); + range.setStart(editor.body.getElementsByTagName('td')[2], 0).collapse(true).select(); + editor.execCommand('insertrownext'); + equal(editor.body.getElementsByTagName('tr').length, 3, '3行'); + editor.execCommand('deletecol'); + equal(editor.body.getElementsByTagName('td')[1].innerHTML, 'asd', ''); + equal(editor.body.getElementsByTagName('td').length, '6', ''); + start(); + }, 50); + stop(); +}); +//test('标题行中底纹',function(){ +// var editor = te.obj[0]; +// var range = te.obj[1]; +// editor.setContent( '

    ' ); +// range.setStart( editor.body.firstChild, 0 ).collapse( true ).select(); +// editor.execCommand( 'inserttable'); +// var tds = editor.body.getElementsByTagName('td'); +// range.setStart(tds[0],0).collapse(true).select(); +// editor.execCommand('inserttitle'); +// +// var ut = editor.getUETable(editor.body.firstChild); +// var ths = editor.body.getElementsByTagName('th'); +// var cellsRange = ut.getCellsRange(ths[0],ths[4]); +// ut.setSelected(cellsRange); +// range.setStart( ths[0], 0 ).collapse( true ).select(); +// editor.execCommand('interlacetable'); +// ut.clearSelected(); +// equal(ths[0].style.backgroundColor,'red','红色'); +//// equal(editor.queryCommandState('settablebackground'),-1,'命令不可用'); +//}); + +/*trace 713*/ +test('trace 713:合并最后一列单元格后再前插入列', function () { + if(ua.browser.ie)//TODO 1.2.6 + return; + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols:3, numRows:3}); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[2], trs[2].cells[2]); + /*合并最后一列的单元格*/ + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[2], 0).collapse(true).select(); + + editor.execCommand('mergecells'); + setTimeout(function () { + equal($(trs[0].cells[2]).attr('rowspan'), 3, '跨3行'); + editor.execCommand('insertcol'); + setTimeout(function () { + /*前插入列*/ + trs = editor.body.getElementsByTagName('tr'); + equal(trs[0].cells.length, 4, '4列'); + equal($(trs[0].cells[3]).attr('rowspan'), 3, '跨3行'); + start(); + }, 50); + }, 50); + }, 50); + stop(); +}); + + +test('inserttitlecol, deletetitlecol', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    ' ); + range.setStart( editor.body.firstChild, 0 ).collapse( true ).select(); + editor.execCommand( 'inserttable', {numCols:2, numRows:2}); + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0],0).collapse(true).select(); + editor.execCommand('inserttitlecol'); + stop(); + setTimeout(function(){ + var trs = editor.body.firstChild.getElementsByTagName('tr'); + equal(trs[0].children.length,3,'表格增加一列'); + for(var i = 0; i< trs.length;i++){ + equal(trs[i].childNodes[0].tagName.toLowerCase(),'th','增加的th'); + } + range.setStart(tds[0],0).collapse(true).select(); + editor.execCommand('deletetitlecol'); + setTimeout(function(){ + equal(trs[0].children.length,2,'表格减少一列'); + equal(editor.body.firstChild.getElementsByTagName('tr')[0].firstChild.tagName.toLowerCase(),'td','第一列不是标题'); + start(); + },20); + },20); +}); +/*trace 3216*/ +test('contextMenu trace 3216:前插入行', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + stop(); + var lang = editor.getLang("contextMenu"); + editor.execCommand('cleardoc'); + editor.execCommand('inserttable'); + var tds = editor.body.getElementsByTagName('td'); + tds[0].innerHTML = 'asd'; + range.setStart(tds[0], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + var menutable = document.getElementsByClassName("edui-menu-body")[1]; + var forTable = document.getElementsByClassName('edui-for-table'); + if (ua.browser.ie) { + ua.mouseenter(forTable[forTable.length - 1]); + } else { + ua.mouseover(forTable[forTable.length - 1]); + } + setTimeout(function () { + lang = editor.getLang("contextMenu"); + ua.click(menutable.childNodes[6]); + equal(editor.body.getElementsByTagName('tr').length, 6, '前插入行后有6行'); + equal(ua.getChildHTML(editor.body.getElementsByTagName('td')[5]), 'asd', '原单元格中文本未改变'); + setTimeout(function () { + document.getElementById('edui_fixedlayer').parentNode.removeChild(document.getElementById('edui_fixedlayer')); + te.dom.push(editor.container); + start(); + }, 200); + }, 200); +}); +test('contextMenu 选区背景隔行', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + stop(); + var lang = editor.getLang("contextMenu"); + editor.execCommand('cleardoc'); + editor.execCommand('inserttable'); + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[1]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + var menutableBody = document.getElementsByClassName("edui-menu-body")[3]; + var forTable = document.getElementsByClassName('edui-for-table'); + if (ua.browser.ie) { + ua.mouseenter(forTable[forTable.length - 1]); + } else { + ua.mouseover(forTable[forTable.length - 1]); + } + setTimeout(function () { + lang = editor.getLang("contextMenu"); + equal(menutableBody.childNodes.length, 4, '4个子项目'); + if (browser.gecko) { + equal(menutableBody.textContent, '表格隔行变色选区背景隔行红蓝相间三色渐变', '检查menu显示的字符'); + } + else { + equal(menutableBody.innerText.replace(/[\r\n\t\u200b\ufeff]/g, ''), '表格隔行变色选区背景隔行红蓝相间三色渐变', '检查menu显示的字符'); + } + ua.click(menutableBody.childNodes[1]); + ut.clearSelected(); + trs = editor.body.getElementsByTagName('tr'); + if (ua.browser.ie == 8) { + equal(trs[0].cells[0].style.backgroundColor, '#bbb', '第一行'); + equal(trs[1].cells[1].style.backgroundColor, '#ccc', '第二行'); + } else { + equal(trs[0].cells[0].style.backgroundColor, 'rgb(187, 187, 187)', '第一行'); + equal(trs[1].cells[1].style.backgroundColor, 'rgb(204, 204, 204)', '第二行'); + } + cellsRange = ut.getCellsRange(trs[0].cells[2], trs[1].cells[3]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[2], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + menutableBody = document.getElementsByClassName("edui-menu-body")[3]; + forTable = document.getElementsByClassName('edui-for-table'); + if (ua.browser.ie) { + ua.mouseenter(forTable[forTable.length - 1]); + } else { + ua.mouseover(forTable[forTable.length - 1]); + } + setTimeout(function () { + lang = editor.getLang("contextMenu"); + equal(menutableBody.childNodes.length, 4, '4个子项目'); + ua.click(menutableBody.childNodes[2]); + ut.clearSelected(); + trs = editor.body.getElementsByTagName('tr'); + equal(trs[0].cells[2].style.backgroundColor, 'red', '第一行'); + equal(trs[1].cells[3].style.backgroundColor, 'blue', '第二行'); + ut = editor.getUETable(editor.body.firstChild); + cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[3]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + menutableBody = document.getElementsByClassName("edui-menu-body")[3]; + forTable = document.getElementsByClassName('edui-for-table'); + if (ua.browser.ie) { + ua.mouseenter(forTable[forTable.length - 1]); + } else { + ua.mouseover(forTable[forTable.length - 1]); + } + setTimeout(function () { + lang = editor.getLang("contextMenu"); + ua.click(menutableBody.childNodes[2]); + trs = editor.body.getElementsByTagName('tr'); + equal(trs[1].cells[2].style.backgroundColor, '', '取消背景隔行'); + setTimeout(function () { + document.getElementById('edui_fixedlayer').parentNode.removeChild(document.getElementById('edui_fixedlayer')); + te.dom.push(editor.container); + start(); + }, 200); + }, 200); + }, 200); + }, 200); +}); + +test('contextMenu 三色渐变', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + stop(); + + editor.execCommand('cleardoc'); + editor.execCommand('inserttable'); + var tds = editor.body.getElementsByTagName('td'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(tds[0], tds[16]); + ut.setSelected(cellsRange); + range.setStart(tds[0], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + var menutable = document.getElementsByClassName("edui-menu-body")[3]; + var forTable = document.getElementsByClassName('edui-for-table'); + if (ua.browser.ie) { + ua.mouseenter(forTable[forTable.length - 1]); + } else { + ua.mouseover(forTable[forTable.length - 1]); + } + ua.click(menutable.childNodes[3]); + ut.clearSelected(); + tds = editor.body.getElementsByTagName('td'); + if (ua.browser.ie == 8) { + equal(tds[0].style.backgroundColor, '#aaa', '第一行'); + equal(tds[6].style.backgroundColor, '#bbb', '第二行'); + equal(tds[11].style.backgroundColor, '#ccc', '第二行'); + } else { + equal(tds[0].style.backgroundColor, 'rgb(170, 170, 170)', '第一行'); + equal(tds[6].style.backgroundColor, 'rgb(187, 187, 187)', '第二行'); + equal(tds[11].style.backgroundColor, 'rgb(204, 204, 204)', '第二行'); + } + setTimeout(function () { + document.getElementById('edui_fixedlayer').parentNode.removeChild(document.getElementById('edui_fixedlayer')); + te.dom.push(editor.container); + start(); + }, 20); +}); + +/*trace 3210*/ +test('contextMenu trace 3210:添加单元格背景色', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[1]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('edittd','#ff0000'); + stop(); + setTimeout(function () { + var tds = editor.body.firstChild.getElementsByTagName('td'); + equal(tds[2].style.backgroundColor, '', '背景色不变'); + equal(ua.formatColor(tds[0].style.backgroundColor), '#ff0000', '添加单元格背景色'); + equal(ua.formatColor(tds[4].style.backgroundColor), '#ff0000', '添加单元格背景色'); + start(); + }, 50); + +}); +/*trace 3099*/ +test('contextMenu trace 3099: 清除边框颜色', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + var trs = editor.body.firstChild.getElementsByTagName('tr'); + + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('edittable','#ff0000'); + stop(); + setTimeout(function () { + var tds = editor.body.firstChild.getElementsByTagName('td'); + equal(ua.formatColor(tds[0].style.borderColor), '#ff0000', '添加边框颜色'); + equal(ua.formatColor(tds[2].style.borderColor), '#ff0000', '添加边框颜色'); + editor.execCommand('edittable',''); + setTimeout(function () { + equal(tds[0].style.borderColor, '', '边框颜色被清除'); + start(); + }, 50); + }, 50); +// var div = document.body.appendChild(document.createElement('div')); +// div.id = 'ue'; +// var editor = UE.getEditor('ue'); +// stop(); +// editor.ready(function () { +// var range = new baidu.editor.dom.Range(editor.document); +// var lang = editor.getLang("contextMenu"); +// editor.execCommand('cleardoc'); +// editor.execCommand('inserttable'); +// setTimeout(function () { +// range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); +// ua.contextmenu(editor.body.firstChild); +// var menutable = document.getElementsByClassName("edui-menu-body")[1]; +// var forTable = document.getElementsByClassName('edui-for-table'); +// if (ua.browser.ie&&ua.browser.ie<9) { +// ua.mouseenter(forTable[forTable.length - 1]); +// } else { +// ua.mouseover(forTable[forTable.length - 1]); +// } +// lang = editor.getLang("contextMenu"); +// ua.click(menutable.childNodes[menutable.childNodes.length-1]);//点开表格属性 +// setTimeout(function () { +// var iframe = document.getElementsByTagName('iframe'); +// var iframe1 ; +// for (var i = iframe.length-1; i >-1; i--) { +// if (iframe[i].id && iframe[i].id.indexOf('edui') != -1) { +// iframe1 = iframe[i]; +// break; +// } +// } +// +// iframe1.contentDocument.getElementById('J_tone').value = '#ff0000'; +// var buttonBody = document.getElementsByClassName('edui-dialog edui-for-edittable edui-default edui-state-centered')[0].firstChild.firstChild.lastChild.firstChild.firstChild.firstChild.firstChild.firstChild; +// ua.click(buttonBody); +// setTimeout(function () { +// var tds = editor.body.getElementsByTagName('td'); +// if (ua.browser.ie == 8) +// equal(tds[0].style.borderColor, '#ff0000', '边框颜色设置为红色'); +// else { +// equal(tds[0].style.borderColor, 'rgb(255, 0, 0)', '边框颜色设置为红色'); +// } +// range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); +// ua.contextmenu(editor.body.firstChild); +// menutable = document.getElementsByClassName("edui-menu-body")[1]; +// forTable = document.getElementsByClassName('edui-for-table'); +// if (ua.browser.ie&&ua.browser.ie<9) { +// ua.mouseenter(forTable[forTable.length - 1]); +// } else { +// ua.mouseover(forTable[forTable.length - 1]); +// } +// lang = editor.getLang("contextMenu"); +// ua.click(menutable.childNodes[menutable.childNodes.length-1]); +// setTimeout(function () { +// iframe = document.getElementsByTagName('iframe'); +// iframe1 = null; +// for (var i = iframe.length-1; i >-1; i--) { +// if (iframe[i].id.indexOf('edui') != -1) { +// iframe1 = iframe[i]; +// break; +// } +// } +// ua.click(iframe1.contentDocument.getElementById('J_tone')); +// setTimeout(function () { +// var div_nocolor = document.getElementsByClassName('edui-colorpicker-nocolor'); +// ua.click(div_nocolor[0]); +// var buttonBody = document.getElementsByClassName('edui-dialog edui-for-edittable edui-default edui-state-centered')[1].firstChild.firstChild.lastChild.firstChild.firstChild.firstChild.firstChild.firstChild; +// ua.click(buttonBody); +// tds = editor.body.getElementsByTagName('td'); +// equal(tds[0].style.borderColor, '', '边框颜色被清除'); +// setTimeout(function () { +// UE.delEditor('ue'); +// document.getElementById('edui_fixedlayer').parentNode.removeChild(document.getElementById('edui_fixedlayer')); +// te.dom.push(document.getElementById('ue')); +// start(); +// }, 200); +// }, 200); +// }, 200); +// }, 200); +// }, 1000); +// }, 200); +// }); +}); +test('trace 3986 contextMenu 标题行中右插入列', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + stop(); + var lang = editor.getLang("contextMenu"); + editor.execCommand('cleardoc'); + editor.execCommand('inserttable'); + range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); + editor.execCommand('inserttitle'); + range.setStart(editor.body.getElementsByTagName('th')[0], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + var menutable = document.getElementsByClassName("edui-menu-body")[1]; + var forTable = document.getElementsByClassName('edui-for-table'); + if (ua.browser.ie) { + ua.mouseenter(forTable[forTable.length - 1]); + } else { + ua.mouseover(forTable[forTable.length - 1]); + } + setTimeout(function () { + lang = editor.getLang("contextMenu"); + equal(menutable.childNodes.length, 15, '15个子项目');//当光标在th[0]时,有15个项目 + /*trace 3197:没有后插行选项*/ + var innerText = lang.deletetable + lang.deleterow+ lang.deletecol + lang.insertcolnext + lang.insertcaption + lang.deletetitle +lang.inserttitlecol+ lang.mergeright + lang.edittd + lang.edittable+lang.setbordervisible; + if (browser.gecko) { + equal(menutable.textContent, innerText, '检查menu显示的字符'); + } else { + equal(menutable.innerText.replace(/[\r\n\t\u200b\ufeff]/g, ''), innerText, '检查menu显示的字符'); + } + ua.click(menutable.childNodes[4]); + equal(editor.body.getElementsByTagName('tr')[0].cells.length, 6, '左插入列后有6列'); + setTimeout(function () { + document.getElementById('edui_fixedlayer').parentNode.removeChild(document.getElementById('edui_fixedlayer')); + te.dom.push(editor.container); + start(); + }, 200); + }); +}); +/*trace 3060*/ +test('contextMenu trace 3060:单元格对齐方式', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + stop(); + + var lang = editor.getLang("contextMenu"); + editor.execCommand('cleardoc'); + editor.execCommand('inserttable'); + editor.body.getElementsByTagName('td')[0].innerHTML = 'asd'; + range.setStart(editor.body.firstChild.firstChild.firstChild.firstChild, 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + var menutableBody = document.getElementsByClassName("edui-for-aligntd")[0]; + setTimeout(function () { + lang = editor.getLang("contextMenu"); + ua.click(menutableBody.childNodes[0]); + var div = document.getElementsByClassName('edui-cellalignpicker-body')[0]; + equal(div.childNodes[0].getElementsByTagName('td').length, 9, '9种单元格对齐方式'); + ua.click(div.childNodes[0].childNodes[0].childNodes[1].childNodes[2].firstChild); + setTimeout(function () { + var tds = editor.body.getElementsByTagName('td'); + equal(tds[0].align, 'right', '水平居右'); + equal(tds[0].vAlign, 'middle', '垂直居中'); + + if(ua.browser.ie>8){ + equal(editor.selection.getRange().startContainer.tagName.toLowerCase(), 'td', '光标位于单元格中'); + + }else{ + equal(editor.selection.getRange().startContainer.parentNode.tagName.toLowerCase(), 'td', '光标位于单元格中'); + } + setTimeout(function () { +// te.dom.push(editor.container); +// document.getElementById('edui_fixedlayer').parentNode.removeChild(document.getElementById('edui_fixedlayer')); + start(); + }, 20); + }, 200); + }, 200); +// }); +}); +/*trace 3315*/ +/*trace 3411*/ +test('contextMenu trace 3315:表格隔行变色', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var lang = editor.getLang("contextMenu"); + editor.execCommand('cleardoc'); + editor.execCommand('inserttable'); + range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + var menutableBody = document.getElementsByClassName("edui-menu-body")[8]; + var forTable = document.getElementsByClassName('edui-for-table'); + if (ua.browser.ie) { + ua.mouseenter(forTable[forTable.length - 1]); + } else { + ua.mouseover(forTable[forTable.length - 1]); + } + setTimeout(function () { + lang = editor.getLang("contextMenu"); + equal(menutableBody.childNodes.length, 1, '1个子项目'); + if (browser.gecko) { + equal(menutableBody.textContent, '表格隔行变色', '检查menu显示的字符'); + } + else { + equal(menutableBody.innerText.replace(/[\r\n\t\u200b\ufeff]/g, ''), '表格隔行变色', '检查menu显示的字符'); + } + ua.click(menutableBody.childNodes[0]); + var trs = editor.body.getElementsByTagName('tr'); + for (var i = 0; i < trs.length; i++) { + if (i % 2 == 0) { + ok(trs[i].className.indexOf('ue-table-interlace-color-single')>-1,'第' + i + '行:浅色行'); + } else { + ok(trs[i].className.indexOf('ue-table-interlace-color-double')>-1,'第' + i + '行:深色行'); + } + } + range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + menutableBody = document.getElementsByClassName("edui-menu-body")[8]; + forTable = document.getElementsByClassName('edui-for-table'); + if (ua.browser.ie) { + ua.mouseenter(forTable[forTable.length - 1]); + } else { + ua.mouseover(forTable[forTable.length - 1]); + } + setTimeout(function () { + lang = editor.getLang("contextMenu"); + equal(menutableBody.childNodes.length, 1, '2个子项目'); + if (browser.gecko) { + equal(menutableBody.textContent, '取消表格隔行变色', '检查menu显示的字符'); + } + else { + equal(menutableBody.innerText.replace(/[\r\n\t\u200b\ufeff]/g, ''), '取消表格隔行变色', '检查menu显示的字符'); + } + ua.click(menutableBody.childNodes[0]); + // equal(editor.body.getElementsByTagName('table')[0].interlaced,'disabled','取消表格隔行变色'); + ok(editor.body.getElementsByTagName('tr')[0].className.indexOf('ue-table-interlace-color')<0, '取消表格隔行变色'); + setTimeout(function () { + document.getElementById('edui_fixedlayer').parentNode.removeChild(document.getElementById('edui_fixedlayer')); + te.dom.push(editor.container); + start(); + }, 200); + }, 200); + }, 200); + stop(); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/table.core.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/table.core.js new file mode 100644 index 000000000..9fd021aef --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/table.core.js @@ -0,0 +1,345 @@ +/** + * Created with JetBrains PhpStorm. + * User: taoqili + * Date: 13-2-21 + * Time: 下午1:31 + * To change this template use File | Settings | File Templates. + */ +function getTable(str) { + var div = document.getElementById("testTable"); + if (!div) { + div = document.createElement("div"); + div.id = "testTable"; + document.body.appendChild(div); + } + div.innerHTML = "" + str + "
    "; + return div.firstChild; +} +UT = UE.UETable; +test("create UETable", function () { + var table = getTable("ddd"), + ut = new UT(table); + ok(ut.table === table, "UT对象创建成功"); + ok(ut.colsNum == 1 && ut.rowsNum == 1, "单元格行、列数为1"); +}); + +test("getMaxRows", function () { + var table = getTable("123" + + "123"), + ut = new UT(table); + var maxRows = ut.getMaxRows(); + equal(maxRows, 2, "最大行数为2"); + table = getTable("123" + + "2"); + ut = new UT(table); + maxRows = ut.getMaxRows(); + equal(maxRows, 3, "最大行数为3"); +}); +test("getMaxCols", function () { + var table = getTable("123" + + "123"), + ut = new UT(table); + var maxCols = ut.getMaxCols(); + equal(maxCols, 3, "最大列数为3"); + + table = getTable("123" + + "2"); + ut = new UT(table); + maxCols = ut.getMaxCols(); + equal(maxCols, 6, "最大列数为6"); +}); + +test("ie9 active trace 3728 getSameEndPosCells", function () { + if(ua.browser.ie>9)return; + var table = getTable("12323"), + ut = new UT(table); + var cell = table.rows[0].cells[0], + cells1 = ut.getSameEndPosCells(cell, "x"), + cells2 = ut.getSameEndPosCells(cell, "y"); + ok(cells1.length == 1, "获取到同样X轴结尾位置的cell1个"); + ok(cells2.length == 2, "获取到同样Y轴结尾位置的cell2个"); +}); + +test("getHSideCell", function () { + var table = getTable("123" + + "23"), + ut = new UT(table); + var rows = table.rows, + cell = rows[1].cells[1], + cell1 = ut.getHSideCell(cell), + cell2 = ut.getHSideCell(cell, true); + equal(cell1, rows[1].cells[0], "左边单元格"); + equal(cell2, null, "位于右边缘的单元格无右邻居单元格"); + equal(ut.getHSideCell(rows[0][0]), null, "位于左边缘的单元格无左邻居单元格"); +}); + +test("getVSideCell", function () { + var table = getTable("123" + + "23"), + ut = new UT(table); + var rows = table.rows, + cell = rows[1].cells[1], + cell1 = ut.getVSideCell(cell), + cell2 = ut.getVSideCell(cell, true), + cell3 = ut.getVSideCell(cell, true, true); + equal(cell1, rows[0].cells[2], "上边单元格"); + equal(cell2, null, "位于下边缘的单元格无下邻居单元格"); + equal(cell3, null, "位于左边缘的单元格无左邻居单元格"); +}); +test("setCellContent", function () { + var table = getTable("123" + + "23"), + ut = new UT(table); + var cell = table.rows[0].cells[0]; + ut.setCellContent(cell, "这是测试内容"); + equal(cell.innerHTML, "这是测试内容", "设置了正确的内容"); + ut.setCellContent(cell); + equal(cell.innerHTML, browser.ie ? domUtils.fillChar : "
    "); +}); + +test("cloneCell", function () { + var table = getTable("123" + + "23"), + ut = new UT(table); + + var cell = ut.cloneCell(table.rows[0].cells[0]); + equal(cell.rowSpan, 2, "clone了一个2行一列的单元格"); + equal(cell.style.borderTopColor, "green", "上边框的颜色将会被下边框取代"); + cell = ut.cloneCell(table.rows[0].cells[0], true); + ok(cell.rowSpan, 1, "忽略被合并单元格时将会充值单元格的rowspan和colspan为1") +}); + + +test("getCellsRange、getCells", function () { + var table = getTable("123" + + "23"), + ut = new UT(table); + var range = ut.getCellsRange(table.rows[0].cells[1], table.rows[1].cells[0]); + ok(range.beginRowIndex === 0 && range.beginColIndex === 1 && range.endRowIndex === 1 && range.endColIndex === 1, "获取到range") + + var cells = ut.getCells(range); + ok(cells.length == 2, "获取到2个单元格"); + ok(cells[0] == table.rows[0].cells[1], "第一个单元格存在"); +}); + +test("insertRow、deleterRow", function () { + var table = getTable("123" + + "23"), + ut = new UT(table); + + var cellPrototype = document.createElement("td"); + cellPrototype.innerHTML = "aa"; + cellPrototype.setAttribute("vAlign", "top"); + ut.insertRow(2, cellPrototype); + ok(table.rows.length === 3, "行数变成3行"); + ok(table.rows[2].cells[0].getAttribute("vAlign") == "top", "新插入的单元格中包含原型单元格中的属性"); + +}); + +test("mergeRight,mergeDown", function () { + var table = getTable("123456" + + "2356" + + "23456"), + ut = new UT(table); + var cell = table.rows[0].cells[1]; + ut.mergeDown(cell); + ok(cell.rowSpan === 2, "向下合并成功"); + + ut.mergeDown(cell); + ok(cell.rowSpan === 3, "向下合并成功"); + + cell = cell.previousSibling; + ut.mergeRight(cell); + ok(cell.rowSpan === 3 && cell.colSpan === 2, "向右合并成功"); + + equal(cell.parentNode.rowIndex, 0, "合并到了正确的位置") +}); +test("mergeRange",function(){ + var table = getTable("123456" + + "2356" + + "23456"), + ut = new UT(table); + var range = ut.getCellsRange(table.rows[0].cells[1],table.rows[2].cells[3]); + ut.setSelected(range); + ut.mergeRange(); + ok(table.rows[0].cells[1].rowSpan===3,"合并选区") + +}); + +test("split", function () { + var table = getTable("123467" + + "2367" + + "234567"), + ut = new UT(table); + var cell = table.rows[0].cells[0], + num = table.getElementsByTagName("td").length; + ut.splitToCells(cell); + ok(cell.rowSpan == 1 && cell.colSpan == 1, "单元格被成功拆分"); + + var newNum = table.getElementsByTagName("td").length; + ok(num + 2 == newNum, "单元格数量增加了2个"); + + cell = table.rows[0].cells[3]; + ut.splitToCols(cell); + ok(cell.colSpan === 1 && cell.rowSpan == 2, "被拆分成了2列"); + + +}); + +test("selectRow", function () { + var table = getTable("123467" + + "2367" + + "234567"), + ut = new UT(table); + ut.selectRow(1); + equal(ut.selectedTds.length, table.getElementsByTagName("td").length, "选中了所有单元格") + var cells = table.rows[1].cells, + flag = false; + utils.each(cells, function (cell) { + if (cell.className == "") { + flag = true; + } + }); + ok(!flag, "所有单元格都被选中"); + ok(ut.cellsRange.beginRowIndex === 0, "cellsRange正确"); + +}); +test("selectTable", function () { + var table = getTable("123467" + + "2367" + + "234567"), + ut = new UT(table); + ut.selectTable(); + ok(ut.selectedTds.length === table.getElementsByTagName("td").length, "选中了整个表格") + +}); + +test("setBackground", function () { + var table = getTable("0123467" + + "1123467" + + "2123467"), + ut = new UT(table); + ut.setBackground(table.getElementsByTagName("td"), "green"); + var cell = table.rows[1].cells[1]; + ok(cell.style.backgroundColor == "green", "单种背景颜色设置成功"); + + ut.removeBackground(table.getElementsByTagName("td")); + ok(cell.style.backgroundColor == "", "背景颜色被清除"); + + ut.setBackground(table.getElementsByTagName("td"), { + repeat:true, + colorList:["green", "red"] + }); + ok(table.rows[0].cells[0].style.backgroundColor == "green", "第一行的单元格为绿色"); + ok(table.rows[1].cells[0].style.backgroundColor == "red", "第二行的单元格为红色"); + ok(table.rows[2].cells[0].style.backgroundColor == "green", "第三行的单元格为绿色"); + + ut.removeBackground(table.getElementsByTagName("td")); + ut.setBackground(table.getElementsByTagName("td"), { + repeat:false, + colorList:["green", "red"] + }); + ok(table.rows[0].cells[0].style.backgroundColor == "green", "第一行的单元格为绿色"); + ok(table.rows[1].cells[0].style.backgroundColor == "red", "第二行的单元格为红色"); + ok(table.rows[2].cells[0].style.backgroundColor == "", "第三行的单元格没有颜色"); + +}); + +test("isFullRow isFullCol", function () { + var table = getTable("0123467" + + "1123467" + + "2123467"), + ut = new UT(table); + var range = ut.getCellsRange(table.rows[0].cells[0], table.rows[1].cells[1]); + ut.setSelected(range); + ok(!ut.isFullRow(), "不是整行"); + range = ut.getCellsRange(table.rows[0].cells[0], table.rows[0].cells[5]); + ut.setSelected(range); + ok(ut.isFullRow(), "是整行"); + + range = ut.getCellsRange(table.rows[0].cells[0], table.rows[2].cells[0]); + ut.setSelected(range); + ok(ut.isFullCol(), "是整列"); + range = ut.getCellsRange(table.rows[0].cells[0], table.rows[1].cells[0]); + ut.setSelected(range); + ok(!ut.isFullCol(), "不是整列"); +}); + +test("last", function () { + var table = getTable("0123467" + + "1123467" + + "2123467"), + ut = new UT(table); + var cell = table.rows[2].cells[5]; + ok(ut.isLastCell(cell), "是最后一个单元格"); + ok(!ut.isLastCell(table.rows[1].cells[0]), "不是最后一个单元格"); +}); +test("getNextCell", function () { + var table = getTable("0123467" + + "1123467" + + "2123467"), + ut = new UT(table); + var cell = table.rows[2].cells[5]; + var newCell = ut.getNextCell(cell); + ok(newCell === table.rows[1].cells[5], "找到正确单元格"); + cell = table.rows[0].cells[4]; + newCell = ut.getNextCell(cell); + ok(!newCell, "顶行不存在nextCell"); + newCell = ut.getNextCell(cell, true); + ok(newCell === table.rows[1].cells[4], "获取到下一行的单元格"); + +}); + +test("getPreviewCell",function(){ + var table = getTable("0123467" + + "1123467" + + "2123467"), + ut = new UT(table); + var cell = table.rows[2].cells[5]; + var newCell = ut.getPreviewCell(cell); + ok(newCell===cell.previousSibling,"找到前置单元格"); +}); + +test("getLastCell", function () { + var table = getTable("0123467" + + "1123467" + + "2123467"), + ut = new UT(table); + var cell = ut.getLastCell(); + ok(cell === table.rows[2].cells[5], "找到最后一个单元格"); +}); + +test("getTabNextCell", function () { + var table = getTable("0123467" + + "1123467" + + "2123467"), + ut = new UT(table); + var rows = table.rows, + cell = rows[0].cells[0]; + var newCell = ut.getTabNextCell(cell); + ok(newCell === table.rows[0].cells[1], "找到最后一个单元格"); + newCell = ut.getTabNextCell(rows[0].cells[5]); + ok(newCell === table.rows[1].cells[0], "找到下一行的第一个单元格"); +}); + +//test("getSameStartPosXCells", function () { +// var table = getTable("0123467" + +// "1123467" + +// "2123467"), +// ut = new UT(table); +// var cell = table.rows[0].cells[1]; +// var cells = ut.getSameStartPosXCells(cell); +// equal(cells.length, 3, "获取到三个单元格") +// +// table = getTable("0123467" + +// "1123467" + +// "212467"); +// ut = new UT(table); +// cells = ut.getSameStartPosXCells(cell); +// ok(cells.length === 2, "获取到2个单元格"); +// +// cells = ut.getSameStartPosXCells(table.rows[0].cells[0]); +// ok(cells.length===3,"获取到三个单元格"); +// +//}); + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/table.sort.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/table.sort.js new file mode 100644 index 000000000..5d86b8740 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/table.sort.js @@ -0,0 +1,258 @@ +module('plugins.table'); + +function getTable(str) { + var div = document.getElementById("testTable"); + if (!div) { + div = document.createElement("div"); + div.id = "testTable"; + document.body.appendChild(div); + } + div.innerHTML = "" + str + "
    "; + return div.firstChild; +} +UT = UE.UETable; +test(" trace 3715 sortTable", function () { + var table = getTable("0123467" + + "1123467" + + "2123467"), + ut = new UT(table); + ut.sortTable(1, function (a, b) { + return 1;//逆序 + }); + var value = table.rows[0].cells[0].innerHTML; + equal(value, "21", "单元格被逆序"); + + ut.sortTable(0, function (td1, td2) { + var value1 = parseInt(td1.innerHTML, 10), + value2 = parseInt(td2.innerHTML, 10); + return value2 - value1; + }) + value = table.rows[0].cells[0].innerHTML; + equal(value, "21", "按数值从大到小排列"); + + ut.sortTable(0, 'reversebynum'); + equal(table.getAttribute('data-sort-type'), "reversebynum", "data-sort-type属性是否设置成功"); +}); +test('active trace 3779 sorttable', function () { + if(ua.browser.ie&&ua.browser.ie>8)return;//todo + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('
    1
    2
    '); + setTimeout(function () { + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(1).select(); + editor.execCommand('sorttable', 1); + ua.manualDeleteFillData(editor.body); + tds = editor.body.getElementsByTagName('td'); + equal(tds[0].innerHTML, 2, ''); + equal(tds[2].innerHTML, 1, ''); + start(); + }, 50); + stop(); +}); +test('sorttable,框选', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('
    1
    2
    3
    '); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[0]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('sorttable', 1); + ua.manualDeleteFillData(editor.body); + var tds = editor.body.getElementsByTagName('td'); + equal(tds[0].innerHTML, 2, ''); + equal(tds[2].innerHTML, 1, ''); + equal(tds[4].innerHTML, 3, ''); + start(); + }, 50); + stop(); +}); +test('enablesort,disablesort', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('
    1
    2
    '); + setTimeout(function () { + var tds = editor.body.getElementsByTagName('td'); + range.setStart(tds[0], 0).collapse(1).select(); + editor.execCommand('enablesort'); + + setTimeout(function () { + equal(editor.body.firstChild.attributes['data-sort'].nodeValue, 'sortEnabled', 'sortEnabled'); + equal(domUtils.hasClass(editor.body.firstChild, 'sortEnabled'), true, 'sortEnabled'); + editor.execCommand('disablesort'); + setTimeout(function () { + equal(editor.body.firstChild.attributes['data-sort'].nodeValue, 'sortDisabled', 'sortDisabled'); + equal(domUtils.hasClass(editor.body.firstChild, 'sortEnabled'), false, 'sortDisabled'); + equal(domUtils.hasClass(editor.body.firstChild.rows[0], 'firstRow'), true, '给第一行添加firstRow的类'); + start(); + }, 20); + }, 20); + }, 50); + stop(); +}); +test('contextMenu 表格逆序当前', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + stop(); + var lang = editor.getLang("contextMenu"); + editor.execCommand('cleardoc'); + var html = '
    Michael1康熙
    ackson4承祜
    {}2胤礼
    &*3襄嫔
    '; + editor.setContent(html); + range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + var menutable = document.getElementsByClassName("edui-menu-body")[2]; + setTimeout(function () { + lang = editor.getLang("contextMenu"); + equal(menutable.childNodes.length, 7, '7个子项目'); + if (browser.gecko) { + equal(menutable.textContent, lang.enablesort+lang.reversecurrent+lang.orderbyasc+lang.reversebyasc+lang.orderbynum+lang.reversebynum, '检查menu显示的字符'); + } + else { + equal(menutable.innerText.replace(/[\r\n\t\u200b\ufeff]/g, ''), lang.enablesort+lang.reversecurrent+lang.orderbyasc+lang.reversebyasc+lang.orderbynum+lang.reversebynum, '检查menu显示的字符'); + } + var reverseIndex = ua.getContextmenuIndexByName(menutable.childNodes,lang.reversecurrent); + ua.click(menutable.childNodes[reverseIndex]);//逆序 + ua.manualDeleteFillData(editor.body); + ua.checkSameHtml(editor.body.firstChild.firstChild.innerHTML,'&*3襄嫔{}2胤礼ackson4承祜Michael1康熙', '表格内容逆序-选区闭合'); + var tds = editor.body.getElementsByTagName('td'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(tds[0], tds[6]); + ut.setSelected(cellsRange); + range.setStart(tds[0], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + menutable = document.getElementsByClassName("edui-menu-body")[2]; + setTimeout(function () { + lang = editor.getLang("contextMenu"); + ua.click(menutable.childNodes[reverseIndex]); + ua.manualDeleteFillData(editor.body); + ua.checkSameHtml(editor.body.innerHTML,'
    ackson4承祜
    {}2胤礼
    &*3襄嫔
    Michael1康熙
    ', '表格内容逆序-选区不闭合'); + + setTimeout(function () { + document.getElementById('edui_fixedlayer').parentNode.removeChild(document.getElementById('edui_fixedlayer')); + te.dom.push(editor.container); + start(); + }, 20); + },20); + },20); +}); + +test('contextMenu 按ASCII字符排序', function () { + if(ua.browser.ie||ua.browser.gecko)return;////todo 1.2.6.1 #3316 + var editor = te.obj[0]; + var range = te.obj[1]; + stop(); + var lang = editor.getLang("contextMenu"); + editor.execCommand('cleardoc'); + var html = '
    Michael1康熙
    ackson4承祜
    {}2胤礼
    &*3襄嫔
    '; + editor.setContent(html); + range.setStart(editor.body.getElementsByTagName('td')[0], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + var menutable = document.getElementsByClassName("edui-menu-body")[2];//表格排序 + setTimeout(function () { + lang = editor.getLang("contextMenu"); + var AsciiIndex = ua.getContextmenuIndexByName(menutable.childNodes,lang.orderbyasc); + ua.click(menutable.childNodes[AsciiIndex]);//ASCII升 + ua.checkSameHtml(editor.body.innerHTML,'
    {}2胤礼
    &*3襄嫔
    ackson4承祜
    Michael1康熙
    ', '选区闭合'); + var tds = editor.body.getElementsByTagName('td'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(tds[0], tds[6]); + ut.setSelected(cellsRange); + range.setStart(tds[0], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + menutable = document.getElementsByClassName("edui-menu-body")[2]; + forTable = document.getElementsByClassName('edui-for-table'); + if (ua.browser.ie) { + ua.mouseenter(forTable[forTable.length - 1]); + } else { + ua.mouseover(forTable[forTable.length - 1]); + } + setTimeout(function () { + lang = editor.getLang("contextMenu"); + ua.click(menutable.childNodes[AsciiIndex+1]);//ASCII降 + ua.manualDeleteFillData(editor.body); + ua.checkSameHtml(editor.body.innerHTML,'
    ackson4承祜
    &*3襄嫔
    {}2胤礼
    Michael1康熙
    ', '表格内容逆序-选区不闭合'); + setTimeout(function () { + document.getElementById('edui_fixedlayer').parentNode.removeChild(document.getElementById('edui_fixedlayer')); + te.dom.push(editor.container); +// + start(); + }, 200); + }, 200); + }, 200); +}); + +test('contextMenu 按数值大小排序', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + stop(); + var lang = editor.getLang("contextMenu"); + editor.execCommand('cleardoc'); + var html = '
    Michael1康熙
    ackson4承祜
    {}2胤礼
    &*3襄嫔
    '; + editor.setContent(html); + range.setStart(editor.body.getElementsByTagName('td')[1], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + var menutable = document.getElementsByClassName("edui-menu-body")[2]; + setTimeout(function () { + lang = editor.getLang("contextMenu"); + var numIndex = ua.getContextmenuIndexByName(menutable.childNodes,lang.orderbynum); + ua.click(menutable.childNodes[numIndex]);//num升 + ua.manualDeleteFillData(editor.body); + ua.checkSameHtml(editor.body.innerHTML, '
    Michael1康熙
    {}2胤礼
    &*3襄嫔
    ackson4承祜
    ', '选区闭合'); + setTimeout(function () { + document.getElementById('edui_fixedlayer').parentNode.removeChild(document.getElementById('edui_fixedlayer')); + te.dom.push(editor.container); + start(); + }, 200); + }, 200); +}); +test('contextMenu trace 3384: 按数值大小排序', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + stop(); + var lang = editor.getLang("contextMenu"); + editor.execCommand('cleardoc'); + var html = '
    Michael1康熙
    ackson4承祜
    {}2胤礼
    &*3襄嫔
    '; + editor.setContent(html); + range.setStart(editor.body.getElementsByTagName('td')[1], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + var menutable = document.getElementsByClassName("edui-menu-body")[2]; + setTimeout(function () { + lang = editor.getLang("contextMenu"); + var numIndex = ua.getContextmenuIndexByName(menutable.childNodes,lang.orderbynum); + ua.click(menutable.childNodes[numIndex]);//num升 + ua.checkSameHtml(editor.body.innerHTML,'
    Michael1康熙
    {}2胤礼
    &*3襄嫔
    ackson4承祜
    ', '选区不闭合'); + + var tds = editor.body.getElementsByTagName('td'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(tds[1], tds[7]); + ut.setSelected(cellsRange); + range.setStart(tds[1], 0).collapse(true).select(); + ua.contextmenu(editor.body.firstChild); + menutable = document.getElementsByClassName("edui-menu-body")[2]; + forTable = document.getElementsByClassName('edui-for-table'); + + if (ua.browser.ie) { + ua.mouseenter(forTable[forTable.length - 1]); + } else { + ua.mouseover(forTable[forTable.length - 1]); + } + setTimeout(function () { + + lang = editor.getLang("contextMenu"); + ua.click(menutable.childNodes[numIndex+1]);//num降 + // todo 1.2.6.1 trace 3510 + if(!ua.browser.gecko){ + ua.checkSameHtml(editor.body.innerHTML,'
    &*3襄嫔
    {}2胤礼
    Michael1康熙
    ackson4承祜
    ', '选区不闭合'); + } + setTimeout(function () { + document.getElementById('edui_fixedlayer').parentNode.removeChild(document.getElementById('edui_fixedlayer')); + te.dom.push(editor.container); + + start(); + }, 200); + }, 200); + }, 200); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/template.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/template.js new file mode 100644 index 000000000..9c722d041 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/template.js @@ -0,0 +1,24 @@ +module( 'plugins.template' ); + +test( '模板', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello

    ' ); + range.setStart(editor.body.firstChild,0).collapse(true).select(); + editor.execCommand('template',{html:'

    欢迎使用UEditor!

    '}); + ua.manualDeleteFillData(editor.body); + equal(ua.getHTML(editor.body.firstChild),'

    欢迎使用ueditor!

    '); + if(!(ua.browser.gecko||ua.browser.ie>8)){ + if(ua.browser.webkit){ + ua.click(editor.body.firstChild); + equal(editor.selection.getRange().startContainer.firstChild.length,'12','检查选区'); + ua.keydown(editor.body.firstChild); + equal(editor.selection.getRange().startContainer.firstChild.length,'12','检查选区'); + }else{ + ua.click(editor.body.firstChild); + equal(editor.selection.getRange().startContainer.length,'12','检查选区'); + ua.keydown(editor.body.firstChild); + equal(editor.selection.getRange().startContainer.length,'12','检查选区'); + } + } +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/time.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/time.js new file mode 100644 index 000000000..81b6225ee --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/time.js @@ -0,0 +1,76 @@ +module( 'plugins.time' ); + +test( '插入时间和日期', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + editor.setContent( '


    ' ); + range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); + var date = new Date(); + var h = date.getHours(); + h = (h < 10) ? ('0' + h) : h; + var min = date.getMinutes(); + min = (min < 10) ? ('0' + min) : min; + var sec = date.getSeconds(); + sec = (sec < 10) ? ('0' + sec) : sec; + editor.execCommand( 'time' ); + ua.manualDeleteFillData( editor.body ); + equal( ua.getChildHTML( body.firstChild ), h + ':' + min + ':' + sec); + range.selectNode( body.firstChild.firstChild ).select(); + editor.execCommand( 'time','hh.ii.ss' ); + ua.manualDeleteFillData( editor.body ); + equal( ua.getChildHTML( body.firstChild ), h + '.' + min + '.' + sec); + + range.selectNode( body.firstChild.firstChild ).select(); + var year = date.getFullYear(); + var month = date.getMonth() + 1; + month = (month < 10) ? ('0' + month) : month; + var date = date.getDate(); + date = (date < 10) ? ('0' + date) : date; + editor.execCommand( 'date' ); + ua.manualDeleteFillData( editor.body ); + equal( ua.getChildHTML( body.firstChild ), year + '-' + month + '-' + date); + range.selectNode( body.firstChild.firstChild ).select(); + editor.execCommand( 'date','yyyy/mm/dd' ); + ua.manualDeleteFillData( editor.body ); + equal( ua.getChildHTML( body.firstChild ), year + '/' + month + '/' + date); +} ); + +test( '表格插入时间和日期', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var body = editor.body; + var br = UE.browser.ie ? "" : "
    "; + editor.setContent( '
    ' ); + var td = body.firstChild.getElementsByTagName( 'td' ); + range.setStart( td[0], 0 ).collapse( 1 ).select(); + var date = new Date(); + var h = date.getHours(); + h = (h < 10) ? ('0' + h) : h; + var min = date.getMinutes(); + min = (min < 10) ? ('0' + min) : min; + var sec = date.getSeconds(); + sec = (sec < 10) ? ('0' + sec) : sec; + editor.execCommand( 'time' ); + ua.manualDeleteFillData(td[0]); + debugger + equal( td[0].innerHTML, h + ':' + min + ':' + sec+(ua.browser.ie==9||ua.browser.ie==10?' ':'')); + range.setStart( td[1], 0 ).collapse( 1 ).select(); + editor.execCommand( 'time','hh.ii.ss' ); + ua.manualDeleteFillData(td[1]); + equal( td[1].innerHTML, h + '.' + min + '.' + sec+(ua.browser.ie==9||ua.browser.ie==10?' ':'')); + /*选中一段内容插入日期*/ + range.setStart( td[2], 0 ).collapse( 1 ).select(); + var year = date.getFullYear(); + var month = date.getMonth() + 1; + month = (month < 10) ? ('0' + month) : month; + date = date.getDate(); + date = (date < 10) ? ('0' + date) : date; + editor.execCommand( 'date' ); + ua.manualDeleteFillData(td[2]); + equal( td[2].innerHTML, year + '-' + month + '-' + date+(ua.browser.ie==9||ua.browser.ie==10?' ':'')); + range.setStart( td[3], 0 ).collapse( 1 ).select(); + editor.execCommand( 'date','yyyy/mm/dd' ); + ua.manualDeleteFillData(td[3]); + equal( td[3].innerHTML, year + '/' + month + '/' + date+(ua.browser.ie==9||ua.browser.ie==10?' ':'')); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/tools.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/tools.js new file mode 100644 index 000000000..1d06be935 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/tools.js @@ -0,0 +1,59 @@ +/** + + */ +(function () { + function mySetup() { + for (var config in window.UEDITOR_CONFIG) { + if (typeof(window.UEDITOR_CONFIG[config]) == 'string') + window.UEDITOR_CONFIG[config] = window.UEDITOR_CONFIG[config].replace('_test/tools/br/', ''); + } + var div = document.body.appendChild(document.createElement('div')); + $(div).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); + var editor = new baidu.editor.Editor({'initialContent':'

    欢迎使用ueditor

    ', 'autoFloatEnabled':false,webAppKey:'Qr0M9yTEoLIiUSXXQTtq7yFt'}); + var ue = new UE.ui.Editor({'UEDITOR_HOME_URL':'../../../', 'autoFloatEnabled':true,webAppKey:'Qr0M9yTEoLIiUSXXQTtq7yFt'}); + editor.render(div); + editor.ready(function () { + var range = new baidu.editor.dom.Range(editor.document); + te.dom.push(div); + te.obj.push(editor); + te.obj.push(range); + te.obj.push(ue); + QUnit.readyFlag =1; + }); + stop(); + QUnit.readyFlag =0; + document.getElementsByClassName = function (eleClassName) { + var getEleClass = [];//定义一个数组 + var myclass = new RegExp("\\b" + eleClassName + "\\b");//创建一个正则表达式对像 + var elem = this.getElementsByTagName("*");//获取文档里所有的元素 + for (var h = 0; h < elem.length; h++) { + var classes = elem[h].className;//获取class对像 + if (myclass.test(classes)) getEleClass.push(elem[h]);//正则比较,取到想要的CLASS对像 + } + return getEleClass;//返回数组 + } + } + + var _d = function () { + if (te) { + if (te.dom && te.dom.length) { + for (var i = 0; i < te.dom.length; i++) { + if (te.dom[i] && te.dom[i].parentNode) + te.dom[i].parentNode.removeChild(te.dom[i]); + } + + } + } + te.dom = []; + te.obj = []; + } + var s = QUnit.testStart, d = QUnit.testDone; + QUnit.testStart = function () { + s.apply(this, arguments); + mySetup(); + }; + QUnit.testDone = function () { + _d(); + d.apply(this, arguments); + } +})(); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/ueditor.config.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/ueditor.config.js new file mode 100644 index 000000000..1568c9b97 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/ueditor.config.js @@ -0,0 +1,20 @@ +module( ".path" ); + +/*trace 3683*/ +test( '路径查找测试', function () { + equal( UE.getUEBasePath( 'http://www.baidu.com/', './ueditor.config.js' ), 'http://www.baidu.com/', 'WEB路径-当前目录下' ); + equal( UE.getUEBasePath( 'http://www.baidu.com/abc/def/', '../ueditor.config.js' ), 'http://www.baidu.com/abc/', 'WEB路径-父目录1' ); + equal( UE.getUEBasePath( 'http://www.baidu.com/abc/def', '../ueditor.config.js' ), 'http://www.baidu.com/', 'WEB路径-父目录2' ); + + equal( UE.getUEBasePath( 'file:///home/hn/a/ueditor/_examples/completeDemo.html', './ueditor.config.js' ), 'file:///home/hn/a/ueditor/_examples/', '本地路径-linux-当前目录1' ); + equal( UE.getUEBasePath( 'file:///home/hn/a/ueditor/_examples/completeDemo.html', 'ueditor.config.js' ), 'file:///home/hn/a/ueditor/_examples/', '本地路径-linux-当前目录2' ); + equal( UE.getUEBasePath( 'file:///home/hn/a/ueditor/_examples/completeDemo.html', '../ueditor.config.js' ), 'file:///home/hn/a/ueditor/', '本地路径-linux-父目录1' ); + equal( UE.getUEBasePath( 'file:///home/hn/a/ueditor/_examples/completeDemo.html', './../ueditor.config.js' ), 'file:///home/hn/a/ueditor/', '本地路径-linux-父目录2' ); + + equal( UE.getUEBasePath( 'file://C:\\webroot\\ueditor\\_examples\\completeDemo.html', './ueditor.config.js' ), 'file://C:/webroot/ueditor/_examples/', '本地路径-windows-当前目录1' ); + equal( UE.getUEBasePath( 'file://C:\\webroot\\ueditor\\_examples\\completeDemo.html', 'ueditor.config.js' ), 'file://C:/webroot/ueditor/_examples/', '本地路径-windows-当前目录2' ); + equal( UE.getUEBasePath( 'file://C:\\webroot\\ueditor\\_examples\\completeDemo.html', '../ueditor.config.js' ), 'file://C:/webroot/ueditor/', '本地路径-windows-父目录1' ); + equal( UE.getUEBasePath( 'file://C:\\webroot\\ueditor\\_examples\\completeDemo.html', './../ueditor.config.js' ), 'file://C:/webroot/ueditor/', '本地路径-windows-父目录2' ); + + equal( UE.getUEBasePath( 'http://www.baidu.com/ueditor/completedemo.html', '/ueditorphp/ueditor.config.js' ), 'http://www.baidu.com/ueditorphp/', 'WEB路径-当前目录下' ); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/undo.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/undo.js new file mode 100644 index 000000000..d83292298 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/undo.js @@ -0,0 +1,496 @@ +module("plugins.undo"); + +//test('', function () { +// stop() +//}); +/*trace 856*/ +test('trace 856 输入文本后撤销按钮不亮', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + ua.keydown(editor.body); + range.insertNode(editor.document.createTextNode('hello')); + ua.keydown(editor.body); + setTimeout(function () { + equal(editor.queryCommandState('undo'), 0, '模拟输入文本后撤销按钮应当高亮'); + start(); + }, 500); + stop(); +}); + +/*trace 583,1726*/ +test('trace 583,1726 插入表格、表情,撤销', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 2, numRows: 2}); + editor.execCommand('insertimage', {src: 'http://img.baidu.com/hi/jx2/j_0001.gif', width: 50, height: 50}); + editor.execCommand('undo'); + editor.execCommand('undo'); + editor.execCommand('undo');//需要3次undo,已经和RD确认过,暂时不改 + ua.manualDeleteFillData(editor.body); + equal(editor.getContent().toLowerCase(), '', '插入表格、表情,撤销'); +}); + +/*trace 595*/ +test('trace 595 撤销合并单元格后再合并单元格', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 3, numRows: 3}); + var tds = editor.body.firstChild.getElementsByTagName('td'); + for (var i = 0; i < 5; i++) { + tds[i].innerHTML = 'hello'; + } + //合并单元格 + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[1]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + + editor.execCommand('mergecells'); + ua.manualDeleteFillData(editor.body); + var tds = editor.body.getElementsByTagName('td'); + equal(tds.length, 6, '单元格数'); + equal(trs[0].cells[0].colSpan, 2, '合并--[0][0]单元格colspan'); + equal(trs[0].cells[0].rowSpan, 2, '合并--[0][0]单元格rowspan'); + equal(trs[0].cells[0].innerHTML.toLowerCase(), 'hello
    hello
    hello
    hello', '内容复制正确'); + + //撤销合并单元格的操作 + editor.execCommand('undo'); + ua.manualDeleteFillData(editor.body); + ok(tds[0].colSpan == 1 && tds[0].rowSpan == 1 && tds.length == 9, '撤销后,单元格回复成多个'); + ok(tds[0].innerHTML.toLowerCase() == 'hello' && tds[1].innerHTML.toLowerCase() == 'hello' && tds[3].innerHTML.toLowerCase() == 'hello' && tds[4].innerHTML.toLowerCase() == 'hello', '内容复制正确'); + + //再次合并单元格 + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[1]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('mergecells'); + ua.manualDeleteFillData(editor.body); + tds = editor.body.firstChild.getElementsByTagName('td'); + ok(tds[0].colSpan == 2 && tds[0].rowSpan == 2 && tds.length == 6, '再次合并,多个单元格合并成一个'); + equal(tds[0].innerHTML.toLowerCase(), 'hello
    hello
    hello
    hello', '内容复制正确'); + start(); + }, 50); + }, 50); + stop(); +}); + +/*trace 599*/ +test('trace 599 插入表格、表情、超链接、表情,撤销2次', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 2, numRows: 2}); //插入表格 + range.setStart(editor.body.lastChild, 0).collapse(true).select(); + editor.execCommand('insertimage', {src: 'http://img.baidu.com/hi/jx2/j_0001.gif', width: 50, height: 50}); //插入表情 + range.setStartAfter(editor.body.lastChild).collapse(true).select(); + editor.execCommand('link', {href: 'http://www.baidu.com/'}); //插入超链接 + range.setStartAfter(editor.body.lastChild).collapse(true).select(); + editor.execCommand('insertimage', {src: 'http://img.baidu.com/hi/jx2/j_0001.gif', width: 50, height: 50}); //插入表情 + + editor.execCommand('Undo'); + editor.execCommand('Undo'); + ua.manualDeleteFillData(editor.body); + equal(editor.body.childNodes.length, 2, '撤销2次后只剩表格、表情'); + var tag = editor.body.childNodes[0].firstChild.tagName.toLowerCase(); + ok(tag == 'table' || tag == 'tbody', '表格'); + equal(editor.body.childNodes[1].firstChild.tagName.toLowerCase(), 'img', '表情'); +}); + +/*trace 617*/ +test('trace 617 插入文本、分割线、文本,撤销2次,撤销掉分割线', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + editor.setContent('

    '); + + //输入文本 + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + ua.keydown(editor.body); + range.insertNode(editor.document.createTextNode('hello')); + if (!ua.browser.ie) + ua.compositionstart(editor.body); + ua.keyup(editor.body); + //输入分割符 + range.setStartAfter(editor.body.lastChild).collapse(true).select(); + editor.execCommand('Horizontal'); + //输入文本 + range.setStartAfter(editor.body.lastChild).collapse(true).select(); + ua.keydown(editor.body); + range.insertNode(editor.document.createTextNode('hello')); + if (!ua.browser.ie) + ua.compositionend(editor.body); + ua.keyup(editor.body); + + editor.execCommand('Undo'); + editor.execCommand('Undo'); + equal(editor.body.getElementsByTagName('hr').length, 0, '分割线已删除'); + +}); + +/*trace 632*/ +test('trace 632 合并单元格后撤销再合并单元格不会丢字', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 4, numRows: 4}); + var tds = editor.body.firstChild.getElementsByTagName('td'); + for (var i = 0; i < 6; i++) { + tds[i].innerHTML = 'hello'; + } + //合并单元格 + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[1]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('mergecells'); + ua.manualDeleteFillData(editor.body); + tds = editor.body.firstChild.getElementsByTagName('td'); + equal(tds[0].innerHTML.toLowerCase(), 'hello
    hello
    hello
    hello', '合并单元格,内容复制正确'); + + //撤销合并单元格的操作,再次合并单元格 + editor.execCommand('Undo'); + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[1].cells[1]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('mergecells'); + ua.manualDeleteFillData(editor.body); + tds = editor.body.firstChild.getElementsByTagName('td'); + equal(tds[0].innerHTML.toLowerCase(), 'hello
    hello
    hello
    hello', '撤销后再次合并单元格,内容复制正确'); + start(); + }, 50); + }, 50); + stop(); +}); + +/*trace 675 这个trace用例中的操作已经设为非法*/ +/*trace 685*/ +test('trace 685 合并单元格后,删除行,再撤销,再删除行', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 4, numRows: 4}); + + //选择第一行的4格单元格,合并 + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[0].cells[3]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + var tds = editor.body.getElementsByTagName('td'); + editor.execCommand('mergecells'); + ok(tds[0].colSpan == 4 && tds[0].rowSpan == 1, '第一行的4个单元格合并成一个'); + + //选择第2,3,4行的第1个单元格,合并 + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[1].cells[0], trs[3].cells[0]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + var tds = editor.body.getElementsByTagName('td'); + editor.execCommand('mergecells'); + ok(tds[1].colSpan == 1 && tds[1].rowSpan == 3, '第2,3,4行的第一个单元格合并成一个'); + + //单击第二步合并的单元格,点击删除行 + range.setStart(tds[4], 0).collapse(true).select(); + editor.execCommand('deleterow'); + equal(editor.body.firstChild.getElementsByTagName('tr').length, 3, '点击删除行,表格剩三行'); + //撤销 + editor.execCommand('undo'); + equal(editor.body.firstChild.getElementsByTagName('tr').length, 4, '撤销后,表格恢复成4行'); + //再次点击删除行 + range.setStart(tds[4], 0).collapse(true).select(); + editor.execCommand('deleterow'); + equal(editor.body.firstChild.getElementsByTagName('tr').length, 3, '撤销后,再点击删除行,表格剩三行'); + start(); + }, 50); + }, 50); + stop(); +}); + +/*trace 711 这个要中文输入法再模拟键盘输入,貌似不能写???*/ +/*trace 718*/ +test('trace 718 合并单元格后,删除列,再撤销,再删除列', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 4, numRows: 4}); + + //选择中间的4格单元格,合并 + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[1].cells[1], trs[2].cells[2]); + ut.setSelected(cellsRange); + range.setStart(trs[1].cells[1], 0).collapse(true).select(); + var tds = editor.body.firstChild.getElementsByTagName('td'); + editor.execCommand('mergecells'); + ok(tds[5].colSpan == 2 && tds[5].rowSpan == 2, '对一个4*4的表格,选择中间的4格单元格,合并成一个'); + //光标定位在合并后的大单元格中,点击删除列按钮 + range.setStart(tds[5], 0).collapse(true).select(); + editor.execCommand('deletecol'); + equal(editor.body.firstChild.getElementsByTagName('tr')[0].childNodes.length, 3, '点击删除列,表格剩三列'); + //撤销 + editor.execCommand('undo'); + equal(editor.body.firstChild.getElementsByTagName('tr')[0].childNodes.length, 4, '撤销后,表格剩四列'); + //再次点击删除列按钮 + //TODO 1.2.6 + if (!ua.browser.gecko && !ua.browser.ie) { + range.setStart(tds[5], 0).collapse(true).select(); + editor.execCommand('deletecol'); + equal(editor.body.firstChild.getElementsByTagName('tr')[0].childNodes.length, 3, '再次点击删除列,表格剩三列'); + } + equal(editor.body.firstChild.getElementsByTagName('tr').length, 4, '表格依然有4行'); + start(); + }, 50); + stop(); +}); + +/*trace 722 需要中文输入法*/ +/*trace 743*/ +test('trace 743 合并单元格后,删除列,再撤销', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable', {numCols: 4, numRows: 4}); + + //第一行的4格单元格,合并 + setTimeout(function () { + var trs = editor.body.firstChild.getElementsByTagName('tr'); + var ut = editor.getUETable(editor.body.firstChild); + var cellsRange = ut.getCellsRange(trs[0].cells[0], trs[0].cells[3]); + ut.setSelected(cellsRange); + range.setStart(trs[0].cells[0], 0).collapse(true).select(); + editor.execCommand('mergecells'); + var tds = editor.body.firstChild.getElementsByTagName('td'); + ok(tds[0].colSpan == 4 && tds[0].rowSpan == 1 && tds.length == 13, '对一个4*4的表格,选择第一行的4格单元格,合并成一个'); + //点击删除列按钮 + editor.execCommand('deletecol'); + equal(editor.body.firstChild.getElementsByTagName('tr')[1].childNodes.length, 3, '点击删除列,表格剩3列'); + //撤销 + editor.execCommand('undo'); + equal(editor.body.firstChild.getElementsByTagName('tr')[1].childNodes.length, 4, '撤销后,表格恢复成4列'); + equal(editor.body.firstChild.getElementsByTagName('tr').length, 4, '表格依然有4行'); + start(); + }, 50); + stop(); +}); + +/*trace 808 需要观察光标延迟,这个问题已经被标为不修*/ +/*trace 855 这个用例描述有问题,而且可以跟trace 584合成一个*/ +/*trace 873*/ +//test( 'trace 873 光标不在编辑器中时替换一个文本后按撤销', function () { +// if(ua.browser.opera) +// return; +// var editor = te.obj[0]; +// editor.setContent('欢迎使用ueditor'); +// editor.execCommand( 'searchreplace', {searchStr:'欢迎', replaceStr:'welcom'} ); +// ua.manualDeleteFillData(editor.body); +// equal( editor.body.firstChild.innerHTML, 'welcom使用ueditor', '查找替换' ); +// editor.execCommand( 'Undo' ); +// ua.manualDeleteFillData( editor.body ); +// equal( editor.body.firstChild.innerHTML, '欢迎使用ueditor', '撤销' ); +//} ); + +/*trace 942*/ +test('trace 942 用格式刷后撤销', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + var flag = true; + stop(); + expect(1); + editor.setContent('

    hello

    hello

    '); + + range.setStart(editor.body.firstChild.firstChild.firstChild, 2).setEnd(editor.body.firstChild.firstChild.firstChild, 4).select(); + editor.addListener('mouseup', function () { + ua.manualDeleteFillData(editor.body); + //从浏览器复制了不可见的空文本 + equal(editor.body.lastChild.firstChild.innerHTML.toLowerCase(), 'hello'); + + }); + editor.execCommand('formatmatch'); + range.setStart(editor.body.lastChild.firstChild.firstChild, 1).collapse(true).select(); + ua.mouseup(editor.body); + setTimeout(function () { + start(); + }, 100); +}); + +test('undo--redo', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + editor.focus(); + editor.execCommand('anchor', 'hello'); + editor.undoManger.undo(); + var spase = ua.browser.ie ? ' ' : '
    '; + equal(ua.getChildHTML(editor.body), '

    ' + spase + '

    ', ''); + editor.undoManger.redo(); + ua.manualDeleteFillData(editor.body); +// var cs=editor.body.firstChild.firstChild.getAttribute('class'); +// var an=editor.body.firstChild.firstChild.getAttribute('anchorname'); +// equal(cs,'anchorclass','锚点class'); +// equal(an,'hello','锚点name'); +// var br = (ua.browser.ie) ? '' : '
    '; + if (ua.browser.ie) + equal(ua.getChildHTML(editor.body), '

    ' + spase + '

    ', ''); + else + equal(ua.getChildHTML(editor.body), '

    ' + spase + '

    ', ''); +}); +test('reset,index', function () { + var editor = te.obj[0]; + editor.setContent('

    '); + editor.focus(); + editor.execCommand('anchor', 'hello'); + var listLength = editor.undoManger.list.length; + ok(listLength > 0, '检查undoManger.list'); + equal(editor.undoManger.index, 1, '检查undoManger.index'); + editor.undoManger.undo(); + equal(editor.undoManger.list.length, listLength, 'undo操作,undoManger.list不变'); + equal(editor.undoManger.index, 0, 'undo操作,undoManger.index-1'); + var spase = ua.browser.ie ? ' ' : '
    '; + equal(ua.getChildHTML(editor.body), '

    ' + spase + '

    ', '检查内容'); + editor.reset(); + equal(editor.undoManger.list.length, 0, 'reset,undoManger.list清空'); + equal(editor.undoManger.index, 0, 'reset,undoManger.index清空'); + editor.undoManger.redo(); + ua.manualDeleteFillData(editor.body); + var spase = ua.browser.ie ? ' ' : '
    '; + equal(ua.getChildHTML(editor.body), '

    ' + spase + '

    ', '检查内容'); + +}); +/*trace 1068 格式刷图片*/ +test('trace 1068 默认样式的图片刷左浮动图片,撤销,左浮动图片刷默认样式的图片', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + var num = 0; + + var body = editor.body; + editor.setContent('


    '); + range.setStart(body.firstChild, 0).collapse(1).select(); + editor.execCommand('insertimage', {src: 'http://img.baidu.com/hi/jx2/j_0001.gif', width: 50, height: 51}); + range.selectNode(editor.body.getElementsByTagName('img')[0]).select(); + editor.execCommand('imagefloat', 'none'); + range.setStart(body.firstChild, 0).collapse(1).select(); + editor.execCommand('insertimage', {src: 'http://img.baidu.com/hi/jx2/j_0002.gif', width: 50, height: 51}); + range.selectNode(editor.body.getElementsByTagName('img')[0]).select(); + editor.execCommand('imagefloat', 'left'); + // equal(ua.getFloatStyle(body.getElementsByTagName( 'img' )[0]), "left", '左浮动' ); + // equal(ua.getFloatStyle(body.getElementsByTagName( 'img' )[1]), "none", '默认' ); + range.selectNode(body.getElementsByTagName('img')[1]).select(); + editor.addListener('mouseup', function () { + equal(editor.queryCommandState('formatmatch'), 0, '刷后状态为0'); + if (num == 1) { + equal(ua.getFloatStyle(body.getElementsByTagName('img')[0]), "none", '默认刷左浮动'); + editor.execCommand('Undo'); + equal(ua.getFloatStyle(body.getElementsByTagName('img')[0]), "left", '撤销后,左浮动还原'); + range.selectNode(body.getElementsByTagName('img')[0]).select(); + editor.execCommand('formatmatch'); + range.selectNode(body.getElementsByTagName('img')[1]).select(); + num = 2; + ua.mouseup(editor.body); + } + else if (num == 2) { + if (!ua.browser.opera) { + equal(ua.getFloatStyle(body.getElementsByTagName('img')[1]), 'left', '左浮动刷默认'); + } + setTimeout(function () { + start(); + }, 100); + } + }); + editor.execCommand('formatmatch'); + range.selectNode(body.getElementsByTagName('img')[0]).select(); + num = 1; + ua.mouseup(body.getElementsByTagName('img')[0]); + stop(); +}); + +//test( +// 'undo', +// function() { +// var editor = new baidu.editor.Editor({ +// enterkey : 'br', +// initialContent : 'test' +// }); +// editor.render(te.dom[0]); +// var domUtils = baidu.editor.dom.domUtils, dtd = baidu.editor.dom.dtd, range = new baidu.editor.dom.Range( +// editor.document); +// editor.setContent('xxxx

    xxxx

    '); +// range.selectNodeContents(editor.document.body).select(); +// editor.execCommand('bold'); +// editor.execCommand('Undo'); +// equals(getHTML(editor.document.body), 'xxxx

    xxxx

    '); +// editor.execCommand('redo'); +// equals(getHTML(editor.document.body), 'xxxx

    xxxx

    '); +// ok(!editor.hasRedo); +// +// editor.execCommand('Undo'); +// editor.execCommand('Undo'); +// equals(getHTML(editor.document.body), 'test'); +// }); + +test('ctrl+z/y', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + + var body = editor.body; + editor.setContent('

    没有加粗的文本

    '); + range.selectNode(body.firstChild).select(); + var p = body.firstChild; + setTimeout(function () { + ua.keydown(editor.body, {'keyCode': 66, 'ctrlKey': true}); + setTimeout(function () { + equal(ua.getChildHTML(p), '没有加粗的文本'); + ua.keydown(editor.body, {'keyCode': 90, 'ctrlKey': true}); + setTimeout(function () { + editor.focus(); + equal(ua.getChildHTML(body.firstChild), '没有加粗的文本'); + ua.keydown(editor.body, {'keyCode': 89, 'ctrlKey': true}); + editor.focus(); + setTimeout(function () { + equal(ua.getChildHTML(body.firstChild), '没有加粗的文本'); + start(); + }, 100); + }, 100); + }, 150); + }, 100); + stop(); +}); + +/*trace 3209 格式刷图片*/ +test('trace 3209 插入表格,undo redo', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent('

    '); + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('inserttable'); + editor.execCommand('undo'); + equal(editor.getContent().toLowerCase(), '', '插入表格,撤销'); + editor.execCommand('redo'); + ua.manualDeleteFillData(editor.body); + equal(editor.body.firstChild.tagName.toLowerCase(), 'table', '插入表格,撤销重做'); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/video.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/video.js new file mode 100644 index 000000000..d4ae6cd11 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/video.js @@ -0,0 +1,64 @@ +/** + * Created with JetBrains PhpStorm. + * User: Administrator + * Date: 13-5-15 + * Time: 下午7:15 + * To change this template use File | Settings | File Templates. + */ +module( 'plugins.video' ); + +test( '插入优酷视频', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent( '

    hello

    ' ); + range.setStart(editor.body.firstChild,0).collapse(true).select(); + var videoObject ={url: "http://player.youku.com/player.php/Type/Folder/Fid/19275705/Ob/1/sid/XNTU3Mjk4NzQ4/v.swf", width: "500", height: "400", align: "center"} + editor.execCommand( 'insertvideo',videoObject); + stop(); + setTimeout(function(){ + var img = editor.body.getElementsByTagName('img'); + equal(img.length,1,'插入img'); + equal(img[0].width,"500"); + equal(img[0].height,"400"); + equal(img[0].src,editor.options.UEDITOR_HOME_URL+'themes/default/images/spacer.gif'); + if(ua.browser.gecko||ua.browser.ie>8){ + ok(img[0].style.background.indexOf('url(\"'+editor.options.UEDITOR_HOME_URL+'themes/default/images/videologo.gif\")') > -1, '占位符背景图是否正常'); + } + else + { + ok(img[0].style.background.indexOf("url("+editor.options.UEDITOR_HOME_URL+"themes/default/images/videologo.gif)") > -1, '占位符背景图是否正常'); + } + var html = editor.getContent(); + ok(html.toLowerCase().indexOf('hello

    ' ); + range.setStart(editor.body.firstChild,0).collapse(true).select(); + var videoObject ={url: "http://video-js.zencoder.com/oceans-clip.mp4", width: "500", height: "400", align: "center"} + editor.execCommand( 'insertvideo',videoObject,'upload'); + stop(); + setTimeout(function(){ + var img = editor.body.getElementsByTagName('img'); + equal(img.length,1,'插入img'); + equal(img[0].width,"500"); + equal(img[0].height,"400"); + ok(img[0].className && img[0].className.indexOf('edui-upload-video') != -1, 'okey:有edui-upload-video的class标记'); + equal(img[0].src,editor.options.UEDITOR_HOME_URL+'themes/default/images/spacer.gif'); + if(ua.browser.gecko||ua.browser.ie>8){ + ok(img[0].style.background.indexOf('url(\"'+editor.options.UEDITOR_HOME_URL+'themes/default/images/videologo.gif\")') > -1, '占位符背景图是否正常'); + } + else + { + ok(img[0].style.background.indexOf("url("+editor.options.UEDITOR_HOME_URL+"themes/default/images/videologo.gif)") > -1, '占位符背景图是否正常'); + } + + var html = editor.getContent(); + ok(html.toLowerCase().indexOf('hello

    '); + setTimeout(function () { + range.setStart(editor.body.firstChild, 0).collapse(true).select(); + editor.execCommand('selectall'); + editor.execCommand('cleardoc'); + equal(editor.getContentLength(true), 0, '插入成功'); + + start(); + }, 50); + stop(); +}); + +test('空格', function () { + var editor = te.obj[0]; + var range = te.obj[1]; + editor.setContent(' \ufeff\u200B\t\t \n\n\t\n\b\t\n\b\u200B\t\t\n\n '); + if (ua.browser.ie) + equal(editor.getContentLength(true), 23, '清空后编辑器中23个空格'); + else + equal(editor.getContentLength(true), 22, '清空后编辑器中22个空格'); +}); + +test(' trace 3744 超出最大', function () { + + var div = document.body.appendChild(document.createElement('div')); + div.id = 'ue'; + var editor = UE.getEditor('ue', {'UEDITOR_HOME_URL': '../../../', 'wordCount': true, 'maximumWords': 10,'initialContent':'','autoFloatEnabled': false}); + editor.ready(function () { + + expect(2); + editor.addListener("wordcountoverflow", function () { + ok(true, "超出最大"); + setTimeout(function () { + UE.delEditor('ue'); + start(); + }, 500); + }); + setTimeout(function () { + editor.setContent('hello hello hello'); + equal(editor.getContentLength(true), 17, '仅统计字数') + + }, 50); + }); + stop(); +}); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/wordimage.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/wordimage.js new file mode 100644 index 000000000..8cf48511a --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/plugins/wordimage.js @@ -0,0 +1,57 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-3-26 + * Time: 下午3:05 + * To change this template use File | Settings | File Templates. + */ +module('plugins.wordimage'); + +test('检查取得word_img的url地址', function () { + var editor = te.obj[0]; + editor.setContent('



    '); + stop(); + setTimeout(function () { + + editor.execCommand('wordimage', 'word_img'); + equal(editor.body.getElementsByTagName('img')[0].getAttribute('word_img'), "file:///C:DOCUME~1DONGYA~1LOCALS~1Tempmsohtmlclip1clip_image001.gif", '检查url地址'); + editor.setContent('


    '); + setTimeout(function () { + editor.execCommand('wordimage', 'word_img'); +// equal(editor.word_img.length, '2', '有2个wordimg'); + equal(editor.body.getElementsByTagName('img')[0].getAttribute('word_img'), "file:///C:\DOCUME~1\DONGYA~1\LOCALS~1\Temp\msohtmlclip1\01\clip_image001.jpg", '检查 第一个url地址'); + equal(editor.body.getElementsByTagName('img')[1].getAttribute('word_img'), "file:///C:\DOCUME~1\DONGYA~1\LOCALS~1\Temp\msohtmlclip1\01\clip_image001.gif", '检查 第二个url地址'); + equal(editor.queryCommandState('wordimage'), '1', 'queryCommandState'); + start(); + }, 50); + }, 50); +}); + +test('多实例编辑器检查取得word_img的url地址', function () { + var div1 = document.createElement('div'); + var div2 = document.createElement('div'); + document.body.appendChild(div1); + document.body.appendChild(div2); + var editor1 = new UE.Editor({'initialContent':'



    ','autoFloatEnabled':false}); + var editor2 = new UE.Editor({'initialContent':'


    ', 'autoFloatEnabled':false}); + stop(); + setTimeout(function () { + editor1.render(div1); + editor1.ready(function () { + editor2.render(div2); + editor2.ready(function () { + editor1.focus(); + editor1.execCommand('wordimage', 'word_img'); +// equal(editor1.word_img.length, '1', 'editor1有一个wordimg'); + equal(editor1.body.getElementsByTagName('img')[0].getAttribute('word_img'), "file:///C:DOCUME~1DONGYA~1LOCALS~1Tempmsohtmlclip1clip_image001.gif", '检查url地址'); + editor2.execCommand('wordimage', 'word_img'); +// equal(editor2.word_img.length, '2', 'editor2有2个wordimg'); + equal(editor2.body.getElementsByTagName('img')[0].getAttribute('word_img'), "file:///C:\DOCUME~1\DONGYA~1\LOCALS~1\Temp\msohtmlclip1\01\clip_image001.jpg", '检查 第一个url地址'); + equal(editor2.body.getElementsByTagName('img')[1].getAttribute('word_img'), "file:///C:\DOCUME~1\DONGYA~1\LOCALS~1\Temp\msohtmlclip1\01\clip_image001.gif", '检查 第二个url地址'); + equal(editor1.queryCommandState('wordimage'), '1', 'queryCommandState'); + equal(editor2.queryCommandState('wordimage'), '1', 'queryCommandState'); + start(); + }); + }); + }); +}); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/qunit/jquery-1.5.1.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/qunit/jquery-1.5.1.js new file mode 100644 index 000000000..fa52d75b8 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/qunit/jquery-1.5.1.js @@ -0,0 +1,8316 @@ +/*! + * jQuery JavaScript Library v1.5.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Wed Feb 23 13:55:29 2011 -0500 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for digits + rdigit = /\d/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // Has the ready events already been bound? + readyBound = false, + + // The deferred used on DOM ready + readyList, + + // Promise methods + promiseMethods = "then done fail isResolved isRejected promise".split( " " ), + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = "body"; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.5.1", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.done( fn ); + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + // A third-party is pushing the ready event forwards + if ( wait === true ) { + jQuery.readyWait--; + } + + // Make sure that the DOM is not already loaded + if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).unbind( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyBound ) { + return; + } + + readyBound = true; + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent("onreadystatechange", DOMContentLoaded); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test(data.replace(rvalidescape, "@") + .replace(rvalidtokens, "]") + .replace(rvalidbraces, "")) ) { + + // Try to use the native JSON parser first + return window.JSON && window.JSON.parse ? + window.JSON.parse( data ) : + (new Function("return " + data))(); + + } else { + jQuery.error( "Invalid JSON: " + data ); + } + }, + + // Cross-browser xml parsing + // (xml & tmp used internally) + parseXML: function( data , xml , tmp ) { + + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + + tmp = xml.documentElement; + + if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { + jQuery.error( "Invalid XML: " + data ); + } + + return xml; + }, + + noop: function() {}, + + // Evalulates a script in a global context + globalEval: function( data ) { + if ( data && rnotwhite.test(data) ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement, + script = document.createElement( "script" ); + + if ( jQuery.support.scriptEval() ) { + script.appendChild( document.createTextNode( data ) ); + } else { + script.text = data; + } + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction(object); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type(array); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var ret = [], value; + + // Go through the array, translating each of the items to their + // new value (or values). + for ( var i = 0, length = elems.length; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + proxy: function( fn, proxy, thisObject ) { + if ( arguments.length === 2 ) { + if ( typeof proxy === "string" ) { + thisObject = fn; + fn = thisObject[ proxy ]; + proxy = undefined; + + } else if ( proxy && !jQuery.isFunction( proxy ) ) { + thisObject = proxy; + proxy = undefined; + } + } + + if ( !proxy && fn ) { + proxy = function() { + return fn.apply( thisObject || this, arguments ); + }; + } + + // Set the guid of unique handler to the same of original handler, so it can be removed + if ( fn ) { + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + } + + // So proxy can be declared as an argument + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can be optionally by executed if its a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Create a simple deferred (one callbacks list) + _Deferred: function() { + var // callbacks list + callbacks = [], + // stored [ context , args ] + fired, + // to avoid firing when already doing so + firing, + // flag to know if the deferred has been cancelled + cancelled, + // the deferred itself + deferred = { + + // done( f1, f2, ...) + done: function() { + if ( !cancelled ) { + var args = arguments, + i, + length, + elem, + type, + _fired; + if ( fired ) { + _fired = fired; + fired = 0; + } + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + deferred.done.apply( deferred, elem ); + } else if ( type === "function" ) { + callbacks.push( elem ); + } + } + if ( _fired ) { + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); + } + } + return this; + }, + + // resolve with given context and args + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { + firing = 1; + try { + while( callbacks[ 0 ] ) { + callbacks.shift().apply( context, args ); + } + } + // We have to add a catch block for + // IE prior to 8 or else the finally + // block will never get executed + catch (e) { + throw e; + } + finally { + fired = [ context, args ]; + firing = 0; + } + } + return this; + }, + + // resolve with this as context and given arguments + resolve: function() { + deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this, arguments ); + return this; + }, + + // Has this deferred been resolved? + isResolved: function() { + return !!( firing || fired ); + }, + + // Cancel + cancel: function() { + cancelled = 1; + callbacks = []; + return this; + } + }; + + return deferred; + }, + + // Full fledged deferred (two callbacks list) + Deferred: function( func ) { + var deferred = jQuery._Deferred(), + failDeferred = jQuery._Deferred(), + promise; + // Add errorDeferred methods, then and promise + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ); + return this; + }, + fail: failDeferred.done, + rejectWith: failDeferred.resolveWith, + reject: failDeferred.resolve, + isRejected: failDeferred.isResolved, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + if ( promise ) { + return promise; + } + promise = obj = {}; + } + var i = promiseMethods.length; + while( i-- ) { + obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; + } + return obj; + } + } ); + // Make sure only one callback list will be used + deferred.done( failDeferred.cancel ).fail( deferred.cancel ); + // Unexpose cancel + delete deferred.cancel; + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + return deferred; + }, + + // Deferred helper + when: function( object ) { + var lastIndex = arguments.length, + deferred = lastIndex <= 1 && object && jQuery.isFunction( object.promise ) ? + object : + jQuery.Deferred(), + promise = deferred.promise(); + + if ( lastIndex > 1 ) { + var array = slice.call( arguments, 0 ), + count = lastIndex, + iCallback = function( index ) { + return function( value ) { + array[ index ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value; + if ( !( --count ) ) { + deferred.resolveWith( promise, array ); + } + }; + }; + while( ( lastIndex-- ) ) { + object = array[ lastIndex ]; + if ( object && jQuery.isFunction( object.promise ) ) { + object.promise().then( iCallback(lastIndex), deferred.reject ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( promise, array ); + } + } else if ( deferred !== object ) { + deferred.resolve( object ); + } + return promise; + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySubclass( selector, context ) { + return new jQuerySubclass.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySubclass, this ); + jQuerySubclass.superclass = this; + jQuerySubclass.fn = jQuerySubclass.prototype = this(); + jQuerySubclass.fn.constructor = jQuerySubclass; + jQuerySubclass.subclass = this.subclass; + jQuerySubclass.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySubclass) ) { + context = jQuerySubclass(context); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass ); + }; + jQuerySubclass.fn.init.prototype = jQuerySubclass.fn; + var rootjQuerySubclass = jQuerySubclass(document); + return jQuerySubclass; + }, + + browser: {} +}); + +// Create readyList deferred +readyList = jQuery._Deferred(); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +if ( indexOf ) { + jQuery.inArray = function( elem, array ) { + return indexOf.call( array, elem ); + }; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +// Expose jQuery to the global object +return jQuery; + +})(); + + +(function() { + + jQuery.support = {}; + + var div = document.createElement("div"); + + div.style.display = "none"; + div.innerHTML = "
    a"; + + var all = div.getElementsByTagName("*"), + a = div.getElementsByTagName("a")[0], + select = document.createElement("select"), + opt = select.appendChild( document.createElement("option") ), + input = div.getElementsByTagName("input")[0]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return; + } + + jQuery.support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: div.firstChild.nodeType === 3, + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText insted) + style: /red/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: a.getAttribute("href") === "/a", + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: input.value === "on", + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Will be defined later + deleteExpando: true, + optDisabled: false, + checkClone: false, + noCloneEvent: true, + noCloneChecked: true, + boxModel: null, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableHiddenOffsets: true + }; + + input.checked = true; + jQuery.support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as diabled) + select.disabled = true; + jQuery.support.optDisabled = !opt.disabled; + + var _scriptEval = null; + jQuery.support.scriptEval = function() { + if ( _scriptEval === null ) { + var root = document.documentElement, + script = document.createElement("script"), + id = "script" + jQuery.now(); + + try { + script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); + } catch(e) {} + + root.insertBefore( script, root.firstChild ); + + // Make sure that the execution of code works by injecting a script + // tag with appendChild/createTextNode + // (IE doesn't support this, fails, and uses .text instead) + if ( window[ id ] ) { + _scriptEval = true; + delete window[ id ]; + } else { + _scriptEval = false; + } + + root.removeChild( script ); + // release memory in IE + root = script = id = null; + } + + return _scriptEval; + }; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + + } catch(e) { + jQuery.support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent("onclick", function click() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + jQuery.support.noCloneEvent = false; + div.detachEvent("onclick", click); + }); + div.cloneNode(true).fireEvent("onclick"); + } + + div = document.createElement("div"); + div.innerHTML = ""; + + var fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; + + // Figure out if the W3C box model works as expected + // document.body must exist before we can do this + jQuery(function() { + var div = document.createElement("div"), + body = document.getElementsByTagName("body")[0]; + + // Frameset documents with no body should not run this code + if ( !body ) { + return; + } + + div.style.width = div.style.paddingLeft = "1px"; + body.appendChild( div ); + jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; + + if ( "zoom" in div.style ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2; + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
    "; + jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2; + } + + div.innerHTML = "
    t
    "; + var tds = div.getElementsByTagName("td"); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0; + + tds[0].style.display = ""; + tds[1].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE < 8 fail this test) + jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0; + div.innerHTML = ""; + + body.removeChild( div ).style.display = "none"; + div = tds = null; + }); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + var eventSupported = function( eventName ) { + var el = document.createElement("div"); + eventName = "on" + eventName; + + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( !el.attachEvent ) { + return true; + } + + var isSupported = (eventName in el); + if ( !isSupported ) { + el.setAttribute(eventName, "return;"); + isSupported = typeof el[eventName] === "function"; + } + el = null; + + return isSupported; + }; + + jQuery.support.submitBubbles = eventSupported("submit"); + jQuery.support.changeBubbles = eventSupported("change"); + + // release memory in IE + div = all = a = null; +})(); + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the pagebreak + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } else { + id = jQuery.expando; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); + } else { + cache[ id ] = jQuery.extend(cache[ id ], name); + } + } + + thisCache = cache[ id ]; + + // Internal jQuery data is stored in a separate object inside the object's data + // cache in order to avoid key collisions between internal data and user-defined + // data + if ( pvt ) { + if ( !thisCache[ internalKey ] ) { + thisCache[ internalKey ] = {}; + } + + thisCache = thisCache[ internalKey ]; + } + + if ( data !== undefined ) { + thisCache[ name ] = data; + } + + // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should + // not attempt to inspect the internal events object using jQuery.data, as this + // internal data object is undocumented and subject to change. + if ( name === "events" && !thisCache[name] ) { + return thisCache[ internalKey ] && thisCache[ internalKey ].events; + } + + return getByName ? thisCache[ name ] : thisCache; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; + + if ( thisCache ) { + delete thisCache[ name ]; + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !isEmptyDataObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( pvt ) { + delete cache[ id ][ internalKey ]; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + var internalCache = cache[ id ][ internalKey ]; + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + if ( jQuery.support.deleteExpando || cache != window ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the entire user cache at once because it's faster than + // iterating through each key, but we need to continue to persist internal + // data if it existed + if ( internalCache ) { + cache[ id ] = {}; + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + + cache[ id ][ internalKey ] = internalCache; + + // Otherwise, we need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + } else if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } else { + elem[ jQuery.expando ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 ) { + var attr = this[0].attributes, name; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = name.substr( 5 ); + dataAttr( this[0], name, data[ name ] ); + } + } + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), + args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + data = elem.getAttribute( "data-" + key ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + !jQuery.isNaN( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON +// property to be considered empty objects; this property always exists in +// order to make sure JSON.stringify does not expose internal metadata +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +jQuery.extend({ + queue: function( elem, type, data ) { + if ( !elem ) { + return; + } + + type = (type || "fx") + "queue"; + var q = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( !data ) { + return q || []; + } + + if ( !q || jQuery.isArray(data) ) { + q = jQuery._data( elem, type, jQuery.makeArray(data) ); + + } else { + q.push( data ); + } + + return q; + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(); + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue", true ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function( i ) { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspaces = /\s+/, + rreturn = /\r/g, + rspecialurl = /^(?:href|src|style)$/, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rradiocheck = /^(?:radio|checkbox)$/i; + +jQuery.props = { + "for": "htmlFor", + "class": "className", + readonly: "readOnly", + maxlength: "maxLength", + cellspacing: "cellSpacing", + rowspan: "rowSpan", + colspan: "colSpan", + tabindex: "tabIndex", + usemap: "useMap", + frameborder: "frameBorder" +}; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name, fn ) { + return this.each(function(){ + jQuery.attr( this, name, "" ); + if ( this.nodeType === 1 ) { + this.removeAttribute( name ); + } + }); + }, + + addClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.addClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( value && typeof value === "string" ) { + var classNames = (value || "").split( rspaces ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className ) { + elem.className = value; + + } else { + var className = " " + elem.className + " ", + setClass = elem.className; + + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { + setClass += " " + classNames[c]; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.removeClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + var classNames = (value || "").split( rspaces ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + var className = (" " + elem.className + " ").replace(rclass, " "); + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[c] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this); + self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspaces ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + if ( !arguments.length ) { + var elem = this[0]; + + if ( elem ) { + if ( jQuery.nodeName( elem, "option" ) ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + + // We need to handle select boxes special + if ( jQuery.nodeName( elem, "select" ) ) { + var index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery(option).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + } + + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { + return elem.getAttribute("value") === null ? "on" : elem.value; + } + + // Everything else, we just grab the value + return (elem.value || "").replace(rreturn, ""); + + } + + return undefined; + } + + var isFunction = jQuery.isFunction(value); + + return this.each(function(i) { + var self = jQuery(this), val = value; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call(this, i, self.val()); + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray(val) ) { + val = jQuery.map(val, function (value) { + return value == null ? "" : value + ""; + }); + } + + if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { + this.checked = jQuery.inArray( self.val(), val ) >= 0; + + } else if ( jQuery.nodeName( this, "select" ) ) { + var values = jQuery.makeArray(val); + + jQuery( "option", this ).each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + this.selectedIndex = -1; + } + + } else { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery(elem)[name](value); + } + + var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), + // Whether we are setting (or getting) + set = value !== undefined; + + // Try to normalize/fix the name + name = notxml && jQuery.props[ name ] || name; + + // Only do all the following if this is a node (faster for style) + if ( elem.nodeType === 1 ) { + // These attributes require special treatment + var special = rspecialurl.test( name ); + + // Safari mis-reports the default selected property of an option + // Accessing the parent's selectedIndex property fixes it + if ( name === "selected" && !jQuery.support.optSelected ) { + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + + // If applicable, access the attribute via the DOM 0 way + // 'in' checks fail in Blackberry 4.7 #6931 + if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) { + if ( set ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } + + if ( value === null ) { + if ( elem.nodeType === 1 ) { + elem.removeAttribute( name ); + } + + } else { + elem[ name ] = value; + } + } + + // browsers index elements by id/name on forms, give priority to attributes. + if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { + return elem.getAttributeNode( name ).nodeValue; + } + + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + if ( name === "tabIndex" ) { + var attributeNode = elem.getAttributeNode( "tabIndex" ); + + return attributeNode && attributeNode.specified ? + attributeNode.value : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + + return elem[ name ]; + } + + if ( !jQuery.support.style && notxml && name === "style" ) { + if ( set ) { + elem.style.cssText = "" + value; + } + + return elem.style.cssText; + } + + if ( set ) { + // convert the value to a string (all browsers do this but IE) see #1070 + elem.setAttribute( name, "" + value ); + } + + // Ensure that missing attributes return undefined + // Blackberry 4.7 returns "" from getAttribute #6938 + if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) { + return undefined; + } + + var attr = !jQuery.support.hrefNormalized && notxml && special ? + // Some attributes require a special call on IE + elem.getAttribute( name, 2 ) : + elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return attr === null ? undefined : attr; + } + // Handle everything which isn't a DOM element node + if ( set ) { + elem[ name ] = value; + } + return elem[ name ]; + } +}); + + + + +var rnamespaces = /\.(.*)$/, + rformElems = /^(?:textarea|input|select)$/i, + rperiod = /\./g, + rspace = / /g, + rescape = /[^\w\s.|`]/g, + fcleanup = function( nm ) { + return nm.replace(rescape, "\\$&"); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // TODO :: Use a try/catch until it's safe to pull this out (likely 1.6) + // Minor release fix for bug #8018 + try { + // For whatever reason, IE has trouble passing the window object + // around, causing it to be cloned in the process + if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) { + elem = window; + } + } + catch ( e ) {} + + if ( handler === false ) { + handler = returnFalse; + } else if ( !handler ) { + // Fixes bug #7229. Fix recommended by jdalton + return; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery._data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events, + eventHandle = elemData.handle; + + if ( !events ) { + elemData.events = events = {}; + } + + if ( !eventHandle ) { + elemData.handle = eventHandle = function() { + // Handle the second event of a trigger and when + // an event is called after a pagebreak has unloaded + return typeof jQuery !== "undefined" && !jQuery.event.triggered ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + if ( !handleObj.guid ) { + handleObj.guid = handler.guid; + } + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for global triggering + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem, undefined, true ); + } + } + }, + + // bubbling is internal + trigger: function( event, data, elem /*, bubbling */ ) { + // Event object or event type + var type = event.type || event, + bubbling = arguments[3]; + + if ( !bubbling ) { + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + jQuery.extend( jQuery.Event(type), event ) : + // Just the event type (string) + jQuery.Event(type); + + if ( type.indexOf("!") >= 0 ) { + event.type = type = type.slice(0, -1); + event.exclusive = true; + } + + // Handle a global trigger + if ( !elem ) { + // Don't bubble custom events when global (to avoid too much overhead) + event.stopPropagation(); + + // Only trigger if we've ever bound an event for it + if ( jQuery.event.global[ type ] ) { + // XXX This code smells terrible. event.js should not be directly + // inspecting the data cache + jQuery.each( jQuery.cache, function() { + // internalKey variable is just used to make it easier to find + // and potentially change this stuff later; currently it just + // points to jQuery.expando + var internalKey = jQuery.expando, + internalCache = this[ internalKey ]; + if ( internalCache && internalCache.events && internalCache.events[ type ] ) { + jQuery.event.trigger( event, data, internalCache.handle.elem ); + } + }); + } + } + + // Handle triggering a single element + + // don't do events on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + // Clean up in case it is reused + event.result = undefined; + event.target = elem; + + // Clone the incoming data, if any + data = jQuery.makeArray( data ); + data.unshift( event ); + } + + event.currentTarget = elem; + + // Trigger the event, it is assumed that "handle" is a function + var handle = jQuery._data( elem, "handle" ); + + if ( handle ) { + handle.apply( elem, data ); + } + + var parent = elem.parentNode || elem.ownerDocument; + + // Trigger an inline bound script + try { + if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { + if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) { + event.result = false; + event.preventDefault(); + } + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (inlineError) {} + + if ( !event.isPropagationStopped() && parent ) { + jQuery.event.trigger( event, data, parent, true ); + + } else if ( !event.isDefaultPrevented() ) { + var old, + target = event.target, + targetType = type.replace( rnamespaces, "" ), + isClick = jQuery.nodeName( target, "a" ) && targetType === "click", + special = jQuery.event.special[ targetType ] || {}; + + if ( (!special._default || special._default.call( elem, event ) === false) && + !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { + + try { + if ( target[ targetType ] ) { + // Make sure that we don't accidentally re-trigger the onFOO events + old = target[ "on" + targetType ]; + + if ( old ) { + target[ "on" + targetType ] = null; + } + + jQuery.event.triggered = true; + target[ targetType ](); + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (triggerError) {} + + if ( old ) { + target[ "on" + targetType ] = old; + } + + jQuery.event.triggered = false; + } + } + }, + + handle: function( event ) { + var all, handlers, namespaces, namespace_re, events, + namespace_sort = [], + args = jQuery.makeArray( arguments ); + + event = args[0] = jQuery.event.fix( event || window.event ); + event.currentTarget = this; + + // Namespaced event handlers + all = event.type.indexOf(".") < 0 && !event.exclusive; + + if ( !all ) { + namespaces = event.type.split("."); + event.type = namespaces.shift(); + namespace_sort = namespaces.slice(0).sort(); + namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.namespace = event.namespace || namespace_sort.join("."); + + events = jQuery._data(this, "events"); + + handlers = (events || {})[ event.type ]; + + if ( events && handlers ) { + // Clone the handlers to prevent manipulation + handlers = handlers.slice(0); + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Filter the functions by class + if ( all || namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + } + + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + // Fixes #1925 where srcElement might not be defined either + event.target = event.srcElement || document; + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var doc = document.documentElement, + body = document.body; + + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { + event.which = event.charCode != null ? event.charCode : event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, + liveConvert( handleObj.origType, handleObj.selector ), + jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); + }, + + remove: function( handleObj ) { + jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); + } + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + // Check if mouse(over|out) are still within the same parent element + var parent = event.relatedTarget; + + // Firefox sometimes assigns relatedTarget a XUL element + // which we cannot access the parentNode property of + try { + + // Chrome does something similar, the parentNode property + // can be accessed but is null. + if ( parent !== document && !parent.parentNode ) { + return; + } + // Traverse up the tree + while ( parent && parent !== this ) { + parent = parent.parentNode; + } + + if ( parent !== this ) { + // set the correct event type + event.type = event.data; + + // handle event if we actually just moused on to a non sub-element + jQuery.event.handle.apply( this, arguments ); + } + + // assuming we've left the element since we most likely mousedover a xul element + } catch(e) { } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var changeFilters, + + getVal = function( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( elem.nodeName.toLowerCase() === "select" ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery._data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery._data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + e.liveFired = undefined; + jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + beforedeactivate: testChange, + + click: function( e ) { + var elem = e.target, type = elem.type; + + if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { + testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = elem.type; + + if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information + beforeactivate: function( e ) { + var elem = e.target; + jQuery._data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return rformElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return rformElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; + + // Handle when the input is .focus()'d + changeFilters.focus = changeFilters.beforeactivate; +} + +function trigger( type, elem, args ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + // Don't pass args or remember liveFired; they apply to the donor event. + var event = jQuery.extend( {}, args[ 0 ] ); + event.type = type; + event.originalEvent = {}; + event.liveFired = undefined; + jQuery.event.handle.call( elem, event ); + if ( event.isDefaultPrevented() ) { + args[ 0 ].preventDefault(); + } +} + +// Create "bubbling" focus and blur events +if ( document.addEventListener ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + jQuery.event.special[ fix ] = { + setup: function() { + this.addEventListener( orig, handler, true ); + }, + teardown: function() { + this.removeEventListener( orig, handler, true ); + } + }; + + function handler( e ) { + e = jQuery.event.fix( e ); + e.type = fix; + return jQuery.event.handle.call( this, e ); + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( jQuery.isFunction( data ) || data === false ) { + fn = data; + data = undefined; + } + + var handler = name === "one" ? jQuery.proxy( fn, function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }) : fn; + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + var event = jQuery.Event( type ); + event.preventDefault(); + event.stopPropagation(); + jQuery.event.trigger( event, data, this[0] ); + return event.result; + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + i = 1; + + // link all the functions, so any of them can unbind this click handler + while ( i < args.length ) { + jQuery.proxy( fn, args[ i++ ] ); + } + + return this.click( jQuery.proxy( fn, function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + })); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( jQuery.isFunction( data ) ) { + fn = data; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( type === "focus" || type === "blur" ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +}); + +function liveHandler( event ) { + var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, + elems = [], + selectors = [], + events = jQuery._data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) + if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { + return; + } + + if ( event.namespace ) { + namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + close = match[i]; + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { + elem = close.elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + event.type = handleObj.preType; + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj, level: close.level }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + + if ( maxLevel && match.level > maxLevel ) { + break; + } + + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + ret = match.handleObj.origHandler.apply( match.elem, arguments ); + + if ( ret === false || event.isPropagationStopped() ) { + maxLevel = match.level; + + if ( ret === false ) { + stop = false; + } + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var match, + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var found, item, + filter = Expr.filter[ type ], + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return "text" === elem.getAttribute( 'type' ); + }, + radio: function( elem ) { + return "radio" === elem.type; + }, + + checkbox: function( elem ) { + return "checkbox" === elem.type; + }, + + file: function( elem ) { + return "file" === elem.type; + }, + password: function( elem ) { + return "password" === elem.type; + }, + + submit: function( elem ) { + return "submit" === elem.type; + }, + + image: function( elem ) { + return "image" === elem.type; + }, + + reset: function( elem ) { + return "reset" === elem.type; + }, + + button: function( elem ) { + return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + var first = match[2], + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // If the nodes are siblings (or identical) we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

    "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector, + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + if ( matches ) { + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + return matches.call( node, expr ); + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
    "; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var ret = this.pushStack( "", "find", selector ), + length = 0; + + for ( var i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( var n = length; n < ret.length; n++ ) { + for ( var r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && jQuery.filter( selector, this ).length > 0; + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + if ( jQuery.isArray( selectors ) ) { + var match, selector, + matches = {}, + level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[selector] ) { + matches[selector] = jQuery.expr.match.POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[selector]; + + if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + var pos = POS.test( selectors ) ? + jQuery( selectors, context || this.context ) : null; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique(ret) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +} + + + + +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /", "" ], + legend: [ 1, "
    ", "
    " ], + thead: [ 1, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + col: [ 2, "", "
    " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and "); +// } diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/8eaccbef76094b364e2cfddaa1cc7cd98d109d49.jpg b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/8eaccbef76094b364e2cfddaa1cc7cd98d109d49.jpg new file mode 100644 index 000000000..9a744b88b Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/8eaccbef76094b364e2cfddaa1cc7cd98d109d49.jpg differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/Manual regression cases.xmind b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/Manual regression cases.xmind new file mode 100644 index 000000000..d1febe891 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/Manual regression cases.xmind differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/VersionUpdate/readme.txt b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/VersionUpdate/readme.txt new file mode 100644 index 000000000..69846e5e9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/VersionUpdate/readme.txt @@ -0,0 +1 @@ +1.3.0֧֮ǰİ汾ƿڷ֧쿴,ٱ \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/VersionUpdate/test list for 1.3.0.xmind b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/VersionUpdate/test list for 1.3.0.xmind new file mode 100644 index 000000000..c922e573d Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/VersionUpdate/test list for 1.3.0.xmind differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/VersionUpdate/test list for 1.3.6.xmind b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/VersionUpdate/test list for 1.3.6.xmind new file mode 100644 index 000000000..ac11a8d23 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/VersionUpdate/test list for 1.3.6.xmind differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/VersionUpdate/test list for 1.4.0.xmind b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/VersionUpdate/test list for 1.4.0.xmind new file mode 100644 index 000000000..30e9db6e2 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/VersionUpdate/test list for 1.4.0.xmind differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/VersionUpdate/test list for 1.4.3.xmind b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/VersionUpdate/test list for 1.4.3.xmind new file mode 100644 index 000000000..e3dfe584a Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/VersionUpdate/test list for 1.4.3.xmind differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/demo_1.3.0/IEAutolinkFalse_demo.html b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/demo_1.3.0/IEAutolinkFalse_demo.html new file mode 100644 index 000000000..7d96f2696 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/demo_1.3.0/IEAutolinkFalse_demo.html @@ -0,0 +1,175 @@ + + + + 完整demo + + + + + + + + + + + + + + +
    + +
    +
    +
    + + + + + + + + + + + +
    +
    + + + + + + + +
    + +
    + + +
    + +
    +
    + + +
    + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/demo_1.3.0/uparse.html b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/demo_1.3.0/uparse.html new file mode 100644 index 000000000..addf2d2de --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/demo_1.3.0/uparse.html @@ -0,0 +1,179 @@ + + + + + + + + + + +

    解析编辑的内容

    +
    +
      +
    1. +

      + asdfsadf +

      +
    2. +
        +
      1. +

        + asfd +

        +
      2. +
          +
        1. +

          + asdf +

          +
        2. +
            +
          1. +

            + asdf +

            +
          2. +
              +
            1. +

              + asdf +

              +
            2. +
                +
              1. +

                + asdf     +

                +
              2. +
              +
            +
          +
        +
      +
    +
      +
    • +

      + asdf +

      +
    • +
        +
      • +

        + sadf +

        +
      • +
          +
        • +

          + sdfsadf +

          +
        • +
            +
          • +

            +
            +

            +
          • +
          +
        +
      +
    +

    + 这里可以书写,编辑器的初始内容 +

    +
    bindEvents:{
    +            'ready':function(){
    +                utils.cssRule('anchor',
    +                    '.anchorclass{background: url(\''
    +                        + this.options.themePath
    +                        + this.options.theme +'/images/anchor.gif\') no-repeat scroll left center transparent;border: 1px dotted #0000FF;cursor: auto;display: inline-block;height: 16px;width: 15px;}',
    +                    this.document);
    +            }
    +        },
    +

    +
    +

    +
    +
    +
    asdf




















    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + 1 + + 6 + + o + + 6 + + 6 + + 6 + + 6 + + 6 + + 6 +
    +
    + + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/demo_1.3.6/Demo_3831.html b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/demo_1.3.6/Demo_3831.html new file mode 100644 index 000000000..943d86cfc --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/demo_1.3.6/Demo_3831.html @@ -0,0 +1,175 @@ + + + + 完整demo + + + + + + + + + + +
    +

    完整demo

    + +
    +
    +
    + + + + + + + + + + + +
    +
    + + + + + + + +
    + +
    + + +
    + +
    +
    + + +
    + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/demo_1.3.6/Demo_contentchange.html b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/demo_1.3.6/Demo_contentchange.html new file mode 100644 index 000000000..51d43565e --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/demo_1.3.6/Demo_contentchange.html @@ -0,0 +1,178 @@ + + + + 完整demo + + + + + + + + + + +
    +

    完整demo

    + +
    +
    +
    + + + + + + + + + + + +
    +
    + + + + + + + +
    + +
    + + +
    + +
    +
    + + +
    + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/demo_1.4.0/uparsedemo.html b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/demo_1.4.0/uparsedemo.html new file mode 100644 index 000000000..45cc4c7a6 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/demo_1.4.0/uparsedemo.html @@ -0,0 +1,51 @@ + + + + + + + + + +

    解析编辑的内容

    +
    + +
    +               moveToBookmark:function (bookmark) {
    +            var start = bookmark.id ? this.document.getElementById(bookmark.start) : bookmark.start,
    +                end = bookmark.end && bookmark.id ? this.document.getElementById(bookmark.end) : bookmark.end;
    +            this.setStartBefore(start);
    +            domUtils.remove(start);
    +            if (end) {
    +                this.setEndBefore(end);
    +                domUtils.remove(end);
    +            } else {
    +                this.collapse(true);
    +            }
    +            return this;
    +        },
    +        
    +
    + + + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/offical site.xmind b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/offical site.xmind new file mode 100644 index 000000000..f9513ec14 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/testDesign/offical site.xmind differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/analysis.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/analysis.php new file mode 100644 index 000000000..94bf58890 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/analysis.php @@ -0,0 +1,112 @@ +circle)) return array();//如果已经被分析过则直接返回 + array_push($this->circle, $domain); + + $include = array(); + $cnts = self::get_src_cnt($domain); + $is = $cnts['i']; + if(sizeof($is) > 0) + foreach($is as $d){ + if($recurse) + $include = array_merge($include, $this->get_import_srcs($d)); + else + $include[$d] = self::$_cache[$d]; + } + + //因为依赖关系的前后联系,最后在include中加入当前domain + if($recurse) + $include[$domain] = $cnts['c']; + return $include; + } + + + /** + * 读取源文件内容,支持缓存,支持覆盖率文件读取,覆盖率路径在Config中配置 + * @param string $domain + * @see Config::$COVERAGE_PATH + */ + static function get_src_cnt($domain){ + new Analysis(); + if(!array_key_exists($domain, self::$_cache)){ + $cnt =''; $covcnt = ''; + //$path = join('/', explode('.', $domain)).'.js'; //为了支持xx.xx.js类型的文件名而修改 田丽丽 + //文件在当前项目存在则取当前项目,否则取tangram项目 + require_once 'config.php'; + foreach(Config::$SOURCE_PATH as $i=>$d){ + if(Config::$DEBUG) + var_dump($d.$path); + if(file_exists($d.$path)){ + $cnt = file_get_contents($d.$path); + $cnt.="\n";//读取文件内容必须加个回车 + break; + } + } + //尝试读取cov目录下的文件,如果不存在则忽略 + $covpath = Config::$COVERAGE_PATH.$path; + if(file_exists($covpath)){ + if(Config::$DEBUG)var_dump($covpath); + $covcnt = file_get_contents($covpath); + } + else $covcnt = $cnt; + if($cnt == ''){ + if(Config::$DEBUG) + print "fail read file : ".$path; + return array('', array(), ''); + } + + if(Config::$DEBUG) + print "start read file $domain
    "; + + $is = array(); + //正则匹配,提取所有(///import xxx;)中的xxx + preg_match_all('/\/\/\/import\s+([^;]+);?/ies', $cnt, $is, PREG_PATTERN_ORDER); + + //移除//,顺便移除空行 + // $cnt = preg_replace('/\/\/.*/m', '', $cnt);TODO:正则处理出现在“”或者正则中的//时出现问题 + //移除/**/ + // $cnt = preg_replace('/\/\*.*\*\//sU', '', $cnt); + + self::$_cache[$domain] = array('c'=>$cnt, 'i'=>$is[1], 'cc'=>$covcnt); + } + return self::$_cache[$domain]; + } +} +?> diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/batchrun.sh b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/batchrun.sh new file mode 100644 index 000000000..f88256c14 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/batchrun.sh @@ -0,0 +1,10 @@ +/home/work/.bash_profile +cd /home/work/repos/Tangram-base +/home/work/soft/git-1.7.3.5/bin-wrappers/git pull +sh release/output.sh +rm -rf test/tools/br/report +wget -q -O /tmp/tmp.php http://10.32.34.115:8000/Tangram-base/test/tools/br/runall.php?clearreport=true&cov=true +sleep 3m +rm -rf test/tools/br/report +wget -q -O /tmp/tmp.php http://10.32.34.115:8000/Tangram-base/test/tools/br/runall.php?release=true&clearreport=true +cd - \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/case.class.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/case.class.php new file mode 100644 index 000000000..40278b6eb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/case.class.php @@ -0,0 +1,242 @@ +projroot = $projroot; + $this->name = $name; + + $this->ext = $ext; + if ( strlen( $ext ) > 0 ) { + $ns = explode( '.' , $name ); + + $n = array_pop( $ns ); + array_push( $ns , $ext , $n ); + $path = implode( '/' , $ns ); + } else { + //$path = implode( '/' , explode( '.' , $name ) ); + $path = $name; //为了支持xx.xx.js类型的文件名而修改 田丽丽 + } +// $dir = explode('/',$path); +// if($dir[0]=='dialogs') +// $this->path = $this->projroot . '_test/' . $path . '.html'; +// else + $this->path = $this->projroot . '_test/' . $path . '.js'; + if ( filesize( $this->path ) < 20 ) { + $this->empty = true; + return; + } + $this->case_id = 'id_case_' . join( '_' , explode( '.' , $name ) ); + } + + + public function print_js( $cov, $release = false ) + { + print '' . "\n"; + print '' . "\n"; + print '' . "\n"; + print '' . "\n"; + print '' . "\n"; + print '' . "\n"; + print '' . "\n"; + print '' . "\n"; + + print '' . "\n"; // print '' . "\n"; + print '' . "\n"; + + + /* load case source*/ + $importurl = "{$this->projroot}_test/tools/br/import.php?f=$this->name"; + if ( $cov ) $importurl .= '^&cov=true'; + print "\n"; + + /* load case and case dependents*/ + //$ps = explode( '.' , $this->name ); + $ps = explode( '/' , $this->name ); //为了支持xx.xx.js类型的文件名而修改 田丽丽 + array_pop( $ps ); + array_push( $ps , 'tools' ); + + if ( file_exists( $this->projroot . '_test/' . implode( '/' , $ps ) . '.js' ) ) //没有就不加载了 + print '' . "\n"; + print '' . "\n"; + + + } + public function print_all_js( $cov, $release = false ) + { + print '' . "\n"; + print '' . "\n"; + print '' . "\n"; + print '' . "\n"; + print '' . "\n"; + print '' . "\n"; + print '' . "\n"; + print '' . "\n"; + + print '' . "\n"; + + print '' . "\n"; + + + /* load case source*/ + $importurl = "{$this->projroot}ueditor/ueditor.all.min.js"; + print "\n"; + + /* load case and case dependents*/ + //$ps = explode( '.' , $this->name ); + $ps = explode( '/' , $this->name ); //为了支持xx.xx.js类型的文件名而修改 田丽丽 + array_pop( $ps ); + array_push( $ps , 'tools' ); + + if ( file_exists( $this->projroot . '_test/' . implode( '/' , $ps ) . '.js' ) ) //没有就不加载了 + print '' . "\n"; + print '' . "\n"; + + + } + public function match( $matcher ) + { + if ( $matcher == '*' ) + return true; + $len = strlen( $matcher ); + + /** + * 处理多选分支,有一个成功则成功,filter后面参数使用|切割 + * @var unknown_type + */ + $as = explode( ';' , $matcher ); + if ( sizeof( $as ) > 1 ) { + + //这里把或的逻辑改成与 + foreach ( $as as $matcher1 ) { + if ( $this->match( $matcher1 ) ) + return true; + } + return false; + } + $ms = explode( ',' , $matcher ); + if ( sizeof( $ms ) > 1 ) { + + //这里把或的逻辑改成与 + foreach ( $ms as $matcher1 ) { + if ( !$this->match( $matcher1 ) ) + return false; + } + return true; + } + + /** + * 处理反向选择分支 + */ + if ( substr( $matcher , 0 , 1 ) == '!' ) { + $m = substr( $matcher , 1 ); + if ( substr( $this->name , 0 , strlen( $m ) ) == $m ) + return false; + return true; + } + + if ( $len > strlen( $this->name ) ) { + return false; + } + return substr( $this->name , 0 , $len ) == $matcher; + } + + public static function listcase( $filter = "*" , $filterRun = '*',$projroot = '../../../' ) + { + $srcpath = $projroot . '_src/'; + $testpath = $projroot . '_test/'; + require_once 'filehelper.php'; + $caselist = getSameFile( $srcpath , $testpath , '' ); + sort($caselist,SORT_STRING); + foreach ( $caselist as $caseitem ) { + /*将文件名替换为域名方式,替换/为.,移除.js*/ + //$name = str_replace( '/' , '.' , substr( $caseitem , 0 , -3 ) ); + $name = substr( $caseitem , 0 , -3 ); //为了支持xx.xx.js类型的文件名而修改 田丽丽 + $c = new Kiss( $projroot , $name ); + if ( $c->empty ) + continue; + if ( $c->match( $filterRun ) ) { + $newName = explode( '\\.' , $name ); + $newName = $newName[ count( $newName ) - 1 ]; + print( "case_id\" class=\"jsframe_qunit\" target=\"_blank\" title=\"$name\" onclick=\"run('$name');\$('#id_rerun').html('$name');return false;\">" + /*过长的时候屏蔽超出20的部分,因为隐藏的处理,所有用例不能直接使用标签a中的innerHTML,而应该使用title*/ + . $newName . "\n" ); + } + } + /** + * 设置在源码路径下没有同名文件对应的测试文件 + */ + foreach(Config::$special_Case as $s_caseitem => $s_source){ + //取形如 'plugins/config_test.js' 中 'plugins/config_test'部分 + $s_newName = str_replace(".js","", $s_caseitem ); + print( "". $s_newName . "\n" ); + } + } + + public static function listSrcOnly( $print = true , $projroot = '../../../' ) + { + $srcpath = $projroot . '_src/'; + $testpath = $projroot . '_test/'; + require_once 'filehelper.php'; + $caselist = getSameFile( $srcpath , $testpath , '' ); + $srclist = getSrcOnlyFile( $srcpath , $testpath , '' ); + $srcList = array(); + foreach ( $srclist as $case ) { + if ( in_array( $case , $caselist ) ) + continue; + $name = str_replace( '/' , '.' , substr( $case , 0 , -3 ) ); + $tag = "" . ( strlen( $name ) > 20 ? substr( $name , 6 ) + : $name ) . ""; + array_push( $srcList , $tag ); + if ( $print ) + echo $tag; + } + return $srcList; + } +} + +?> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/config.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/config.php new file mode 100644 index 000000000..fbc842dc9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/config.php @@ -0,0 +1,83 @@ + array( '10.94.26.94' , "C:\\Program Files\\Internet Explorer\\iexplore.exe" ) + , 'ie11main' => array( '10.81.96.46' , "C:\\Program Files\\Internet Explorer\\iexplore.exe" ) + + , + 'firefox' => array( '10.94.26.95' , "C:\\Program Files\\mozilla firefox\\firefox.exe" ) +// 'firefox' => array( '10.81.96.46@8500' , "C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe" ) +// , '360ie8' => array('10.81.58.64@8500',"C:\\Program Files\\360\\360se\\360SE.exe") +// , '360ie7' => array( '10.81.58.87@8500' , "C:\\Program Files\\360\\360se\\360SE.exe" ) + + +// , 'ie6' => array( '10.81.58.86@8500' , "C:\\Program Files\\Internet Explorer\\iexplore.exe" ) +//C:\Program Files\Google\Chrome\Application\chrome.exe +// "C:\Program Files\Mozilla Firefox\firefox.exe" + , 'chrome' => array( '10.94.26.95' , "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" ) + , + 'ie8main' => array( '10.94.26.94' , "C:\\Program Files\\Internet Explorer\\iexplore.exe" ) + , 'ie11supp' => array( '10.81.96.46' , "C:\\Program Files\\Internet Explorer\\iexplore.exe" ) +// , 'ie7' => array( '10.81.58.87@8500' , "C:\\Program Files\\Internet Explorer\\iexplore.exe" ) +// , 'opera' => array( '10.81.58.64@8500' , "C:\\Program Files\\Opera\\opera.exe" ) +// , 'safari' => array( '10.81.58.63@8500' , "C:\\Program Files\\Safari\\Safari.exe" ) + ); + + public static $DEBUG = false; + + public static $HISTORY_REPORT_PATH = '/report'; + + public static function getBrowserSet($browsers){ + if(strcmp($browsers,'')==0){ + return Config::$BROWSERS; + } + $selectedBrowsers =array(); + $browserName = explode('_',$browsers); + foreach($browserName as $s){ + if(array_key_exists($s,Config::$BROWSERS));{ + $selectedBrowsers[$s] =Config::$BROWSERS[$s]; + } + } + return $selectedBrowsers; + } + + public static function StopAll() + { + $hostarr = array(); + foreach ( Config::$BROWSERS as $b => $h ) { + $host = $h[ 0 ]; + if ( array_search( $host , $hostarr ) ) + continue; + array_push( $hostarr , $host ); + require_once 'lib/Staf.php'; + Staf::process_stop( '' , $host , true ); + Staf::process( "free all" ); + } + } + public static function StopOne($key){ + $host = Config::$BROWSERS[$key][0]; + require_once 'lib/Staf.php'; + Staf::process_stop( '' , $host , true ); + } + /** + * 源码路径配置,会在所有位置寻找源码 + * @var ArrayIterator::String + */ + public static $SOURCE_PATH = array( "../../../_src/" ); + + public static $test_PATH = "../../../_test/"; + + /** + * 覆盖率相关源码所在路径,如果路径中没有找到会回到$SOURCH_PATH中查找 + * @var string + */ + public static $COVERAGE_PATH = "../../coverage/"; + /** + * 设置在源码路径下没有同名文件对应的测试文件 + * @var array + */ + public static $special_Case = array('plugins/ueditor.config.js'=>'../../../ueditor.config.js'); + } + +?> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscov.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscov.php new file mode 100644 index 000000000..fe8d96413 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscov.php @@ -0,0 +1,61 @@ + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage-highlight.css b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage-highlight.css new file mode 100644 index 000000000..d2ad01da5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage-highlight.css @@ -0,0 +1,38 @@ +/* + jscoverage-highlight.css - JSCoverage syntax highlighting style sheet + Copyright (C) 2008, 2009, 2010 siliconforks.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* keyword, type, symbol, cbracket */ +#sourceTable .k { + font-weight: bold; +} + +/* string, regexp, number */ +#sourceTable .s { + color: #006400; +} + +/* specialchar */ +#sourceTable .t { + color: #2e8b57; +} + +/* comment */ +#sourceTable .c { + font-style: italic; +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage-ie.css b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage-ie.css new file mode 100644 index 000000000..05cad2afa --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage-ie.css @@ -0,0 +1,108 @@ +/* + jscoverage-ie.css - JSCoverage style sheet for Internet Explorer + Copyright (C) 2007, 2008, 2009, 2010 siliconforks.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#headingDiv { + position: static; + margin-left: 10px; + margin-right: 10px; + padding-top: 0.5em; +} + +#tabs { + clear: all; + position: static; + top: auto; + left: auto; + right: auto; + height: auto; + margin-left: 10px; + margin-right: 10px; +} + +#tabs div { + position: relative; + height: auto; + line-height: normal; + padding-top: 5px; + padding-bottom: 5px; +} + +#tabs div.selected { + padding-bottom: 6px; + z-index: 2; +} + +.TabPage { + position: relative; + top: -1px; + left: auto; + right: auto; + bottom: auto; + clear: left; + margin-left: 10px; + margin-right: 10px; + padding: 10px; + z-index: 1; +} + +#locationDiv { + margin-bottom: 10px; +} + +#iframeDiv { + position: static; + width: 100%; +} + +#summaryDiv { + position: static; + width: 100%; +} + +#fileDiv { + margin-bottom: 10px; +} + +#sourceDiv { + position: static; + width: 100%; +} + +#storeDiv { + position: static; + width: 100%; +} + +/* some defaults */ + +.TabPage { + height: 650px; +} + +#iframeDiv { + height: 600px; +} + +#summaryDiv { + height: 600px; +} + +#sourceDiv { + height: 600px; +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage-throbber.gif b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage-throbber.gif new file mode 100644 index 000000000..f13c0b4ec Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage-throbber.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage.css b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage.css new file mode 100644 index 000000000..9866fd706 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage.css @@ -0,0 +1,355 @@ +/* + jscoverage.css - code coverage for JavaScript + Copyright (C) 2007, 2008, 2009, 2010 siliconforks.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +body { + background-color: #bfffbf; + font-family: sans-serif; + font-size: 100%; + margin: 0; +} + +#mainDiv { + font-size: 0.8125em; +} + +#headingDiv { + position: absolute; + top: 0.5em; + left: 1.5em; + right: 1.5em; + bottom: 0; + line-height: 1.5em; +} + +h1 { + float: left; + margin: 0; + padding-bottom: 0.5em; + font-size: 1.3em; +} + +.ProgressBar { + float: left; + visibility: hidden; +} + +.ProgressPercentage { + display: block; + float: left; + width: 5em; + text-align: right; +} + +.ProgressGraph { + float: left; + width: 100px; + height: 10px; + border: 1px solid black; + margin-top: 0.3em; + background-color: #d4d0c8; + overflow: hidden; +} + +.ProgressCovered { + /* windows system color ActiveCaption or Highlight */ + background-color: #0a246a; + width: 0; + height: 10px; + overflow: hidden; +} + +#progressLabel { + display: block; + float: left; + padding-left: 0.3em; +} + +#warningDiv { + display: none; + float: right; + background-color: #FFBFBF; + border: 1px solid red; + padding-left: 2px; + padding-right: 2px; +} + +.WarningDialog { + display: none; + background-color: #FFBFBF; + position: absolute; + z-index: 10; + top: 20%; + left: 20%; + width: 50%; + padding: 5%; + border: 1px solid red; +} + +.WarningDialog button { + display: block; + margin-left: auto; + margin-right: auto; +} + +/******************************************************************************* +browser tab +*/ + +input#location, button { + border: 1px solid black; + margin-left: 1px; + margin-right: 1px; +} + +#iframeDiv { + position: absolute; + top: 3.5em; + left: 1em; + right: 1em; + bottom: 1em; +} + +iframe { + width: 100%; + height: 100%; +} + +/******************************************************************************* +summary tab +*/ + +#summaryDiv { + position: absolute; + top: 3em; + left: 1em; + right: 1em; + bottom: 1em; + overflow: auto; +} + +table#summaryTable { + width: 100%; + margin-left: 0px; + margin-right: 0px; + border-collapse: collapse; + font-size: small; +} + +table#summaryTable th, table#summaryTable td { + border-left: 1px solid #d9d9d9; +} + +table#summaryTable th.leftColumn, table#summaryTable td.leftColumn { + border-left-width: 0px; +} + +table#summaryTable th, table#summaryTable td { + padding: 2px; +} + +th { + background-color: #e6ffe6; +} + +td.numeric { + text-align: right; +} + +abbr { + cursor: help; +} + +tr#summaryTotals td.leftColumn span { + float: right; +} +tr#summaryTotals td.leftColumn span.title { + float: left; + font-weight: bold; +} +tr#summaryTotals td { + background-color: #ffd; +} +td.coverage { + width: 150px; +} +td.coverage span { + float: right; + margin-right: 5px; +} +.pctGraph { + width: 100px; + height: 10px; + float: right; + border: 1px solid #000; + background-color: #e00000; + overflow: hidden; + margin-top: 4px; +} +.pctGraph .covered { + background-color: #00f000; + width: 0; + height: 10px; +} +.pctGraph .skipped { + background-color: #d4d0c8; + width: 100px; + height: 10px; +} +tbody#summaryTbody tr.even td { + background-color: #e6ffe6; +} + +/******************************************************************************* +source tab +*/ + +#fileDiv { + font-size: large; + font-weight: bold; +} + +#sourceDiv { + position: absolute; + top: 3em; + left: 1em; + right: 1em; + bottom: 1em; + overflow: auto; +} + +table#sourceTable { + border: 0px; + border-collapse: collapse; + font-size: small; +} + +/* +IE default behavior is to make
     smaller than surrounding text.  Because
    +the table already has font-size small, this would make the font-size within the
    +
     x-small.  So we don't rely on the default.
    +*/
    +table#sourceTable pre {
    +  font-size: medium;
    +}
    +
    +table#sourceTable td {
    +  border: 0px;
    +  padding-top: 0px;
    +  padding-bottom: 0px;
    +  padding-left: 10px;
    +  padding-right: 10px;
    +}
    +
    +table#sourceTable pre {
    +  border: 0px;
    +  margin: 0px;
    +}
    +
    +.g {
    +  background-color: #bfffbf;
    +}
    +
    +.y {
    +  background-color: #ffffbf;
    +}
    +
    +.r {
    +  background-color: #ffbfbf;
    +}
    +
    +/*******************************************************************************
    +store tab
    +*/
    +
    +#storeDiv {
    +  position: absolute;
    +  top: 3em;
    +  left: 1em;
    +  right: 1em;
    +  bottom: 1em;
    +  overflow: auto;
    +}
    +
    +/*******************************************************************************
    +about tab
    +*/
    +
    +p {
    +  margin-top: 0;
    +}
    +
    +/*******************************************************************************
    +tabs
    +*/
    +
    +#tabs {
    +  position: absolute;
    +  top: 3em;
    +  left: 1.5em;
    +  right: 1.5em;
    +  height: 2em;
    +}
    +
    +#tabs div {
    +  background-color: white;
    +  position: relative;
    +  float: left;
    +  border: 1px solid black;
    +  border-bottom-width: 0;
    +  cursor: pointer;
    +  margin-left: 0.5em;
    +  margin-right: 0.5em;
    +  padding-left: 0.5em;
    +  padding-right: 0.5em;
    +  height: 2em;
    +  z-index: 1;
    +  line-height: 1.8em;
    +}
    +
    +#tabs div.selected {
    +  z-index: 3;
    +  cursor: default;
    +}
    +
    +#tabs div.disabled {
    +  /* windows system color GrayText */
    +  color: #808080;
    +  cursor: default; 
    +}
    +
    +.TabPage {
    +  background-color: white;
    +  border: 1px solid black;
    +  position: absolute;
    +  top: 5em;
    +  left: 1.5em;
    +  right: 1.5em;
    +  bottom: 1.5em;
    +  z-index: 2;
    +  padding: 1em;
    +  display: none;
    +}
    +
    +#tabPages div.selected {
    +  display: block;
    +}
    +
    +img {
    +  visibility: hidden;
    +}
    diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage.html b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage.html
    new file mode 100644
    index 000000000..e6288fce2
    --- /dev/null
    +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage.html
    @@ -0,0 +1,168 @@
    +
    +
    +
    +
    +
    +
    +JSCoverage
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +

    +Recent web browsers tend to place significant security restrictions on the use +of file: URLs. These restrictions can prevent JSCoverage from +working properly. To avoid problems, it is recommended that you do either of the +following: +

    +
      +
    • If you are using the jscoverage program to instrument your +JavaScript code, install the instrumented files on a web server.
    • +
    • Use the jscoverage-server program (which itself acts as a web +server).
    • +
    +

    +See the +manual +for further details. +

    + +
    + +
    +

    +Recent web browsers tend to place significant security restrictions on the use +of file: URLs. These restrictions can prevent JSCoverage from +working properly. To avoid problems, it is recommended that you view coverage +reports stored to the filesystem by serving them from a web server. +

    +

    +See the +manual +for further details. +

    + +
    + +
    + +
    Summary
    +
    Source
    +
    Store
    +
    About
    +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + +
    FileStatementsExecutedCoverage
    + Total: + 0 + 00 +
    +
    +
    + 0% +
    +
    +
    +
    +
    +
    +
    +
    + + loading... +
    +
    +
    +

    + This is version 0.5.1 of JSCoverage, a program that calculates code + coverage statistics for JavaScript. +

    +

    + See http://siliconforks.com/jscoverage/ for more information. +

    +

    + Copyright © 2007, 2008, 2009, 2010 siliconforks.com +

    +
    +
    +
    + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage.js new file mode 100644 index 000000000..4233615a4 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/jscoverage.js @@ -0,0 +1,1176 @@ +/* + jscoverage.js - code coverage for JavaScript + Copyright (C) 2007, 2008, 2009, 2010 siliconforks.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +function jscoverage_openWarningDialog() { + var id; + if (jscoverage_isReport) { + id = 'reportWarningDialog'; + } + else { + id = 'warningDialog'; + } + var dialog = document.getElementById(id); + dialog.style.display = 'block'; +} + +function jscoverage_closeWarningDialog() { + var id; + if (jscoverage_isReport) { + id = 'reportWarningDialog'; + } + else { + id = 'warningDialog'; + } + var dialog = document.getElementById(id); + dialog.style.display = 'none'; +} + +/** +Initializes the _$jscoverage object in a window. This should be the first +function called in the page. +@param w this should always be the global window object +*/ +function jscoverage_init(w) { + try { + // in Safari, "import" is a syntax error + Components.utils['import']('resource://app/modules/jscoverage.jsm'); + jscoverage_isInvertedMode = true; + return; + } + catch (e) {} + + // check if we are in inverted mode + if (w.opener) { + try { + if (w.opener.top._$jscoverage) { + jscoverage_isInvertedMode = true; + if (! w._$jscoverage) { + w._$jscoverage = w.opener.top._$jscoverage; + } + } + else { + jscoverage_isInvertedMode = false; + } + } + catch (e) { + try { + if (w.opener._$jscoverage) { + jscoverage_isInvertedMode = true; + if (! w._$jscoverage) { + w._$jscoverage = w.opener._$jscoverage; + } + } + else { + jscoverage_isInvertedMode = false; + } + } + catch (e2) { + jscoverage_isInvertedMode = false; + } + } + } + else { + jscoverage_isInvertedMode = false; + } + + if (! jscoverage_isInvertedMode) { + if (! w._$jscoverage) { + w._$jscoverage = {}; + } + } +} + +var jscoverage_currentFile = null; +var jscoverage_currentLine = null; + +var jscoverage_inLengthyOperation = false; + +/* +Possible states: + isInvertedMode isServer isReport tabs +normal false false false Browser +inverted true false false +server, normal false true false Browser, Store +server, inverted true true false Store +report false false true +*/ +var jscoverage_isInvertedMode = false; +var jscoverage_isServer = false; +var jscoverage_isReport = false; + +jscoverage_init(window); + +function jscoverage_createRequest() { + // Note that the IE7 XMLHttpRequest does not support file URL's. + // http://xhab.blogspot.com/2006/11/ie7-support-for-xmlhttprequest.html + // http://blogs.msdn.com/ie/archive/2006/12/06/file-uris-in-windows.aspx +//#JSCOVERAGE_IF + if (window.ActiveXObject) { + return new ActiveXObject("Microsoft.XMLHTTP"); + } + else { + return new XMLHttpRequest(); + } +} + +// http://www.quirksmode.org/js/findpos.html +function jscoverage_findPos(obj) { + var result = 0; + do { + result += obj.offsetTop; + obj = obj.offsetParent; + } + while (obj); + return result; +} + +// http://www.quirksmode.org/viewport/compatibility.html +function jscoverage_getViewportHeight() { +//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent) + if (self.innerHeight) { + // all except Explorer + return self.innerHeight; + } + else if (document.documentElement && document.documentElement.clientHeight) { + // Explorer 6 Strict Mode + return document.documentElement.clientHeight; + } + else if (document.body) { + // other Explorers + return document.body.clientHeight; + } + else { + throw "Couldn't calculate viewport height"; + } +//#JSCOVERAGE_ENDIF +} + +/** +Indicates visually that a lengthy operation has begun. The progress bar is +displayed, and the cursor is changed to busy (on browsers which support this). +*/ +function jscoverage_beginLengthyOperation() { + jscoverage_inLengthyOperation = true; + + var progressBar = document.getElementById('progressBar'); + progressBar.style.visibility = 'visible'; + ProgressBar.setPercentage(progressBar, 0); + var progressLabel = document.getElementById('progressLabel'); + progressLabel.style.visibility = 'visible'; + + /* blacklist buggy browsers */ +//#JSCOVERAGE_IF + if (! /Opera|WebKit/.test(navigator.userAgent)) { + /* + Change the cursor style of each element. Note that changing the class of the + element (to one with a busy cursor) is buggy in IE. + */ + var tabs = document.getElementById('tabs').getElementsByTagName('div'); + var i; + for (i = 0; i < tabs.length; i++) { + tabs.item(i).style.cursor = 'wait'; + } + } +} + +/** +Removes the progress bar and busy cursor. +*/ +function jscoverage_endLengthyOperation() { + var progressBar = document.getElementById('progressBar'); + ProgressBar.setPercentage(progressBar, 100); + setTimeout(function() { + jscoverage_inLengthyOperation = false; + progressBar.style.visibility = 'hidden'; + var progressLabel = document.getElementById('progressLabel'); + progressLabel.style.visibility = 'hidden'; + progressLabel.innerHTML = ''; + + var tabs = document.getElementById('tabs').getElementsByTagName('div'); + var i; + for (i = 0; i < tabs.length; i++) { + tabs.item(i).style.cursor = ''; + } + }, 50); +} + +function jscoverage_setSize() { +//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent) + var viewportHeight = jscoverage_getViewportHeight(); + + /* + border-top-width: 1px + padding-top: 10px + padding-bottom: 10px + border-bottom-width: 1px + margin-bottom: 10px + ---- + 32px + */ + var tabPages = document.getElementById('tabPages'); + var tabPageHeight = (viewportHeight - jscoverage_findPos(tabPages) - 32) + 'px'; + var nodeList = tabPages.childNodes; + var length = nodeList.length; + for (var i = 0; i < length; i++) { + var node = nodeList.item(i); + if (node.nodeType !== 1) { + continue; + } + node.style.height = tabPageHeight; + } + + var iframeDiv = document.getElementById('iframeDiv'); + // may not exist if we have removed the first tab + if (iframeDiv) { + iframeDiv.style.height = (viewportHeight - jscoverage_findPos(iframeDiv) - 21) + 'px'; + } + + var summaryDiv = document.getElementById('summaryDiv'); + summaryDiv.style.height = (viewportHeight - jscoverage_findPos(summaryDiv) - 21) + 'px'; + + var sourceDiv = document.getElementById('sourceDiv'); + sourceDiv.style.height = (viewportHeight - jscoverage_findPos(sourceDiv) - 21) + 'px'; + + var storeDiv = document.getElementById('storeDiv'); + if (storeDiv) { + storeDiv.style.height = (viewportHeight - jscoverage_findPos(storeDiv) - 21) + 'px'; + } +//#JSCOVERAGE_ENDIF +} + +/** +Returns the boolean value of a string. Values 'false', 'f', 'no', 'n', 'off', +and '0' (upper or lower case) are false. +@param s the string +@return a boolean value +*/ +function jscoverage_getBooleanValue(s) { + s = s.toLowerCase(); + if (s === 'false' || s === 'f' || s === 'no' || s === 'n' || s === 'off' || s === '0') { + return false; + } + return true; +} + +function jscoverage_removeTab(id) { + var tab = document.getElementById(id + 'Tab'); + tab.parentNode.removeChild(tab); + var tabPage = document.getElementById(id + 'TabPage'); + tabPage.parentNode.removeChild(tabPage); +} + +function jscoverage_isValidURL(url) { + // RFC 3986 + var matches = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/.exec(url); + if (matches === null) { + return false; + } + var scheme = matches[1]; + if (typeof scheme === 'string') { + scheme = scheme.toLowerCase(); + return scheme === '' || scheme === 'file:' || scheme === 'http:' || scheme === 'https:'; + } + return true; +} + +/** +Initializes the contents of the tabs. This sets the initial values of the +input field and iframe in the "Browser" tab and the checkbox in the "Summary" +tab. +@param queryString this should always be location.search +*/ +function jscoverage_initTabContents(queryString) { + var showMissingColumn = false; + var url = null; + var windowURL = null; + var parameters, parameter, i, index, name, value; + if (queryString.length > 0) { + // chop off the question mark + queryString = queryString.substring(1); + parameters = queryString.split(/&|;/); + for (i = 0; i < parameters.length; i++) { + parameter = parameters[i]; + index = parameter.indexOf('='); + if (index === -1) { + // still works with old syntax + url = decodeURIComponent(parameter); + } + else { + name = parameter.substr(0, index); + value = decodeURIComponent(parameter.substr(index + 1)); + if (name === 'missing' || name === 'm') { + showMissingColumn = jscoverage_getBooleanValue(value); + } + else if (name === 'url' || name === 'u' || name === 'frame' || name === 'f') { + url = value; + } + else if (name === 'window' || name === 'w') { + windowURL = value; + } + } + } + } + + var checkbox = document.getElementById('checkbox'); + checkbox.checked = showMissingColumn; + if (showMissingColumn) { + jscoverage_appendMissingColumn(); + } + + var isValidURL = function (url) { + var result = jscoverage_isValidURL(url); + if (! result) { + alert('Invalid URL: ' + url); + } + return result; + }; + + if (url !== null && isValidURL(url)) { + // this will automatically propagate to the input field + frames[0].location = url; + } + else if (windowURL !== null && isValidURL(windowURL)) { + window.open(windowURL); + } + + // if the browser tab is absent, we have to initialize the summary tab + if (! document.getElementById('browserTab')) { + jscoverage_recalculateSummaryTab(); + } +} + +function jscoverage_body_load() { + // check if this is a file: URL + if (window.location && window.location.href && /^file:/i.test(window.location.href)) { + var warningDiv = document.getElementById('warningDiv'); + warningDiv.style.display = 'block'; + } + + var progressBar = document.getElementById('progressBar'); + ProgressBar.init(progressBar); + + function reportError(e) { + jscoverage_endLengthyOperation(); + var summaryThrobber = document.getElementById('summaryThrobber'); + summaryThrobber.style.visibility = 'hidden'; + var div = document.getElementById('summaryErrorDiv'); + div.innerHTML = 'Error: ' + e; + } + + if (jscoverage_isReport) { + jscoverage_beginLengthyOperation(); + var summaryThrobber = document.getElementById('summaryThrobber'); + summaryThrobber.style.visibility = 'visible'; + var request = jscoverage_createRequest(); + try { + request.open('GET', 'jscoverage.json', true); + request.onreadystatechange = function (event) { + if (request.readyState === 4) { + try { + if (request.status !== 0 && request.status !== 200) { + throw request.status; + } + var response = request.responseText; + if (response === '') { + throw 404; + } + + var json; + if (window.JSON && window.JSON.parse) { + json = window.JSON.parse(response); + } + else { + json = eval('(' + response + ')'); + } + + var file; + for (file in json) { + if (! json.hasOwnProperty(file)) { + continue; + } + + var fileCoverage = json[file]; + _$jscoverage[file] = fileCoverage.coverage; + _$jscoverage[file].source = fileCoverage.source; + } + jscoverage_recalculateSummaryTab(); + summaryThrobber.style.visibility = 'hidden'; + } + catch (e) { + reportError(e); + } + } + }; + request.send(null); + } + catch (e) { + reportError(e); + } + + jscoverage_removeTab('browser'); + jscoverage_removeTab('store'); + } + else { + if (jscoverage_isInvertedMode) { + jscoverage_removeTab('browser'); + } + + if (! jscoverage_isServer) { + jscoverage_removeTab('store'); + } + } + + jscoverage_initTabControl(); + + jscoverage_initTabContents(location.search); +} + +function jscoverage_body_resize() { + if (/MSIE/.test(navigator.userAgent)) { + jscoverage_setSize(); + } +} + +// ----------------------------------------------------------------------------- +// tab 1 + +function jscoverage_updateBrowser() { + var input = document.getElementById("location"); + frames[0].location = input.value; +} + +function jscoverage_openWindow() { + var input = document.getElementById("location"); + var url = input.value; + window.open(url); +} + +function jscoverage_input_keypress(e) { + if (e.keyCode === 13) { + if (e.shiftKey) { + jscoverage_openWindow(); + } + else { + jscoverage_updateBrowser(); + } + } +} + +function jscoverage_openInFrameButton_click() { + jscoverage_updateBrowser(); +} + +function jscoverage_openInWindowButton_click() { + jscoverage_openWindow(); +} + +function jscoverage_browser_load() { + /* update the input box */ + var input = document.getElementById("location"); + + /* sometimes IE seems to fire this after the tab has been removed */ + if (input) { + input.value = frames[0].location; + } +} + +// ----------------------------------------------------------------------------- +// tab 2 + +function jscoverage_createHandler(file, line) { + return function () { + jscoverage_get(file, line); + return false; + }; +} + +function jscoverage_createLink(file, line) { + var link = document.createElement("a"); + link.href = '#'; + link.onclick = jscoverage_createHandler(file, line); + + var text; + if (line) { + text = line.toString(); + } + else { + text = file; + } + + link.appendChild(document.createTextNode(text)); + + return link; +} + +function jscoverage_recalculateSummaryTab(cc) { + var checkbox = document.getElementById('checkbox'); + var showMissingColumn = checkbox.checked; + + if (! cc) { + cc = window._$jscoverage; + } + if (! cc) { +//#JSCOVERAGE_IF 0 + throw "No coverage information found."; +//#JSCOVERAGE_ENDIF + } + + var tbody = document.getElementById("summaryTbody"); + while (tbody.hasChildNodes()) { + tbody.removeChild(tbody.firstChild); + } + + var totals = { files:0, statements:0, executed:0 }; + + var file; + var files = []; + for (file in cc) { + if (! cc.hasOwnProperty(file)) { + continue; + } + + files.push(file); + } + files.sort(); + + var rowCounter = 0; + for (var f = 0; f < files.length; f++) { + file = files[f]; + var lineNumber; + var num_statements = 0; + var num_executed = 0; + var missing = []; + var fileCC = cc[file]; + var length = fileCC.length; + var currentConditionalEnd = 0; + var conditionals = null; + if (fileCC.conditionals) { + conditionals = fileCC.conditionals; + } + for (lineNumber = 0; lineNumber < length; lineNumber++) { + var n = fileCC[lineNumber]; + + if (lineNumber === currentConditionalEnd) { + currentConditionalEnd = 0; + } + else if (currentConditionalEnd === 0 && conditionals && conditionals[lineNumber]) { + currentConditionalEnd = conditionals[lineNumber]; + } + + if (currentConditionalEnd !== 0) { + continue; + } + + if (n === undefined || n === null) { + continue; + } + + if (n === 0) { + missing.push(lineNumber); + } + else { + num_executed++; + } + num_statements++; + } + + var percentage = ( num_statements === 0 ? 0 : parseInt(100 * num_executed / num_statements) ); + + var row = document.createElement("tr"); + row.className = ( rowCounter++ % 2 == 0 ? "odd" : "even" ); + + var cell = document.createElement("td"); + cell.className = 'leftColumn'; + var link = jscoverage_createLink(file); + cell.appendChild(link); + + row.appendChild(cell); + + cell = document.createElement("td"); + cell.className = 'numeric'; + cell.appendChild(document.createTextNode(num_statements)); + row.appendChild(cell); + + cell = document.createElement("td"); + cell.className = 'numeric'; + cell.appendChild(document.createTextNode(num_executed)); + row.appendChild(cell); + + // new coverage td containing a bar graph + cell = document.createElement("td"); + cell.className = 'coverage'; + var pctGraph = document.createElement("div"), + covered = document.createElement("div"), + pct = document.createElement("span"); + pctGraph.className = "pctGraph"; + if( num_statements === 0 ) { + covered.className = "skipped"; + pct.appendChild(document.createTextNode("N/A")); + } else { + covered.className = "covered"; + covered.style.width = percentage + "px"; + pct.appendChild(document.createTextNode(percentage + '%')); + } + pct.className = "pct"; + pctGraph.appendChild(covered); + cell.appendChild(pctGraph); + cell.appendChild(pct); + row.appendChild(cell); + + if (showMissingColumn) { + cell = document.createElement("td"); + for (var i = 0; i < missing.length; i++) { + if (i !== 0) { + cell.appendChild(document.createTextNode(", ")); + } + link = jscoverage_createLink(file, missing[i]); + + // group contiguous missing lines; e.g., 10, 11, 12 -> 10-12 + var j, start = missing[i]; + for (;;) { + j = 1; + while (i + j < missing.length && missing[i + j] == missing[i] + j) { + j++; + } + var nextmissing = missing[i + j], cur = missing[i] + j; + if (isNaN(nextmissing)) { + break; + } + while (cur < nextmissing && ! fileCC[cur]) { + cur++; + } + if (cur < nextmissing || cur >= length) { + break; + } + i += j; + } + if (start != missing[i] || j > 1) { + i += j - 1; + link.innerHTML += "-" + missing[i]; + } + + cell.appendChild(link); + } + row.appendChild(cell); + } + + tbody.appendChild(row); + + totals['files'] ++; + totals['statements'] += num_statements; + totals['executed'] += num_executed; + + // write totals data into summaryTotals row + var tr = document.getElementById("summaryTotals"); + if (tr) { + var tds = tr.getElementsByTagName("td"); + tds[0].getElementsByTagName("span")[1].firstChild.nodeValue = totals['files']; + tds[1].firstChild.nodeValue = totals['statements']; + tds[2].firstChild.nodeValue = totals['executed']; + + var coverage = parseInt(100 * totals['executed'] / totals['statements']); + if( isNaN( coverage ) ) { + coverage = 0; + } + tds[3].getElementsByTagName("span")[0].firstChild.nodeValue = coverage + '%'; + tds[3].getElementsByTagName("div")[1].style.width = coverage + 'px'; + } + + } + jscoverage_endLengthyOperation(); +} + +function jscoverage_appendMissingColumn() { + var headerRow = document.getElementById('headerRow'); + var missingHeader = document.createElement('th'); + missingHeader.id = 'missingHeader'; + missingHeader.innerHTML = 'Missing'; + headerRow.appendChild(missingHeader); + var summaryTotals = document.getElementById('summaryTotals'); + var empty = document.createElement('td'); + empty.id = 'missingCell'; + summaryTotals.appendChild(empty); +} + +function jscoverage_removeMissingColumn() { + var missingNode; + missingNode = document.getElementById('missingHeader'); + missingNode.parentNode.removeChild(missingNode); + missingNode = document.getElementById('missingCell'); + missingNode.parentNode.removeChild(missingNode); +} + +function jscoverage_checkbox_click() { + if (jscoverage_inLengthyOperation) { + return false; + } + jscoverage_beginLengthyOperation(); + var checkbox = document.getElementById('checkbox'); + var showMissingColumn = checkbox.checked; + setTimeout(function() { + if (showMissingColumn) { + jscoverage_appendMissingColumn(); + } + else { + jscoverage_removeMissingColumn(); + } + jscoverage_recalculateSummaryTab(); + }, 50); + return true; +} + +// ----------------------------------------------------------------------------- +// tab 3 + +function jscoverage_makeTable() { + var coverage = _$jscoverage[jscoverage_currentFile]; + var lines = coverage.source; + + // this can happen if there is an error in the original JavaScript file + if (! lines) { + lines = []; + } + + var rows = ['']; + var i = 0; + var progressBar = document.getElementById('progressBar'); + var tableHTML; + var currentConditionalEnd = 0; + + function joinTableRows() { + tableHTML = rows.join(''); + ProgressBar.setPercentage(progressBar, 60); + /* + This may be a long delay, so set a timeout of 100 ms to make sure the + display is updated. + */ + setTimeout(appendTable, 100); + } + + function appendTable() { + var sourceDiv = document.getElementById('sourceDiv'); + sourceDiv.innerHTML = tableHTML; + ProgressBar.setPercentage(progressBar, 80); + setTimeout(jscoverage_scrollToLine, 0); + } + + while (i < lines.length) { + var lineNumber = i + 1; + + if (lineNumber === currentConditionalEnd) { + currentConditionalEnd = 0; + } + else if (currentConditionalEnd === 0 && coverage.conditionals && coverage.conditionals[lineNumber]) { + currentConditionalEnd = coverage.conditionals[lineNumber]; + } + + var row = ''; + row += ''; + var timesExecuted = coverage[lineNumber]; + if (timesExecuted !== undefined && timesExecuted !== null) { + if (currentConditionalEnd !== 0) { + row += ''; + } + else { + row += ''; + } + row += ''; + row += ''; + row += '\n'; + rows[lineNumber] = row; + i++; + } + rows[i + 1] = '
    ' + lineNumber + ''; + } + else if (timesExecuted === 0) { + row += ''; + } + else { + row += ''; + } + row += timesExecuted; + row += '
    ' + lines[i] + '
    '; + ProgressBar.setPercentage(progressBar, 40); + setTimeout(joinTableRows, 0); +} + +function jscoverage_scrollToLine() { + jscoverage_selectTab('sourceTab'); + if (! window.jscoverage_currentLine) { + jscoverage_endLengthyOperation(); + return; + } + var div = document.getElementById('sourceDiv'); + if (jscoverage_currentLine === 1) { + div.scrollTop = 0; + } + else { + var cell = document.getElementById('line-' + jscoverage_currentLine); + + // this might not be there if there is an error in the original JavaScript + if (cell) { + var divOffset = jscoverage_findPos(div); + var cellOffset = jscoverage_findPos(cell); + div.scrollTop = cellOffset - divOffset; + } + } + jscoverage_currentLine = 0; + jscoverage_endLengthyOperation(); +} + +/** +Loads the given file (and optional line) in the source tab. +*/ +function jscoverage_get(file, line) { + if (jscoverage_inLengthyOperation) { + return; + } + jscoverage_beginLengthyOperation(); + setTimeout(function() { + var sourceDiv = document.getElementById('sourceDiv'); + sourceDiv.innerHTML = ''; + jscoverage_selectTab('sourceTab'); + if (file === jscoverage_currentFile) { + jscoverage_currentLine = line; + jscoverage_recalculateSourceTab(); + } + else { + if (jscoverage_currentFile === null) { + var tab = document.getElementById('sourceTab'); + tab.className = ''; + tab.onclick = jscoverage_tab_click; + } + jscoverage_currentFile = file; + jscoverage_currentLine = line || 1; // when changing the source, always scroll to top + var fileDiv = document.getElementById('fileDiv'); + fileDiv.innerHTML = jscoverage_currentFile; + jscoverage_recalculateSourceTab(); + return; + } + }, 50); +} + +/** +Calculates coverage statistics for the current source file. +*/ +function jscoverage_recalculateSourceTab() { + if (! jscoverage_currentFile) { + jscoverage_endLengthyOperation(); + return; + } + var progressLabel = document.getElementById('progressLabel'); + progressLabel.innerHTML = 'Calculating coverage ...'; + var progressBar = document.getElementById('progressBar'); + ProgressBar.setPercentage(progressBar, 20); + setTimeout(jscoverage_makeTable, 0); +} + +// ----------------------------------------------------------------------------- +// tabs + +/** +Initializes the tab control. This function must be called when the document is +loaded. +*/ +function jscoverage_initTabControl() { + var tabs = document.getElementById('tabs'); + var i; + var child; + var tabNum = 0; + for (i = 0; i < tabs.childNodes.length; i++) { + child = tabs.childNodes.item(i); + if (child.nodeType === 1) { + if (child.className !== 'disabled') { + child.onclick = jscoverage_tab_click; + } + tabNum++; + } + } + jscoverage_selectTab(0); +} + +/** +Selects a tab. +@param tab the integer index of the tab (0, 1, 2, or 3) + OR + the ID of the tab element + OR + the tab element itself +*/ +function jscoverage_selectTab(tab) { + if (typeof tab !== 'number') { + tab = jscoverage_tabIndexOf(tab); + } + var tabs = document.getElementById('tabs'); + var tabPages = document.getElementById('tabPages'); + var nodeList; + var tabNum; + var i; + var node; + + nodeList = tabs.childNodes; + tabNum = 0; + for (i = 0; i < nodeList.length; i++) { + node = nodeList.item(i); + if (node.nodeType !== 1) { + continue; + } + + if (node.className !== 'disabled') { + if (tabNum === tab) { + node.className = 'selected'; + } + else { + node.className = ''; + } + } + tabNum++; + } + + nodeList = tabPages.childNodes; + tabNum = 0; + for (i = 0; i < nodeList.length; i++) { + node = nodeList.item(i); + if (node.nodeType !== 1) { + continue; + } + + if (tabNum === tab) { + node.className = 'selected TabPage'; + } + else { + node.className = 'TabPage'; + } + tabNum++; + } +} + +/** +Returns an integer (0, 1, 2, or 3) representing the index of a given tab. +@param tab the ID of the tab element + OR + the tab element itself +*/ +function jscoverage_tabIndexOf(tab) { + if (typeof tab === 'string') { + tab = document.getElementById(tab); + } + var tabs = document.getElementById('tabs'); + var i; + var child; + var tabNum = 0; + for (i = 0; i < tabs.childNodes.length; i++) { + child = tabs.childNodes.item(i); + if (child.nodeType === 1) { + if (child === tab) { + return tabNum; + } + tabNum++; + } + } +//#JSCOVERAGE_IF 0 + throw "Tab not found"; +//#JSCOVERAGE_ENDIF +} + +function jscoverage_tab_click(e) { + if (jscoverage_inLengthyOperation) { + return; + } + var target; +//#JSCOVERAGE_IF + if (e) { + target = e.target; + } + else if (window.event) { + // IE + target = window.event.srcElement; + } + if (target.className === 'selected') { + return; + } + jscoverage_beginLengthyOperation(); + setTimeout(function() { + if (target.id === 'summaryTab') { + var tbody = document.getElementById("summaryTbody"); + while (tbody.hasChildNodes()) { + tbody.removeChild(tbody.firstChild); + } + } + else if (target.id === 'sourceTab') { + var sourceDiv = document.getElementById('sourceDiv'); + sourceDiv.innerHTML = ''; + } + jscoverage_selectTab(target); + if (target.id === 'summaryTab') { + jscoverage_recalculateSummaryTab(); + } + else if (target.id === 'sourceTab') { + jscoverage_recalculateSourceTab(); + } + else { + jscoverage_endLengthyOperation(); + } + }, 50); +} + +// ----------------------------------------------------------------------------- +// progress bar + +var ProgressBar = { + init: function(element) { + element._percentage = 0; + + /* doing this via JavaScript crashes Safari */ +/* + var pctGraph = document.createElement('div'); + pctGraph.className = 'pctGraph'; + element.appendChild(pctGraph); + var covered = document.createElement('div'); + covered.className = 'covered'; + pctGraph.appendChild(covered); + var pct = document.createElement('span'); + pct.className = 'pct'; + element.appendChild(pct); +*/ + + ProgressBar._update(element); + }, + setPercentage: function(element, percentage) { + element._percentage = percentage; + ProgressBar._update(element); + }, + _update: function(element) { + var pctGraph = element.getElementsByTagName('div').item(0); + var covered = pctGraph.getElementsByTagName('div').item(0); + var pct = element.getElementsByTagName('span').item(0); + pct.innerHTML = element._percentage.toString() + '%'; + covered.style.width = element._percentage + 'px'; + } +}; + +// ----------------------------------------------------------------------------- +// reports + +function jscoverage_pad(s) { + return '0000'.substr(s.length) + s; +} + +function jscoverage_quote(s) { + return '"' + s.replace(/[\u0000-\u001f"\\\u007f-\uffff]/g, function (c) { + switch (c) { + case '\b': + return '\\b'; + case '\f': + return '\\f'; + case '\n': + return '\\n'; + case '\r': + return '\\r'; + case '\t': + return '\\t'; + // IE doesn't support this + /* + case '\v': + return '\\v'; + */ + case '"': + return '\\"'; + case '\\': + return '\\\\'; + default: + return '\\u' + jscoverage_pad(c.charCodeAt(0).toString(16)); + } + }) + '"'; +} + +function jscoverage_serializeCoverageToJSON() { + var json = []; + for (var file in _$jscoverage) { + if (! _$jscoverage.hasOwnProperty(file)) { + continue; + } + + var coverage = _$jscoverage[file]; + + var array = []; + var length = coverage.length; + for (var line = 0; line < length; line++) { + var value = coverage[line]; + if (value === undefined || value === null) { + value = 'null'; + } + array.push(value); + } + + var source = coverage.source; + var lines = []; + length = source.length; + for (var line = 0; line < length; line++) { + lines.push(jscoverage_quote(source[line])); + } + + json.push(jscoverage_quote(file) + ':{"coverage":[' + array.join(',') + '],"source":[' + lines.join(',') + ']}'); + } + return '{' + json.join(',') + '}'; +} + +function jscoverage_storeButton_click() { + if (jscoverage_inLengthyOperation) { + return; + } + + jscoverage_beginLengthyOperation(); + var img = document.getElementById('storeImg'); + img.style.visibility = 'visible'; + + var request = jscoverage_createRequest(); + request.open('POST', '/jscoverage-store', true); + request.onreadystatechange = function (event) { + if (request.readyState === 4) { + var message; + try { + if (request.status !== 200 && request.status !== 201 && request.status !== 204) { + throw request.status; + } + message = request.responseText; + } + catch (e) { + if (e.toString().search(/^\d{3}$/) === 0) { + message = e + ': ' + request.responseText; + } + else { + message = 'Could not connect to server: ' + e; + } + } + + jscoverage_endLengthyOperation(); + var img = document.getElementById('storeImg'); + img.style.visibility = 'hidden'; + + var div = document.getElementById('storeDiv'); + div.appendChild(document.createTextNode(new Date() + ': ' + message)); + div.appendChild(document.createElement('br')); + } + }; + request.setRequestHeader('Content-Type', 'application/json'); + var json = jscoverage_serializeCoverageToJSON(); + request.setRequestHeader('Content-Length', json.length.toString()); + request.send(json); +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/readCoverage.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/readCoverage.js new file mode 100644 index 000000000..fbd437322 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/coverage/readCoverage.js @@ -0,0 +1,98 @@ +/** + * + */ +///import source +function creatJscoverage(){ + try { + if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { + // this is a browser window that was opened from another window + if (! top.opener._$jscoverage) { + top.opener._$jscoverage = {}; + } + } + } + + catch (e) {} + try { + if (typeof top === 'object' && top !== null) { + // this is a browser window + try { + if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { + top._$jscoverage = top.opener._$jscoverage; + } + } + catch (e) {} + + if (! top._$jscoverage) { + top._$jscoverage = {}; + } + } + } + catch (e) {} + + try { + if (typeof top === 'object' && top !== null && top._$jscoverage) { + _$jscoverage = top._$jscoverage; + } + } + catch (e) {} + if (typeof _$jscoverage !== 'object') { + _$jscoverage = {}; + } +} + +(function(){ + var xmlDoc; + if (window.ActiveXObject) + { + xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); + if(xmlDoc != null) + { + xmlDoc.async=true; + xmlDoc.load("../HTML_Report/report.xml"); + } + } + else if(document.implementation && document.implementation.createDocument) + { + var xmlHttp=new window.XMLHttpRequest(); + xmlHttp.open("GET","../HTML_Report/report.xml",false); + xmlHttp.send(null); + xmlDoc = xmlHttp.responseXML; + }else{ + xmlDom=null; + } + function readCoverage(){ + creatJscoverage(); + var nodeNumber=xmlDoc.getElementsByTagName("testsuite").length; + for(i=0;i li:last-child { + border-radius: 0 0 15px 15px; + -moz-border-radius: 0 0 15px 15px; + -webkit-border-bottom-right-radius: 15px; + -webkit-border-bottom-left-radius: 15px; +} + +#qunit-tests .fail { color: #000000; background-color: #EE5757; } +#qunit-tests .fail .test-name, +#qunit-tests .fail .module-name { color: #000000; } + +#qunit-tests .fail .test-actual { color: #EE5757; } +#qunit-tests .fail .test-expected { color: green; } + +#qunit-banner.qunit-fail { background-color: #EE5757; } + + +/** Result */ + +#qunit-testresult { + padding: 0.5em 0.5em 0.5em 2.5em; + + color: #2b81af; + background-color: #D2E0E6; + + border-bottom: 1px solid white; +} + +/** Fixture */ + +#qunit-fixture { + position: absolute; + top: -10000px; + left: -10000px; +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/css/tangramtest.css b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/css/tangramtest.css new file mode 100644 index 000000000..cd306e139 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/css/tangramtest.css @@ -0,0 +1,173 @@ +* { + margin: 0; + padding: 0; +} + +html { + border: 0; + height: 100%; +} + +body { + font: 12px/1.5 Lucida Grande, Helvetica, Arial, sans-serif; + background: #F3F1F1; + color: #41464D; +} + +body,#container { + width: 100%; + height: 100%; +} + +.clear { /* generic container (i.e. div) for floating buttons */ + overflow: hidden; + width: 100%; +} + +a { + text-decoration: none; + overflow: hidden; +} + +#title { + top: 0; + left: 0; + width: 100%; + padding: 5px 0; + background: #aaa; + background: #41464D; + color: #F3F1F1; + height: 30px; +} + +a:link,a:visited { + color: #528CE0; +} + +a:hover,a:active { + color: #41464D !important; + cursor: pointer !important; +} + +#title h1 { + height: 30px; + font: 25px/1.1 Arial, sans-serif; + font-weight: bolder; + float: left; + margin: 1px 0 2px 20px; + text-shadow: 0 2px 2px rgba(0, 0, 0, 0.4); +} + +h3 { + font-size: 14px; + padding: 3px 5px 1px; +} + +.control { + background: #d5ded7; + width: 99%; +} + +.testlist { + max-height: 200px; + overflow-y: scroll; + border-style: double; +} + +.testlist a { + display: block; + width: 150px; + color: #657528; + background: #d5dea7; + border: 1px solid #c8dc7b; + margin: 5px 0 0 5px; + text-indent: 5px; + line-height: 24px; + font-size: 14px; + float: left; +} + +a.button { + background: transparent url('bg_button_a.gif') no-repeat scroll top + right; + color: #444; + display: block; + float: left; + font: normal 12px arial, sans-serif; + height: 24px; + margin-right: 6px; + padding-right: 18px; /* sliding doors padding */ + text-decoration: none; +} + +a.button span { + background: transparent url('bg_button_span.gif') no-repeat; + display: block; + line-height: 14px; + padding: 5px 0 5px 18px; +} + +a.button:active { + background-position: bottom right; + color: #000; + outline: none; /* hide dotted outline in Firefox */ +} + +a.button:active span { + background-position: bottom left; + padding: 6px 0 4px 18px; /* push text down 1px */ +} + +.testlist a:link { + +} + +.testlist a:visited { + +} + +.testlist a:hover { + background: #c8dc7b; +} + +.testlist a.jsframe_jsspec { + background: #DDDDDD +} + +.testlist a.running_case { + color: yellow; +} + +.testlist a.fail_case { + color: red; +} + +.testlist a.pass_case { + color: green; +} + +.runningarea { + height: 60%; +} + +.runningmaindiv { + height: 99%; +} + +.runningframe { + height: 99.99%; + width: 99.99%; +} + +.runningstatus { + clear: both; + height: 10%; + border: solid +} + +.reportarea { + padding: 10px; + border: 10px blue; + max-height: 200px; + overflow-y: scroll; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/css/testsuite.css b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/css/testsuite.css new file mode 100644 index 000000000..5714bf4a5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/css/testsuite.css @@ -0,0 +1,119 @@ + +ol#qunit-tests { + font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; + margin:0; + padding:0; + list-style-position:inside; + + font-size: smaller; +} +ol#qunit-tests li{ + padding:0.4em 0.5em 0.4em 2.5em; + border-bottom:1px solid #fff; + font-size:small; + list-style-position:inside; +} +ol#qunit-tests li ol{ + box-shadow: inset 0px 2px 13px #999; + -moz-box-shadow: inset 0px 2px 13px #999; + -webkit-box-shadow: inset 0px 2px 13px #999; + margin-top:0.5em; + margin-left:0; + padding:0.5em; + background-color:#fff; + border-radius:15px; + -moz-border-radius: 15px; + -webkit-border-radius: 15px; +} +ol#qunit-tests li li{ + border-bottom:none; + margin:0.5em; + background-color:#fff; + list-style-position: inside; + padding:0.4em 0.5em 0.4em 0.5em; +} + +ol#qunit-tests li li.pass{ + border-left:26px solid #C6E746; + background-color:#fff; + color:#5E740B; + } +ol#qunit-tests li li.fail{ + border-left:26px solid #EE5757; + background-color:#fff; + color:#710909; +} +ol#qunit-tests li.pass{ + background-color:#D2E0E6; + color:#528CE0; +} +ol#qunit-tests li.fail{ + background-color:#EE5757; + color:#000; +} +ol#qunit-tests li strong { + cursor:pointer; +} +h1#qunit-header{ + background-color:#0d3349; + margin:0; + padding:0.5em 0 0.5em 1em; + color:#fff; + font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; + border-top-right-radius:15px; + border-top-left-radius:15px; + -moz-border-radius-topright:15px; + -moz-border-radius-topleft:15px; + -webkit-border-top-right-radius:15px; + -webkit-border-top-left-radius:15px; + text-shadow: rgba(0, 0, 0, 0.5) 4px 4px 1px; +} +h2#qunit-banner{ + font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; + height:5px; + margin:0; + padding:0; +} +h2#qunit-banner.qunit-pass{ + background-color:#C6E746; +} +h2#qunit-banner.qunit-fail, #qunit-testrunner-toolbar { + background-color:#EE5757; +} +#qunit-testrunner-toolbar { + font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; + padding:0; + /*width:80%;*/ + padding:0em 0 0.5em 2em; + font-size: small; +} +h2#qunit-userAgent { + font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; + background-color:#2b81af; + margin:0; + padding:0; + color:#fff; + font-size: small; + padding:0.5em 0 0.5em 2.5em; + text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; +} +p#qunit-testresult{ + font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; + margin:0; + font-size: small; + color:#2b81af; + border-bottom-right-radius:15px; + border-bottom-left-radius:15px; + -moz-border-radius-bottomright:15px; + -moz-border-radius-bottomleft:15px; + -webkit-border-bottom-right-radius:15px; + -webkit-border-bottom-left-radius:15px; + background-color:#D2E0E6; + padding:0.5em 0.5em 0.5em 2.5em; +} +strong b.fail{ + color:#710909; + } +strong b.pass{ + color:#5E740B; + } diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/filehelper.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/filehelper.php new file mode 100644 index 000000000..bd4d691a1 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/filehelper.php @@ -0,0 +1,57 @@ + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/geneHTML.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/geneHTML.php new file mode 100644 index 000000000..6549fe7f0 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/geneHTML.php @@ -0,0 +1,209 @@ +来设置css是因为有的邮件客户端会过滤这样的信息 + * + * ***/ +function geneHTML($caseList, $name=''){ + date_default_timezone_set('PRC'); +// $url = (isset ($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '') . $_SERVER['PHP_SELF']; + $url =""; + $html = " +
    +

    自动化用例测试结果".date('Y-m-d H:i:s')."

    +网页版 + +".getTrCase($caseList,true,1)."
    fail的用例统计
    用例名称


    + +".getTrCase($caseList,false,1)."".getTrCase($caseList,false,0)."
    全部用例统计
    用例名称
    未覆盖到的用例
    "; +// ."
    "._srcOnlyList()."" + return $html; +} + +/** + * 创建遗漏用例列表 + * FIXME: 需要过滤package类型,考虑使用js名称同名目录存在进行过滤或者白名单 + */ +function _srcOnlyList(){ + require 'case.class.php'; + $list = Kiss::listSrcOnly(false); + $len = sizeof($list); + $flag="
    遗漏列表:总计$len,未过滤无需用例的package类型
    "; + $flag.=implode("
    ", $list); + $flag.="
    "; + return $flag; +} + +/** + * + * 根据实际浏览器书目确认生成表头 + * @param unknown_type $caseList + */ +function getThBrowser($caseList){ + //创建浏览器相关单元格 + $thBrowser = ''; + $count = 0; + foreach ($caseList as $casename => $casedetail) { + //每一个用例 + foreach ($casedetail as $b => $info) { + $thBrowser .= "$b"; + $count++; + } + $thBrowser .=""; + break;//遍历一次就知道所有浏览器的信息 + } + for($index = 0; $index < $count; $index++) { + $thBrowser .= "covfailtotal"; + } + + return $thBrowser.""; +} + +/** + * + * 根据执行结果生成单元格信息 + * @param unknown_type $caseList + */ +function getTrCase($caseList,$onlyFail,$onlyCoverd){ +//$onlyFail 为真时,只显示 fail 的用例 + //$onlyCoverd 为0时,只显示全浏览器覆盖率为0的用例;为1时,只显示全浏览器覆盖率不为0的用例;为其他时,显示所有的用例 + //创建case名对应的单元格 + $totalTrCase = ''; + require_once 'config.php'; + $rowColor = '#B0E0E6';//标记行的颜色,单双数行显示的背景颜色不同 + $numBro = count(Config::getBrowserSet($configBrowserSet)); + $averageCov = 0;//所有用例的全浏览器覆盖率的平均值(全浏览器覆盖率为0的不计) + $numCov = 0;//全浏览器覆盖率不为0的用例数量 + foreach ($caseList as $casename => $caseDetail) { + //每一个用例 + $ifFail = false; + $cnurl = implode('.', explode('_', $casename)); + $trCase = ''; + $totalCov = calTotalCov($caseDetail,$numBro); + $averageCov +=$totalCov; + $numCov = $totalCov==0?$numCov:$numCov+1; + if(($onlyCoverd==0&&$totalCov!=0)||($onlyCoverd==1&&$totalCov==0))//$onlyCoverd 为0时,只显示全浏览器覆盖率为0的用例;为1时,只显示全浏览器覆盖率不为0的用例; + continue; + if(!$onlyFail){//对于展示 fail 的用例的列表,不显示全浏览器覆盖率 + $trCase .= "".$totalCov.($totalCov=="_"?"":"%").""; + } + foreach ($caseDetail as $br => $infos) { + //$b为browser名字,$info为详细信息 + $fail = $infos['fail']; + $ifFail = $fail==0?$ifFail:true; + $total = $infos['total']; + $cov = $infos['cov']; + $color = $fail == 0 ? $rowColor : '#CD5C5C'; + $PercentSign = $cov=='_'?'':'%'; + $trCase .= "".$cov.$PercentSign."".$fail."".$total.""; + } + $trCase ="运行$casename".$trCase.""; + if(!$onlyFail||$ifFail){ + $totalTrCase =$totalTrCase.$trCase; + $rowColor = $rowColor=='#F0FFFF'?'#B0E0E6':'#F0FFFF'; + } + else; + } + $averageCov = number_format($averageCov/$numCov,1); + if($onlyCoverd==0) + $tableContent = $totalTrCase; + elseif(!$onlyFail) + $tableContent = "总覆盖率
    (平均值:".$averageCov."%)".getThBrowser($caseList).$totalTrCase; + else + $tableContent = getThBrowser($caseList).$totalTrCase; + return $tableContent; +} + +/** + * + * 计算总覆盖率信息 + * @param unknown_type $caseDetail + * @param unknown_type $brcount + */ +function calTotalCov($caseDetail,$brcount){ + $length = -1; + $num_statements = 0; + $num_executed = 0; + $totalInfo = null;//数组,记录全浏览器的覆盖情况,对文件中的每一行:覆盖为1,没覆盖为0,不计数为2 + $flag = 1;//$flag==-1时,各个浏览器覆盖率记录的文件信息有冲突,不能计算出全浏览器覆盖率(统计的文件长度不同/标记为2的不计入统计的行信息不同) + foreach ($caseDetail as $caseInfo){ + //如果recordCovForBrowser为空,跳过这个$caseInfo + if($caseInfo['recordCovForBrowser']==''){ + continue; + } + $infos = explode(',',$caseInfo['recordCovForBrowser']); + + $length = ($length==-1||$length==count($infos))?count($infos):-1; + if($length==-1||$length!=count($infos)) + break;//统计的文件长度不同 + else + ; + if($totalInfo==null){ +// if(count($infos)==1){ +// $flag = 0;//没有覆盖率信息 +// break; +// } + for($i=0;$i \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/geneHistory.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/geneHistory.php new file mode 100644 index 000000000..7448bfd5e --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/geneHistory.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/geneXML.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/geneXML.php new file mode 100644 index 000000000..ae0742c1b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/geneXML.php @@ -0,0 +1,82 @@ +testsuite as $testsuite){ + foreach ($testsuite->testcase as $testResult) { + // $totalCov = 0; + $browser = $testResult['browserInfo']; + $host = $testResult['hostInfo']; + $caseName = $testResult['name']; //得到用例名称 + settype($caseName, "string"); //$caseName本来类型为object,需要做转换 + $fail = $testResult['failNumber']; + $total = $testResult['totalNumber']; + $cov = $testResult['cov']; + settype($browser, "string"); + settype($host, "string"); + settype($fail, "string"); + settype($total, "string"); + settype($cov, "float"); + + if (!array_key_exists($caseName, $caseList)) { //如果这个用例不存在 + $caseInfo = array ( + 'hostInfo' => $host, + 'fail' => $fail, + 'total' => $total, + 'cov' => $cov + ); + // $totalCov += $cov; + $caseList[$caseName] = array ( + $browser => $caseInfo//, + // 'totalCov'=>$totalCov + ); + + // $caseList['totalCov'] = $totalCov; + } else { //否则添加到相应的用例中去 + $foundCase = $caseList[$caseName]; //找到用例名称对应的array,$caseName为key + if (!array_key_exists($browser, $foundCase)) { //如果没有该浏览器信息,则添加 + // $totalCov += $cov; + $caseList[$caseName][$browser] = array ( + 'hostInfo' => $host, + 'fail' => $fail, + 'total' => $total, + 'cov' => $cov + ); + // $caseList[$caseName]['totalCov'] = $totalCov; + } else { + $foundBrowser = $foundCase[$browser]; //有这个浏览器 + array_push($foundBrowser, array ( + 'hostInfo' => $host, + 'fail' => $fail, + 'total' => $total, + 'cov' => $cov + )); + } + } + + } + } + + //根据需求添加仅记录失败情况的接口 + if($onlyfails){//如果仅考虑失败情况,此处根据用例情况过滤 + foreach($caseList as $name => $info){ + $all_success = true;//记录当前用例是否全部运行成功 + foreach($info as $b => $result){ + if($result['fail'] > 0) + $all_success = false;//如果有失败情况则终止循环并进入下一个用例分析 + break; + } + //if($all_success) //如果全部通过则从记录中移除 + //unset($caseList[$name]); + } + } + return $caseList; +} +?> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/import.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/import.php new file mode 100644 index 000000000..c1672bd64 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/import.php @@ -0,0 +1,71 @@ +$d){ +// if(preg_match("/editorui/",$dd)){ +// echo "*************".file_get_contents($d.$path)."************"; +// } + if(file_exists($d.$path)){ + $source.= file_get_contents($d.$path); + $source.="\n";//读取文件内容必须加个回车 + break; + } + } + } + } + return $source; +} +//update by bell 2011-03-25, 更新覆盖率相关逻辑 +echo importSrc($cov); +?> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/js/UserAction manual.rar b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/js/UserAction manual.rar new file mode 100644 index 000000000..75853cb98 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/js/UserAction manual.rar differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/js/UserAction.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/js/UserAction.js new file mode 100644 index 000000000..17b784798 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/js/UserAction.js @@ -0,0 +1,1888 @@ +/** + * 测试用例库文件,提供如event mock、iframe封装等各种常用功能 部分方法来源于YUI测试框架 + */ +UserAction = { + beforedispatch:null, +// flag : true, + isf /* is function ? */:function (value) { + return value && (typeof value == 'function'); + }, + isb /* is boolean? */:function (value) { + return value && (typeof value == 'boolean'); + }, + iso /* is object? */:function (value) { + return value && (typeof value == 'object'); + }, + iss /* is string? */:function (value) { + return value && (typeof value == 'string'); + }, + isn /* is number? */:function (value) { + return value && (typeof value == 'number'); + }, + // -------------------------------------------------------------------------- + // Generic event methods + // -------------------------------------------------------------------------- + + /** + * Simulates a key event using the given event information to populate the + * generated event object. This method does browser-equalizing calculations + * to account for differences in the DOM and IE event models as well as + * different browser quirks. Note: keydown causes Safari 2.x to crash. + * + * @method simulateKeyEvent + * @private + * @static + * @param {HTMLElement} + * target The target of the given event. + * @param {String} + * type The type of event to fire. This can be any one of the + * following: keyup, keydown, and keypress. + * @param {Boolean} + * bubbles (Optional) Indicates if the event can be bubbled up. + * DOM Level 3 specifies that all key events bubble by default. + * The default is true. + * @param {Boolean} + * cancelable (Optional) Indicates if the event can be canceled + * using preventDefault(). DOM Level 3 specifies that all key + * events can be cancelled. The default is true. + * @param {Window} + * view (Optional) The view containing the target. This is + * typically the window object. The default is window. + * @param {Boolean} + * ctrlKey (Optional) Indicates if one of the CTRL keys is + * pressed while the event is firing. The default is false. + * @param {Boolean} + * altKey (Optional) Indicates if one of the ALT keys is pressed + * while the event is firing. The default is false. + * @param {Boolean} + * shiftKey (Optional) Indicates if one of the SHIFT keys is + * pressed while the event is firing. The default is false. + * @param {Boolean} + * metaKey (Optional) Indicates if one of the META keys is + * pressed while the event is firing. The default is false. + * @param {int} + * keyCode (Optional) The code for the key that is in use. The + * default is 0. + * @param {int} + * charCode (Optional) The Unicode code for the character + * associated with the key being used. The default is 0. + */ + simulateKeyEvent:function (target /* :HTMLElement */, type /* :String */, bubbles /* :Boolean */, cancelable /* :Boolean */, view /* :Window */, ctrlKey /* :Boolean */, altKey /* :Boolean */, shiftKey /* :Boolean */, metaKey /* :Boolean */, keyCode /* :int */, charCode /* :int */) /* :Void */ { + // check target + target = typeof target == 'string' ? document.getElementById(target) + : target; + if (!target) { + throw new Error("simulateKeyEvent(): Invalid target."); + } + + // check event type + if (typeof type == 'string') { + type = type.toLowerCase(); + switch (type) { + case "compositionend": + case "compositionstart": + case "paste": + case "cut": + case "keyup": + case "keydown": + case "keypress": + break; + case "textevent": // DOM Level 3 + type = "keypress"; + break; + // @TODO was the fallthrough intentional, if so throw error + default: + throw new Error("simulateKeyEvent(): Event type '" + type + + "' not supported."); + } + } else { + throw new Error("simulateKeyEvent(): Event type must be a string."); + } + + // setup default values + if (!this.isb(bubbles)) { + bubbles = true; // all key events bubble + } + if (!this.isb(cancelable)) { + cancelable = true; // all key events can be cancelled + } + if (!this.iso(view)) { + view = window; // view is typically window + } + if (!this.isb(ctrlKey)) { + ctrlKey = false; + } + if (!this.isb(typeof altKey == 'boolean')) { + altKey = false; + } + if (!this.isb(shiftKey)) { + shiftKey = false; + } + if (!this.isb(metaKey)) { + metaKey = false; + } + if (!(typeof keyCode == 'number')) { + keyCode = 0; + } + if (!(typeof charCode == 'number')) { + charCode = 0; + } + + // try to create a mouse event + var customEvent /* :MouseEvent */ = null; + + // check for DOM-compliant browsers first + if (this.isf(document.createEvent)) { + + try { + + // try to create key event + customEvent = document.createEvent("KeyEvents"); + + /* + * Interesting problem: Firefox implemented a non-standard + * version of initKeyEvent() based on DOM Level 2 specs. Key + * event was removed from DOM Level 2 and re-introduced in DOM + * Level 3 with a different interface. Firefox is the only + * browser with any implementation of Key Events, so for now, + * assume it's Firefox if the above line doesn't error. + */ + // TODO: Decipher between Firefox's implementation and a correct + // one. + customEvent.initKeyEvent(type, bubbles, cancelable, view, + ctrlKey, altKey, shiftKey, metaKey, keyCode, charCode); + + } catch (ex /* :Error */) { + + /* + * If it got here, that means key events aren't officially + * supported. Safari/WebKit is a real problem now. WebKit 522 + * won't let you set keyCode, charCode, or other properties if + * you use a UIEvent, so we first must try to create a generic + * event. The fun part is that this will throw an error on + * Safari 2.x. The end result is that we need another + * try...catch statement just to deal with this mess. + */ + try { + + // try to create generic event - will fail in Safari 2.x + customEvent = document.createEvent("Events"); + + } catch (uierror /* :Error */) { + + // the above failed, so create a UIEvent for Safari 2.x + customEvent = document.createEvent("UIEvents"); + + } finally { + + customEvent.initEvent(type, bubbles, cancelable); + + // initialize + customEvent.view = view; + customEvent.altKey = altKey; + customEvent.ctrlKey = ctrlKey; + customEvent.shiftKey = shiftKey; + customEvent.metaKey = metaKey; + customEvent.keyCode = keyCode; + customEvent.charCode = charCode; + + } + + } + + // before dispatch + if (this.beforedispatch && typeof this.beforedispatch == 'function') + this.beforedispatch(customEvent); + this.beforedispatch = null; + + // fire the event + target.dispatchEvent(customEvent); + + } else if (this.iso(document.createEventObject)) { // IE + + // create an IE event object + customEvent = document.createEventObject(); + + // assign available properties + customEvent.bubbles = bubbles; + customEvent.cancelable = cancelable; + customEvent.view = view; + customEvent.ctrlKey = ctrlKey; + customEvent.altKey = altKey; + customEvent.shiftKey = shiftKey; + customEvent.metaKey = metaKey; + + /* + * IE doesn't support charCode explicitly. CharCode should take + * precedence over any keyCode value for accurate representation. + */ + customEvent.keyCode = (charCode > 0) ? charCode : keyCode; + + // before dispatch + if (this.beforedispatch && typeof this.beforedispatch == 'function') + this.beforedispatch(customEvent); + this.beforedispatch = null; + + // fire the event + target.fireEvent("on" + type, customEvent); + + } else { + throw new Error( + "simulateKeyEvent(): No event simulation framework present."); + } + + this.beforedispatch = null; + }, + + /** + * Simulates a mouse event using the given event information to populate the + * generated event object. This method does browser-equalizing calculations + * to account for differences in the DOM and IE event models as well as + * different browser quirks. + * + * @method simulateMouseEvent + * @private + * @static + * @param {HTMLElement} + * target The target of the given event. + * @param {String} + * type The type of event to fire. This can be any one of the + * following: click, dblclick, mousedown, mouseup, mouseout, + * mouseover, and mousemove. + * @param {Boolean} + * bubbles (Optional) Indicates if the event can be bubbled up. + * DOM Level 2 specifies that all mouse events bubble by default. + * The default is true. + * @param {Boolean} + * cancelable (Optional) Indicates if the event can be canceled + * using preventDefault(). DOM Level 2 specifies that all mouse + * events except mousemove can be cancelled. The default is true + * for all events except mousemove, for which the default is + * false. + * @param {Window} + * view (Optional) The view containing the target. This is + * typically the window object. The default is window. + * @param {int} + * detail (Optional) The number of times the mouse button has + * been used. The default value is 1. + * @param {int} + * screenX (Optional) The x-coordinate on the screen at which + * point the event occured. The default is 0. + * @param {int} + * screenY (Optional) The y-coordinate on the screen at which + * point the event occured. The default is 0. + * @param {int} + * clientX (Optional) The x-coordinate on the client at which + * point the event occured. The default is 0. + * @param {int} + * clientY (Optional) The y-coordinate on the client at which + * point the event occured. The default is 0. + * @param {Boolean} + * ctrlKey (Optional) Indicates if one of the CTRL keys is + * pressed while the event is firing. The default is false. + * @param {Boolean} + * altKey (Optional) Indicates if one of the ALT keys is pressed + * while the event is firing. The default is false. + * @param {Boolean} + * shiftKey (Optional) Indicates if one of the SHIFT keys is + * pressed while the event is firing. The default is false. + * @param {Boolean} + * metaKey (Optional) Indicates if one of the META keys is + * pressed while the event is firing. The default is false. + * @param {int} + * button (Optional) The button being pressed while the event is + * executing. The value should be 0 for the primary mouse button + * (typically the left button), 1 for the terciary mouse button + * (typically the middle button), and 2 for the secondary mouse + * button (typically the right button). The default is 0. + * @param {HTMLElement} + * relatedTarget (Optional) For mouseout events, this is the + * element that the mouse has moved to. For mouseover events, + * this is the element that the mouse has moved from. This + * argument is ignored for all other events. The default is null. + */ + simulateMouseEvent:function (target /* :HTMLElement */, type /* :String */, bubbles /* :Boolean */, cancelable /* :Boolean */, view /* :Window */, detail /* :int */, screenX /* :int */, screenY /* :int */, clientX /* :int */, clientY /* :int */, ctrlKey /* :Boolean */, altKey /* :Boolean */, shiftKey /* :Boolean */, metaKey /* :Boolean */, button /* :int */, relatedTarget /* :HTMLElement */,button) /* :Void */ { + + // check target + target = typeof target == 'string' ? document.getElementById(target) + : target; + if (!target) { + throw new Error("simulateMouseEvent(): Invalid target."); + } + + // check event type + if (this.iss(type)) { + type = type.toLowerCase(); + switch (type) { + case "mouseover": + case "mouseout": + case "mousedown": + case "mouseup": + case "click": + case "dblclick": + case "mousemove": + case "mouseenter":// 非标准支持,仅为测试提供,该项仅IE下work + case "mouseleave": + case "contextmenu": + case "dragend": + case "blur": + break; + default: + throw new Error("simulateMouseEvent(): Event type '" + type + + "' not supported."); + } + } else { + throw new Error( + "simulateMouseEvent(): Event type must be a string."); + } + + // setup default values + if (!this.isb(bubbles)) { + bubbles = true; // all mouse events bubble + } + if (!this.isb(cancelable)) { + cancelable = (type != "mousemove"); // mousemove is the only one + // that can't be cancelled + } + if (!this.iso(view)) { + view = window; // view is typically window + } + if (!this.isn(detail)) { + detail = 1; // number of mouse clicks must be at least one + } + if (!this.isn(screenX)) { + screenX = 0; + } + if (!this.isn(screenY)) { + screenY = 0; + } + if (!this.isn(clientX)) { + clientX = 0; + } + if (!this.isn(clientY)) { + clientY = 0; + } + if (!this.isb(ctrlKey)) { + ctrlKey = false; + } + if (!this.isb(altKey)) { + altKey = false; + } + if (!this.isb(shiftKey)) { + shiftKey = false; + } + if (!this.isb(metaKey)) { + metaKey = false; + } + if (!this.isn(button)) { + button = 0; + } + // try to create a mouse event + var customEvent /* :MouseEvent */ = null; + + // check for DOM-compliant browsers first + if (this.isf(document.createEvent)) { + + customEvent = document.createEvent("MouseEvents"); + // Safari 2.x (WebKit 418) still doesn't implement initMouseEvent() + if (this.browser.ie < 9 && customEvent.initMouseEvent) { + + customEvent.initMouseEvent(type, bubbles, cancelable, view, + detail, screenX, screenY, clientX, clientY, ctrlKey, + altKey, shiftKey, metaKey, button, relatedTarget); + } else { // Safari + + // the closest thing available in Safari 2.x is UIEvents + customEvent = document.createEvent("UIEvents"); + customEvent.initEvent(type, bubbles, cancelable); + customEvent.view = view; + customEvent.detail = detail; + customEvent.screenX = screenX; + customEvent.screenY = screenY; + customEvent.clientX = clientX; + customEvent.clientY = clientY; + customEvent.ctrlKey = ctrlKey; + customEvent.altKey = altKey; + customEvent.metaKey = metaKey; + customEvent.shiftKey = shiftKey; + customEvent.button = button; + customEvent.relatedTarget = relatedTarget; + } + + /* + * Check to see if relatedTarget has been assigned. Firefox versions + * less than 2.0 don't allow it to be assigned via initMouseEvent() + * and the property is readonly after event creation, so in order to + * keep YAHOO.util.getRelatedTarget() working, assign to the IE + * proprietary toElement property for mouseout event and fromElement + * property for mouseover event. + */ + if (relatedTarget && !customEvent.relatedTarget) { + if (type == "mouseout") { + customEvent.toElement = relatedTarget; + } else if (type == "mouseover") { + customEvent.fromElement = relatedTarget; + } + } + + // before dispatch + if (this.beforedispatch && typeof this.beforedispatch == 'function') + this.beforedispatch(customEvent); + this.beforedispatch = null; + + // fire the event + target.dispatchEvent(customEvent); + + } else if (this.iso(document.createEventObject)) { // IE + + // create an IE event object + customEvent = document.createEventObject(); + + // assign available properties + customEvent.bubbles = bubbles; + customEvent.cancelable = cancelable; + customEvent.view = view; + customEvent.detail = detail; + customEvent.screenX = screenX; + customEvent.screenY = screenY; + customEvent.clientX = clientX; + customEvent.clientY = clientY; + customEvent.ctrlKey = ctrlKey; + customEvent.altKey = altKey; + customEvent.metaKey = metaKey; + customEvent.shiftKey = shiftKey; + + // fix button property for IE's wacky implementation + switch (button) { + case 0: + customEvent.button = 1; + break; + case 1: + customEvent.button = 4; + break; + case 2: + customEvent.button = 2; + // leave as is + break; + default: + customEvent.button = 0; + } + + /* + * Have to use relatedTarget because IE won't allow assignment to + * toElement or fromElement on generic events. This keeps + * YAHOO.util.customEvent.getRelatedTarget() functional. + */ + customEvent.relatedTarget = relatedTarget; + + // before dispatch + if (this.beforedispatch && typeof this.beforedispatch == 'function') + this.beforedispatch(customEvent); + this.beforedispatch = null; + // fire the event + target.fireEvent("on" + type, customEvent); + + } else { + throw new Error( + "simulateMouseEvent(): No event simulation framework present."); + } + }, + + // -------------------------------------------------------------------------- + // Mouse events + // -------------------------------------------------------------------------- + + /** + * Simulates a mouse event on a particular element. + * + * @param {HTMLElement} + * target The element to click on. + * @param {String} + * type The type of event to fire. This can be any one of the + * following: click, dblclick, mousedown, mouseup, mouseout, + * mouseover, and mousemove. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method mouseEvent + * @static + */ + fireMouseEvent:function (target /* :HTMLElement */, type /* :String */, options /* :Object */) /* :Void */ { + options = options || {}; + this.simulateMouseEvent(target, type, options.bubbles, + options.cancelable, options.view, options.detail, + options.screenX, options.screenY, options.clientX, + options.clientY, options.ctrlKey, options.altKey, + options.shiftKey, options.metaKey, options.button, + options.relatedTarget,options.button); + }, + + /** + * Simulates a click on a particular element. + * + * @param {HTMLElement} + * target The element to click on. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method click + * @static + */ + click:function (target /* :HTMLElement */, options /* :Object */) /* :Void */ { + this.fireMouseEvent(target, "click", options); + }, + + /** + * Simulates a double click on a particular element. + * + * @param {HTMLElement} + * target The element to double click on. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method dblclick + * @static + */ + dblclick:function (target /* :HTMLElement */, options /* :Object */) /* :Void */ { + this.fireMouseEvent(target, "dblclick", options); + }, + + /** + * Simulates a mousedown on a particular element. + * + * @param {HTMLElement} + * target The element to act on. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method mousedown + * @static + */ + mousedown:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { + this.fireMouseEvent(target, "mousedown", options); + }, + + /** + * Simulates a mousemove on a particular element. + * + * @param {HTMLElement} + * target The element to act on. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method mousemove + * @static + */ + mousemove:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { + this.fireMouseEvent(target, "mousemove", options); + }, + + /** + * Simulates a mouseout event on a particular element. Use "relatedTarget" + * on the options object to specify where the mouse moved to. Quirks: + * Firefox less than 2.0 doesn't set relatedTarget properly, so toElement is + * assigned in its place. IE doesn't allow toElement to be be assigned, so + * relatedTarget is assigned in its place. Both of these concessions allow + * YAHOO.util.Event.getRelatedTarget() to work correctly in both browsers. + * + * @param {HTMLElement} + * target The element to act on. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method mouseout + * @static + */ + mouseout:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { + this.fireMouseEvent(target, "mouseout", options); + }, + + /** + * Simulates a mouseover event on a particular element. Use "relatedTarget" + * on the options object to specify where the mouse moved from. Quirks: + * Firefox less than 2.0 doesn't set relatedTarget properly, so fromElement + * is assigned in its place. IE doesn't allow fromElement to be be assigned, + * so relatedTarget is assigned in its place. Both of these concessions + * allow YAHOO.util.Event.getRelatedTarget() to work correctly in both + * browsers. + * + * @param {HTMLElement} + * target The element to act on. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method mouseover + * @static + */ + mouseover:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { + this.fireMouseEvent(target, "mouseover", options); + }, + + /** + * Simulates a mouseup on a particular element. + * + * @param {HTMLElement} + * target The element to act on. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method mouseup + * @static + */ + mouseup:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { + this.fireMouseEvent(target, "mouseup", options); + }, + mouseenter:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { + this.fireMouseEvent(target, "mouseenter", options); + }, + mouseleave:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { + this.fireMouseEvent(target, "mouseleave", options); + }, + /** + * Simulates a contextmenu on a particular element. + * + * @param {HTMLElement} + * target The element to show contextmenu. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method contextmenu + * @static + */ + contextmenu:function (target /* :HTMLElement */, options /* :Object */) /* :Void */ { + this.fireMouseEvent(target, "contextmenu", options); + }, + /** + * Simulates a dragend on a particular element. + * + * @param {HTMLElement} + * target The element to show dragend. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method dragend + * @static + */ + dragend:function (target /* :HTMLElement */, options /* :Object */) /* :Void */ { + this.fireMouseEvent(target, "dragend", options); + }, + /** + * Simulates a blur on a particular element. + * + * @param {HTMLElement} + * target The element to show blur. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method blur + * @static + */ + blur:function (target /* :HTMLElement */, options /* :Object */) /* :Void */ { + this.fireMouseEvent(target, "blur", options); + }, + dragto:function (target, options) { + var me = this; + me.mousemove(target, { + clientX:options.startX, + clientY:options.startY + }); + setTimeout(function () { + me.mousedown(target, { + clientX:options.startX, + clientY:options.startY + }); + setTimeout(function () { + me.mousemove(target, { + clientX:options.endX, + clientY:options.endY + }); + setTimeout(function () { + me.mouseup(target, { + clientX:options.endX, + clientY:options.endY + }); + if (options.callback) + options.callback(); + }, options.aftermove || 20); + }, options.beforemove || 20); + }, options.beforestart || 50); + }, + + // -------------------------------------------------------------------------- + // Key events + // -------------------------------------------------------------------------- + + /** + * Fires an event that normally would be fired by the keyboard (keyup, + * keydown, keypress). Make sure to specify either keyCode or charCode as an + * option. + * + * @private + * @param {String} + * type The type of event ("keyup", "keydown" or "keypress"). + * @param {HTMLElement} + * target The target of the event. + * @param {Object} + * options Options for the event. Either keyCode or charCode are + * required. + * @method fireKeyEvent + * @static + */ + fireKeyEvent:function (type /* :String */, target /* :HTMLElement */, options /* :Object */) /* :Void */ { + options = options || {}; + this.simulateKeyEvent(target, type, options.bubbles, + options.cancelable, options.view, options.ctrlKey, + options.altKey, options.shiftKey, options.metaKey, + options.keyCode, options.charCode); + }, + + /** + * Simulates a cut event on a particular element. + * + * @param {HTMLElement} + * target The element to act on. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method cut + * @static + */ + cut:function (target /* :HTMLElement */, options /* :Object */) /* :Void */ { + this.fireKeyEvent("cut", target, options); + }, + + /** + * Simulates a paste event on a particular element. + * + * @param {HTMLElement} + * target The element to act on. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method paste + * @static + */ + paste:function ( target /* :HTMLElement */, options /* :Object */ ) /* :Void */ { + this.fireKeyEvent( "paste", target, options ); + }, + + /** + * Simulates a keydown event on a particular element. + * + * @param {HTMLElement} + * target The element to act on. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method keydown + * @static + */ + keydown:function (target /* :HTMLElement */, options /* :Object */) /* :Void */ { + this.fireKeyEvent("keydown", target, options); + }, + + /** + * Simulates a keypress on a particular element. + * + * @param {HTMLElement} + * target The element to act on. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method keypress + * @static + */ + keypress:function (target /* :HTMLElement */, options /* :Object */) /* :Void */ { + this.fireKeyEvent("keypress", target, options); + }, + + /** + * Simulates a keyup event on a particular element. + * + * @param {HTMLElement} + * target The element to act on. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method keyup + * @static + */ + keyup:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { + this.fireKeyEvent("keyup", target, options); + }, + + /** + * Simulates a compositionstart event on a particular element. + * + * @param {HTMLElement} + * target The element to act on. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method compositionstart + * @static + */ + compositionstart:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { + this.fireKeyEvent("compositionstart", target, options); + }, + + /** + * Simulates a compositionstart event on a particular element. + * + * @param {HTMLElement} + * target The element to act on. + * @param {Object} + * options Additional event options (use DOM standard names). + * @method compositionstart + * @static + */ + compositionend:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { + this.fireKeyEvent("compositionend", target, options); + }, + + /** + * 提供iframe扩展支持,用例测试需要独立场景的用例,由于异步支持,通过finish方法触发start + *
  • 事件绑定在frame上,包括afterfinish和jsloaded + * + * @param op.win + * @param op.nojs + * 不加载额外js + * @param op.ontest + * 测试步骤 + * @param op.onbeforestart + * 测试启动前处理步骤,默认为QUnit.stop(); + * @param op.onafterfinish + * 测试完毕执行步骤,默认为QUnit.start() + * + */ + frameExt:function (op) { + stop(); + op = typeof op == 'function' ? { + ontest:op + } : op; + var pw = op.win || window, w, f, url = '', id = typeof op.id == 'undefined' ? 'f' + : op.id, fid = 'iframe#' + id; + + op.finish = function () { + pw.$(fid).unbind(); + setTimeout(function () { + pw.$('div#div' + id).remove(); + start(); + }, 20); + }; + + if (pw.$(fid).length == 0) { + /* 添加frame,部分情况下,iframe没有边框,为了可以看到效果,添加一个带边框的div */ + pw.$(pw.document.body).append('
    '); + pw.$('div#div' + id).append(''); + } + op.onafterstart && op.onafterstart($('iframe#f')[0]); + pw.$('script').each(function () { + if (this.src && this.src.indexOf('import.php') >= 0) { + url = this.src.split('import.php')[1]; + } + }); + pw.$(fid).one('load', + function (e) { + var w = e.target.contentWindow; + var h = setInterval(function () { + if (w.baidu) {// 等待加载完成,IE6下这地方总出问题 + clearInterval(h); + op.ontest(w, w.frameElement); + } + }, 20); + // 找到当前操作的iframe,然后call ontest + }).attr('src', cpath + 'frame.php' + url); + }, + + /** + * + * 判断2个数组是否相等 + * + * @static + */ + isEqualArray:function (array1, array2) { + if ('[object Array]' != Object.prototype.toString.call(array1) + || '[object Array]' != Object.prototype.toString.call(array2)) + return (array1 === array2); + else if (array1.length != array2.length) + return false; + else { + for (var i in array1) { + if (array1[i] != array2[i]) + return false; + } + return true; + } + }, + + /*************************************************************************** + * + * 通用数据模块 + * + * @static + * + **************************************************************************/ + commonData:{// 针对测试文件的路径而不是UserAction的路径 + "testdir":'../../', + datadir:(function () { + return location.href.split("/_test/")[0] + "/_test/tools/data/"; + })(), + currentPath:function () { + var params = location.search.substring(1).split('&'); + for (var i = 0; i < params.length; i++) { + var p = params[i]; + if (p.split('=')[0] == 'case') { + var casepath = p.split('=')[1].split('.').join('/'); + return location.href.split('/_test/')[0] + '/_test/' + + casepath.substring(0, casepath.lastIndexOf('/')) + + '/'; + } + } + return ""; + } + }, + + importsrc:function (src, callback, matcher, exclude, win) { + win = win || window; + var doc = win.document; + + var srcpath = location.href.split("/_test/")[0] + + "/_test/tools/br/import.php"; + var param0 = src; + var ps = { + f:src + }; + if (exclude) + ps.e = exclude; + var param1 = exclude || ""; + /** + * IE下重复载入会出现无法执行情况 + */ + if (win.execScript) { + $.get(srcpath, ps, function (data) { + win.execScript(data); + }); + } else { + var head = doc.getElementsByTagName('head')[0]; + var sc = doc.createElement('script'); + sc.type = 'text/javascript'; + sc.src = srcpath + "?f=" + param0 + "&e=" + param1; + head.appendChild(sc); + } + + matcher = matcher || src; + var mm = matcher.split(",")[0].split("."); + var h = setInterval(function () { + var p = win; + for (var i = 0; i < mm.length; i++) { + if (typeof (p[mm[i]]) == 'undefined') { + // console.log(mm[i]); + return; + } + p = p[mm[i]]; + } + clearInterval(h); + if (callback && 'function' == typeof callback) + callback(); + }, 20); + }, + + /* 用于加载css文件,如果没有加载完毕则不执行回调函数 */ + loadcss:function (url, callback, classname, style, value) { + var links = document.getElementsByTagName('link'); + for (var link in links) { + if (link.href == url) { + callback(); + return; + } + } + var head = document.getElementsByTagName('head')[0]; + var link = head.appendChild(document.createElement('link')); + link.setAttribute("rel", "stylesheet"); + link.setAttribute("type", "text/css"); + link.setAttribute("href", url); + var div = document.body.appendChild(document.createElement("div")); + $(document).ready( + function () { + div.className = classname || 'cssloaded'; + var h = setInterval(function () { + if ($(div).css(style || 'width') == value + || $(div).css(style || 'width') == '20px') { + clearInterval(h); + document.body.removeChild(div); + setTimeout(callback, 20); + } + }, 20); + }); + }, + + /** + * options supported + */ + delayhelper:function (oncheck, onsuccess, onfail, timeout) { + onsuccess = onsuccess || oncheck.onsuccess; + onfail = onfail || oncheck.onfail || function () { + window.QUnit.fail('timeout wait for timeout : ' + timeout + 'ms'); + start(); + }; + timeout = timeout || oncheck.timeout || 10000; + + oncheck = (typeof oncheck == 'function') ? oncheck : oncheck.oncheck; + var h1 = setInterval(function () { + if (!oncheck()) + return; + else { + clearInterval(h1); + clearTimeout(h2); + typeof onsuccess == "function" && onsuccess(); + } + }, 20); + var h2 = setTimeout(function () { + clearInterval(h1); + clearTimeout(h2); + onfail(); + }, timeout); + }, + + browser:(function () { + var win = window; + var numberify = function (s) { + var c = 0; + return parseFloat(s.replace(/\./g, function () { + return (c++ == 1) ? '' : '.'; + })); + }, + + nav = win && win.navigator, + + o = { + + /** + * Internet Explorer version number or 0. Example: 6 + * + * @property ie + * @type float + * @static + */ + ie:0, + + /** + * Opera version number or 0. Example: 9.2 + * + * @property opera + * @type float + * @static + */ + opera:0, + + /** + * Gecko engine revision number. Will evaluate to 1 if Gecko is + * detected but the revision could not be found. Other browsers will + * be 0. Example: 1.8 + * + *
    +                 * Firefox 1.0.0.4: 1.7.8   <-- Reports 1.7
    +                 * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
    +                 * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
    +                 * Firefox 3.0   <-- 1.9
    +                 * Firefox 3.5   <-- 1.91
    +                 * 
    + * + * @property gecko + * @type float + * @static + */ + gecko:0, + + /** + * AppleWebKit version. KHTML browsers that are not WebKit browsers + * will evaluate to 1, other browsers 0. Example: 418.9 + * + *
    +                 * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
    +                 *                                   latest available for Mac OSX 10.3.
    +                 * Safari 2.0.2:         416     <-- hasOwnProperty introduced
    +                 * Safari 2.0.4:         418     <-- preventDefault fixed
    +                 * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
    +                 *                                   different versions of webkit
    +                 * Safari 2.0.4 (419.3): 419     <-- Tiger installations that have been
    +                 *                                   updated, but not updated
    +                 *                                   to the latest patch.
    +                 * Webkit 212 nightly:   522+    <-- Safari 3.0 precursor (with native SVG
    +                 *                                   and many major issues fixed).
    +                 * Safari 3.0.4 (523.12) 523.12  <-- First Tiger release - automatic update
    +                 *                                   from 2.x via the 10.4.11 OS patch
    +                 * Webkit nightly 1/2008:525+    <-- Supports DOMContentLoaded event.
    +                 *                                   yahoo.com user agent hack removed.
    +                 * 
    + * + * http://en.wikipedia.org/wiki/Safari_version_history + * + * @property webkit + * @type float + * @static + */ + webkit:0, + + /** + * Chrome will be detected as webkit, but this property will also be + * populated with the Chrome version number + * + * @property chrome + * @type float + * @static + */ + chrome:0, + + safari:0, + + firefox:0, + + maxthon:0, + maxthonIE:0, + + /** + * The mobile property will be set to a string containing any + * relevant user agent information when a modern mobile browser is + * detected. Currently limited to Safari on the iPhone/iPod Touch, + * Nokia N-series devices with the WebKit-based browser, and Opera + * Mini. + * + * @property mobile + * @type string + * @static + */ + mobile:null, + + /** + * Adobe AIR version number or 0. Only populated if webkit is + * detected. Example: 1.0 + * + * @property air + * @type float + */ + air:0, + + /** + * Google Caja version number or 0. + * + * @property caja + * @type float + */ + caja:nav && nav.cajaVersion, + + /** + * Set to true if the pagebreak appears to be in SSL + * + * @property secure + * @type boolean + * @static + */ + secure:false, + + /** + * The operating system. Currently only detecting windows or + * macintosh + * + * @property os + * @type string + * @static + */ + os:null + + }, + + ua = nav && nav.userAgent, + + loc = win && win.location, + + href = loc && loc.href, + + m; + + o.secure = href && (href.toLowerCase().indexOf("https") === 0); + + if (ua) { + + if ((/windows|win32/i).test(ua)) { + o.os = 'windows'; + } else if ((/macintosh/i).test(ua)) { + o.os = 'macintosh'; + } else if ((/rhino/i).test(ua)) { + o.os = 'rhino'; + } + + // Modern KHTML browsers should qualify as Safari X-Grade + if ((/KHTML/).test(ua)) { + o.webkit = 1; + } + if (window.external && /(\d+\.\d)/.test(external.max_version)) { + + o.maxthon = parseFloat(RegExp['\x241']); + if (/MSIE/.test(ua)) { + o.maxthonIE = 1; + o.maxthon = 0; + } + + } + // Modern WebKit browsers are at least X-Grade + m = ua.match(/AppleWebKit\/([^\s]*)/); + if (m && m[1]) { + o.webkit = numberify(m[1]); + + // Mobile browser check + if (/ Mobile\//.test(ua)) { + o.mobile = "Apple"; // iPhone or iPod Touch + } else { + m = ua.match(/NokiaN[^\/]*|Android \d\.\d|webOS\/\d\.\d/); + if (m) { + o.mobile = m[0]; // Nokia N-series, Android, webOS, + // ex: + // NokiaN95 + } + } + + var m1 = ua.match(/Safari\/([^\s]*)/); + if (m1 && m1[1]) // Safari + o.safari = numberify(m1[1]); + m = ua.match(/Chrome\/([^\s]*)/); + if (o.safari && m && m[1]) { + o.chrome = numberify(m[1]); // Chrome + } else { + m = ua.match(/AdobeAIR\/([^\s]*)/); + if (m) { + o.air = m[0]; // Adobe AIR 1.0 or better + } + } + } + + if (!o.webkit) { // not webkit + // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; + // fi; U; + // try get firefox and it's ver + // ssr) + m = ua.match(/Opera[\s\/]([^\s]*)/); + if (m && m[1]) { + m = ua.match(/Version[\s\/]([^\s]*)/); + o.opera = numberify(m[1]); + m = ua.match(/Opera Mini[^;]*/); + if (m) { + o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316 + } + } else { // not opera or webkit + m = ua.match(/MSIE\s([^;]*)/); + if (m && m[1]) { + o.ie = numberify(m[1]); + }else if (ua.match(/Gecko([^\s]*)/)&&ua.match(/rv:11/)){//todo + o.ie = 11; + } else { // not opera, webkit, or ie + m = ua.match(/Gecko\/([^\s]*)/); + if (m) { + o.gecko = 1; // Gecko detected, look for revision + m = ua.match(/rv:([^\s\)]*)/); + if (m && m[1]) { + o.gecko = numberify(m[1]); + } + } + } + } + } + } + + return o; + }) + (), + + /** + * 提供队列方式执行用例的方案,接口包括start、add、next,方法全部执行完毕时会启动用例继续执行 + */ + functionListHelper:function () { + var check = { + list:[], + start:function () { + var self = this; + $(this).bind('next', function () { + setTimeout(function () {// 避免太深的堆栈 + if (self.list.length == 0) + start(); + else + self.list.shift()(); + }, 0); + }); + self.next(); + }, + add:function (func) { + this.list.push(func); + }, + next:function (delay) { + var self = this; + if (delay) { + setTimeout(function () { + $(self).trigger('next'); + }, delay); + } else + $(this).trigger('next'); + } + }; + return check; + }, + getHTML:function (co) { + var div = document.createElement('div'), h; + if (!co) + return 'null'; + div.appendChild(co.cloneNode(true)); + h = div.innerHTML.toLowerCase(); + + h = h.replace(/[\r\n\t\u200b\ufeff]/g, ''); // Remove line feeds and tabs + h = h.replace(/ (\w+)=([^\"][^\s>]*)/gi, ' $1="$2"'); // Restore + // attribs on IE + return h; + }, + getChildHTML:function (co) { + + var h = co.innerHTML.toLowerCase(); + + h = h.replace(/[\r\n\t\u200b\ufeff]/g, ''); // Remove line feeds and tabs + h = h.replace(/ (\w+)=([^\"][^\s>]*)/gi, ' $1="$2"'); // Restore attribs on IE + + return h.replace(/\u200B/g, ''); + }, + getIndex:function (node) { + var childNodes = node.parentNode.childNodes, i = 0; + while (childNodes[i] !== node) + i++; + return i; + }, + checkResult:function (range, sc, ec, so, eo, collapsed, descript) { + descript = descript ? descript : ''; + equal(range.collapsed, collapsed, "check collapsed --" + descript); + ok(range.startContainer === sc, "check startContainer--" + descript); + ok(range.endContainer === ec, "check endContainer--" + descript); + equal(range.startOffset, so, "check startOffset--" + descript); + equal(range.endOffset, eo, "check endOffset--" + descript); + }, + isSameRange:function (rangeA, rangeB, descript) { + descript = descript ? descript : ''; + equal(rangeA.collapsed, rangeB.collapsed, "check collapsed --" + descript); + ok(rangeA.document === rangeB.document, "check document--" + descript); + ok(rangeA.startContainer === rangeB.startContainer, "check startContainer--" + descript); + ok(rangeA.endContainer === rangeB.endContainer, "check endContainer--" + descript); + equal(rangeA.startOffset, rangeB.startOffset, "check startOffset--" + descript); + equal(rangeA.endOffset, rangeB.endOffset, "check endOffset--" + descript); + }, + manualDeleteFillData:function (node) { + var childs = node.childNodes; + for (var i = 0; i < childs.length; i++) { + var fillData = childs[i]; + if ((fillData.nodeType == 3) && ( fillData.data == domUtils.fillChar )) { + domUtils.remove(fillData); + fillData = null; + + } + else + this.manualDeleteFillData(fillData); + } + + + }, + cssStyleToDomStyle:function (cssName) { + var test = document.createElement('div').style, + cssFloat = test.cssFloat != undefined ? 'cssFloat' + : test.styleFloat != undefined ? 'styleFloat' + : 'float', + cache = { 'float':cssFloat }; + + function replacer(match) { + return match.charAt(1).toUpperCase(); + } + +// return function( cssName ) { + return cache[cssName] || (cache[cssName] = cssName.replace(/-./g, replacer) ); +// }; + }, + isSameStyle:function (elementA, elementB) { +// var styleA = elementA.style.cssText, +// styleB = elementB.style.cssText; +// if ( this.browser.ie && this.browser.version == 6 ) { +// styleA = styleA.toLowerCase(); +// styleB = styleB.toLowerCase(); +// } +// if ( !styleA && !styleB ) { +// return true; +// } else if ( !styleA || !styleB ) { +// return false; +// } +// var styleNameMap = {}, +// record = [], +// exit = {}; +// styleA.replace( /[\w-]+\s*(?=:)/g, function ( name ) { +// styleNameMap[name] = record.push( name ); +// } ); +// try { +// styleB.replace( /[\w-]+\s*(?=:)/g, function ( name ) { +// var index = styleNameMap[name]; +// if ( index ) { +//// name = this.cssStyleToDomStyle( name ); +// if ( elementA.style[name] !== elementB.style[name] ) { +// throw exit; +// } +// record[index - 1] = ''; +// } else { +// throw exit; +// } +// } ); +// } catch ( ex ) { +// if ( ex === exit ) { +// return false; +// } +// } +// return !record.join( '' ); + function indexOf(array, item, at) { + for (var i = at || 0, l = array.length; i < l; i++) { + if (array[i] === item) { + return i; + } + } + return -1; + } + + var styleA = elementA.style.cssText.replace(/( ?; ?)/g, ';').replace(/( ?: ?)/g, ':'), + styleB = elementB.style.cssText.replace(/( ?; ?)/g, ';').replace(/( ?: ?)/g, ':'); + if (browser.opera) { + styleA = elementA.style; + styleB = elementB.style; + if (styleA.length != styleB.length) + return 0; + for (var p in styleA) { + if (/^(\d+|csstext)$/i.test(p)) + continue; + if (styleA[p] != styleB[p]) + return 0; + } + return 1; + } + + + if (!styleA || !styleB) { + return styleA == styleB ? 1 : 0; + } + styleA = styleA.split(';'); + styleB = styleB.split(';'); + + if (styleA.length != styleB.length) + return 0; + for (var j = 0; j < styleB.length; j++) { + if (styleB[j].toLowerCase().indexOf("color") > -1 && styleB[j].toLowerCase().indexOf("rgb") > -1) { + var color = this.formatColor(styleB[j].substr(styleB[j].indexOf("rgb"), styleB[j].length)); + styleB[j] = styleB[j].replace(styleB[j].substr(styleB[j].indexOf("rgb"), styleB[j].length), color); + } + } + for (var i = 0, ci; ci = styleA[i++];) { + if (ci.toLowerCase().indexOf("color") > -1 && ci.toLowerCase().indexOf("rgb") > -1) { + var color = this.formatColor(ci.substr(ci.indexOf("rgb"), ci.length)); + ci = ci.replace(ci.substr(ci.indexOf("rgb"), ci.length), color); + } + if (indexOf(styleB, ci) == -1) { + + return 0; + + }//styleA[0].substr(styleA[0].indexOf("rga"),styleA[0].length) + } + return 1; + }, + + + formatColor:function (color) { + var reg1 = /^\#[\da-f]{6}$/i, + reg2 = /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/, + keyword = { + black:'#000000', + silver:'#c0c0c0', + gray:'#808080', + white:'#ffffff', + maroon:'#800000', + red:'#ff0000', + purple:'#800080', + fuchsia:'#ff00ff', + green:'#008000', + lime:'#00ff00', + olive:'#808000', + yellow:'#ffff0', + navy:'#000080', + blue:'#0000ff', + teal:'#008080', + aqua:'#00ffff' + }; + if (reg1.test(color)) { + // #RRGGBB 直接返回 + return color; + } else if (reg2.test(color)) { + // 非IE中的 rgb(0, 0, 0) + for (var s, i = 1, color = "#"; i < 4; i++) { + s = parseInt(RegExp["\x24" + i]).toString(16); + color += ("00" + s).substr(s.length); + } + return color; + } else if (/^\#[\da-f]{3}$/.test(color)) { + // 简写的颜色值: #F00 + var s1 = color.charAt(1), + s2 = color.charAt(2), + s3 = color.charAt(3); + return "#" + s1 + s1 + s2 + s2 + s3 + s3; + } else if (keyword[color]) + return keyword[color]; + + return ""; + + }, + hasSameAttrs:function (nodeA, nodeB) { + if (nodeA.tagName != nodeB.tagName) + return 0; + var thisAttribs = nodeA.attributes, + otherAttribs = nodeB.attributes; + if (thisAttribs.length != otherAttribs.length) + return 0; + if (thisAttribs.length == 0) + return 1; + var attrA, attrB; + for (var i = 0; attrA = thisAttribs[i++];) { + if (attrA.nodeName == 'style') { + if (this.isSameStyle(nodeA, nodeB)) { + continue + } else { + return 0; + } + } + if (!ua.browser.ie || attrA.specified) { + attrB = nodeB.attributes[attrA.nodeName]; + if (!attrB) { + return 0; + } + } + return 1; + } + return 1; + }, + /** + *清除空Text节点 + */ + + clearWhiteNode:function (node) { + for (var i = 0; i < node.childNodes.length; i++) { + var tmpNode = node.childNodes[i]; + if (tmpNode.nodeType == 3 && !tmpNode.length) { + tmpNode.parentNode.removeChild(tmpNode); + i--; + } + } + }, + /** + *检查两个节点(包含所有子节点)是否具有相同的属性 + */ + flag:true, + checkAllChildAttribs:function (nodeA, nodeB) { + var k = nodeA.childNodes.length; + if (k != nodeB.childNodes.length) { + if (ua.browser.opera) { + this.clearWhiteNode(nodeA); + k = nodeA.childNodes.length; + if (k != nodeB.childNodes.length) + this.flag = false; + } + else + this.flag = false; + } + if (!this.flag) + return this.flag; + while (k) { + var tmpNodeA = nodeA.childNodes[k - 1]; + var tmpNodeB = nodeB.childNodes[k - 1]; + k--; + + if (tmpNodeA.nodeType == 3 || tmpNodeB.nodeType == 3 || tmpNodeA.nodeType == 8 || tmpNodeB.nodeType == 8) + continue; + if (!this.hasSameAttrs(tmpNodeA, tmpNodeB)) { + this.flag = false; + break; + + } + + this.checkAllChildAttribs(tmpNodeA, tmpNodeB); + } + return this.flag; + }, + haveSameAllChildAttribs:function (nodeA, nodeB) { + this.flag = true; + return this.checkAllChildAttribs(nodeA, nodeB); + }, + /*查看传入的html是否与传入的元素ele具有相同的style*/ + checkHTMLSameStyle:function (html, doc, ele, descript) { + var tagEle = doc.createElement(ele.tagName); + tagEle.innerHTML = html; + /*会有一些不可见字符,在比较前提前删掉*/ + this.manualDeleteFillData(ele); + ok(this.haveSameAllChildAttribs(ele, tagEle), descript); +// ok(this.equalsNode(ele.innerHMTL,html),descript); + }, + + + equalsNode:function (na, nb) { + function compare(nodeA, nodeB) { + if (nodeA.nodeType != nodeB.nodeType) { + return 0; + } + if (nodeA.nodeType == 3) { + return nodeA.nodeValue == nodeB.nodeValue + } + if (domUtils.isSameElement(nodeA, nodeB)) { + if (!nodeA.firstChild && !nodeB.firstChild) { + return 1; + } + if (nodeA.firstChild && !nodeB.firstChild || !nodeA.firstChild && nodeB.firstChild) { + return 0 + } + for (var i = 0, ai, bi; ai = nodeA.childNodes[i], bi = nodeB.childNodes[i++];) { + + if (!compare(ai, bi)) { + return 0 + } + } + return 1; + } else { + return 0; + } + } + + return compare(domUtils.createElement(document, 'div', { + 'innerHTML':na + }), domUtils.createElement(document, 'div', { + 'innerHTML':nb + })); + }, + + + getSelectedText:function () { + if (window.getSelection) { + // This technique is the most likely to be standardized. + // getSelection() returns a Selection object, which we do not document. + return window.getSelection().toString(); + } + else if (document.getSelection) { + // This is an older, simpler technique that returns a string + return document.getSelection(); + } + else if (document.selection) { + // This is the IE-specific technique. + // We do not document the IE selection property or TextRange objects. + return document.selection.createRange().text; + } + }, + findPosition:function (oElement) { + var x2 = 0; + var y2 = 0; + var width = oElement.offsetWidth; + var height = oElement.offsetHeight; + if (typeof( oElement.offsetParent ) != 'undefined') { + for (var posX = 0, posY = 0; oElement; oElement = oElement.offsetParent) { + posX += oElement.offsetLeft; + posY += oElement.offsetTop; + } + x2 = posX + width; + y2 = posY + height; + return [ posX, posY , x2, y2]; + + } else { + x2 = oElement.x + width; + y2 = oElement.y + height; + return [ oElement.x, oElement.y, x2, y2]; + } + }, + + checkElementPath:function (arr1, arr2, descript) { + if (!descript) + descript = ''; + var index = arr1.length; + if (index != arr2.length) + ok(false, '路径深度不相同'); + else { + + while (index > 0) + equal(arr1[--index ], arr2[index ], descript + '---第' + index + '个元素' + arr1[index]); + } + }, + getBrowser:function () { + var browser = ""; + if (this.browser.ie == 6) + browser = 'ie6'; + if (this.browser.ie == 7) + browser = 'ie7'; + if (this.browser.ie == 8) + browser = 'ie8'; + if (this.browser.ie == 9) + browser = 'ie9'; + if (this.browser.safari) + browser = 'safari'; + if (this.browser.firefox) + browser = 'firefox'; + if (this.browser.chrome) + browser = 'chrome'; + if (this.browser.maxthon) { + browser = 'maxthon'; + } + if (this.browser.maxthonIE) + browser = 'maxIE'; + if (this.browser.opera) + browser = 'opera'; + return browser; + }, + getFloatStyle:function (ele) { + if (this.browser.ie) + return ele.style['styleFloat']; + else + return ele.style['cssFloat']; + }, + + getComputedStyle:function(ele ){ + if(this.browser.ie&&ua.browser.ie<9){ + return ele.currentStyle; + }else{ + return window.getComputedStyle(ele); + } + }, + readFile:function (name, f) { + var args = {}; + args['name'] = name; + $.ajax({ + url:'read.php', + type:'post', + data:args, + success:function (msg) { + f(msg); + }, + error:function (xhr, msg) { + f(null); + } + }); + }, + readTxt:function (name, f) { + var args = {}; + args['name'] = './txt/' + name; + $.ajax({ + url:'read.php', + type:'post', + data:args, + success:function (msg) { + f(msg); + }, + error:function (xhr, msg) { + f(null); + } + }); + }, checkLowerCase:function (stringA, stringB) { + if (!(stringA || stringB)) + return true; + else if (!stringA || !stringB) + return false; + else { + return stringA.toLowerCase() == stringB.toLowerCase(); + } + }, removeEndSemicolon:function (styleValue) { + if (styleValue.length - 1 == styleValue.lastIndexOf(';')) + styleValue = styleValue.substring(0, styleValue.length - 1); + return styleValue; + }, checkNodeStyle:function (nodeA, nodeB) { + var nodeAStyle = this.removeEndSemicolon(nodeA.getAttr("style").replace(/\s+/g, "")).replace(/"/g,'').split(";"); + var nodeBStyle = this.removeEndSemicolon(nodeB.getAttr("style").replace(/\s+/g, "")).replace(/"/g,'').split(";"); + var lengthA = nodeAStyle.length; + var lengthB = nodeBStyle.length; + if (!(lengthA && lengthB)) + return true; + else if (lengthA != lengthB) + return false; + else { + for (var i = 0; i < lengthA; i++) { + if (nodeAStyle[i].match(/[-\w]+\s*:/) ) { + var styleName = nodeAStyle[i].match(/[-\w]+\s*:/)[0].replace(/\s*:/, ""); + nodeA.attrs.style = nodeA.attrs.style.replace(/"/g,''); + nodeB.attrs.style = nodeB.attrs.style.replace(/"/g,''); + var styleValueA = nodeA.getStyle(styleName).toLowerCase().replace(/\s+/g, ""); + var styleValueB = nodeB.getStyle(styleName).toLowerCase().replace(/\s+/g, ""); + if(/color/.test(styleName)){ + styleValueA = this.formatColor(styleValueA); + styleValueB = this.formatColor(styleValueB); + } + else; + if (styleValueA != styleValueB) + return false; + } + } + } + return true; + }, getPropertyCount:function (o) { + var n, count = 0; + for (n in o) { + if (o.hasOwnProperty(n)) { + count++; + } + } + return count; + },formHref:function(str){ + if(str.lastIndexOf('/')== str.length-1){ + str = str.substring(0,str.length-1); + } + return str; + },checkSameNodeAttrs:function (nodeA, nodeB) { + var lengthA = this.getPropertyCount(nodeA.attrs); + var lengthB = this.getPropertyCount(nodeB.attrs); + if (!(lengthA && lengthB)) + return true; + else if (lengthA != lengthB) + return false; + else { + for (var p in nodeA.attrs) { + if(!nodeB.getAttr(p)&&!nodeA.getAttr(p)) + return true; + else if (!nodeB.getAttr(p)||!nodeA.getAttr(p)) + return false; + else if (p.toLowerCase() == "style") { + if (!this.checkNodeStyle(nodeA, nodeB)) + return false; + } + else if(p.toLowerCase() == "href"){ + if (this.formHref(nodeA.getAttr(p).toLowerCase()) != this.formHref(nodeB.getAttr(p).toLowerCase())) + return false; + } + else { + if (nodeA.getAttr(p).toLowerCase().replace(/^\s+|\s+$/g, "") != nodeB.getAttr(p).toLowerCase().replace(/^\s+|\s+$/g, "")) + return false; + } + } + } + return true; + + }, checkChildren:function (nodeA, nodeB) { + if (!(nodeA.children || nodeB.children)) + return true; + else if (!(nodeA.children && nodeB.children)) + return false; + else if (nodeA.children.length != nodeB.children.length) + return false; + else { + var lengthA = nodeA.children.length; + for (var i = 0; i < lengthA; i++) { + if (!this.checkSameNode(nodeA.children[i], nodeB.children[i])) + return false; + } + } + return true; + }, checkSameNode:function (nodeA, nodeB) { + if (!this.checkSameNodeAttrs(nodeA, nodeB)) + return false; + else if (!this.checkChildren(nodeA, nodeB)) + return false; + else if (nodeA.data != nodeB.data) + return false; + else if (!this.checkLowerCase(nodeA.tagName, nodeB.tagName)) + return false; + else if (!this.checkLowerCase(nodeA.type, nodeB.type)) + return false; + else + return true; + }, checkSameHtml:function (stringA, stringB, scholium) { + ok(this.checkSameNode(UE.htmlparser(stringA), UE.htmlparser(stringB)), scholium); + }, + getContextmenuIndexByName:function(contextmenu,name){ + for(var i=0;i)[^>]*$|#([\w\-]+)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for digits + rdigit = /\d/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // Has the ready events already been bound? + readyBound = false, + + // The deferred used on DOM ready + readyList, + + // Promise methods + promiseMethods = "then done fail isResolved isRejected promise".split( " " ), + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = "body"; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.5.1", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.done( fn ); + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + // A third-party is pushing the ready event forwards + if ( wait === true ) { + jQuery.readyWait--; + } + + // Make sure that the DOM is not already loaded + if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).unbind( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyBound ) { + return; + } + + readyBound = true; + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent("onreadystatechange", DOMContentLoaded); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test(data.replace(rvalidescape, "@") + .replace(rvalidtokens, "]") + .replace(rvalidbraces, "")) ) { + + // Try to use the native JSON parser first + return window.JSON && window.JSON.parse ? + window.JSON.parse( data ) : + (new Function("return " + data))(); + + } else { + jQuery.error( "Invalid JSON: " + data ); + } + }, + + // Cross-browser xml parsing + // (xml & tmp used internally) + parseXML: function( data , xml , tmp ) { + + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + + tmp = xml.documentElement; + + if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { + jQuery.error( "Invalid XML: " + data ); + } + + return xml; + }, + + noop: function() {}, + + // Evalulates a script in a global context + globalEval: function( data ) { + if ( data && rnotwhite.test(data) ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement, + script = document.createElement( "script" ); + + if ( jQuery.support.scriptEval() ) { + script.appendChild( document.createTextNode( data ) ); + } else { + script.text = data; + } + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction(object); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type(array); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var ret = [], value; + + // Go through the array, translating each of the items to their + // new value (or values). + for ( var i = 0, length = elems.length; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + proxy: function( fn, proxy, thisObject ) { + if ( arguments.length === 2 ) { + if ( typeof proxy === "string" ) { + thisObject = fn; + fn = thisObject[ proxy ]; + proxy = undefined; + + } else if ( proxy && !jQuery.isFunction( proxy ) ) { + thisObject = proxy; + proxy = undefined; + } + } + + if ( !proxy && fn ) { + proxy = function() { + return fn.apply( thisObject || this, arguments ); + }; + } + + // Set the guid of unique handler to the same of original handler, so it can be removed + if ( fn ) { + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + } + + // So proxy can be declared as an argument + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can be optionally by executed if its a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Create a simple deferred (one callbacks list) + _Deferred: function() { + var // callbacks list + callbacks = [], + // stored [ context , args ] + fired, + // to avoid firing when already doing so + firing, + // flag to know if the deferred has been cancelled + cancelled, + // the deferred itself + deferred = { + + // done( f1, f2, ...) + done: function() { + if ( !cancelled ) { + var args = arguments, + i, + length, + elem, + type, + _fired; + if ( fired ) { + _fired = fired; + fired = 0; + } + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + deferred.done.apply( deferred, elem ); + } else if ( type === "function" ) { + callbacks.push( elem ); + } + } + if ( _fired ) { + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); + } + } + return this; + }, + + // resolve with given context and args + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { + firing = 1; + try { + while( callbacks[ 0 ] ) { + callbacks.shift().apply( context, args ); + } + } + // We have to add a catch block for + // IE prior to 8 or else the finally + // block will never get executed + catch (e) { + throw e; + } + finally { + fired = [ context, args ]; + firing = 0; + } + } + return this; + }, + + // resolve with this as context and given arguments + resolve: function() { + deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this, arguments ); + return this; + }, + + // Has this deferred been resolved? + isResolved: function() { + return !!( firing || fired ); + }, + + // Cancel + cancel: function() { + cancelled = 1; + callbacks = []; + return this; + } + }; + + return deferred; + }, + + // Full fledged deferred (two callbacks list) + Deferred: function( func ) { + var deferred = jQuery._Deferred(), + failDeferred = jQuery._Deferred(), + promise; + // Add errorDeferred methods, then and promise + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ); + return this; + }, + fail: failDeferred.done, + rejectWith: failDeferred.resolveWith, + reject: failDeferred.resolve, + isRejected: failDeferred.isResolved, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + if ( promise ) { + return promise; + } + promise = obj = {}; + } + var i = promiseMethods.length; + while( i-- ) { + obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; + } + return obj; + } + } ); + // Make sure only one callback list will be used + deferred.done( failDeferred.cancel ).fail( deferred.cancel ); + // Unexpose cancel + delete deferred.cancel; + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + return deferred; + }, + + // Deferred helper + when: function( object ) { + var lastIndex = arguments.length, + deferred = lastIndex <= 1 && object && jQuery.isFunction( object.promise ) ? + object : + jQuery.Deferred(), + promise = deferred.promise(); + + if ( lastIndex > 1 ) { + var array = slice.call( arguments, 0 ), + count = lastIndex, + iCallback = function( index ) { + return function( value ) { + array[ index ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value; + if ( !( --count ) ) { + deferred.resolveWith( promise, array ); + } + }; + }; + while( ( lastIndex-- ) ) { + object = array[ lastIndex ]; + if ( object && jQuery.isFunction( object.promise ) ) { + object.promise().then( iCallback(lastIndex), deferred.reject ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( promise, array ); + } + } else if ( deferred !== object ) { + deferred.resolve( object ); + } + return promise; + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySubclass( selector, context ) { + return new jQuerySubclass.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySubclass, this ); + jQuerySubclass.superclass = this; + jQuerySubclass.fn = jQuerySubclass.prototype = this(); + jQuerySubclass.fn.constructor = jQuerySubclass; + jQuerySubclass.subclass = this.subclass; + jQuerySubclass.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySubclass) ) { + context = jQuerySubclass(context); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass ); + }; + jQuerySubclass.fn.init.prototype = jQuerySubclass.fn; + var rootjQuerySubclass = jQuerySubclass(document); + return jQuerySubclass; + }, + + browser: {} +}); + +// Create readyList deferred +readyList = jQuery._Deferred(); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +if ( indexOf ) { + jQuery.inArray = function( elem, array ) { + return indexOf.call( array, elem ); + }; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +// Expose jQuery to the global object +return jQuery; + +})(); + + +(function() { + + jQuery.support = {}; + + var div = document.createElement("div"); + + div.style.display = "none"; + div.innerHTML = "
    a"; + + var all = div.getElementsByTagName("*"), + a = div.getElementsByTagName("a")[0], + select = document.createElement("select"), + opt = select.appendChild( document.createElement("option") ), + input = div.getElementsByTagName("input")[0]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return; + } + + jQuery.support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: div.firstChild.nodeType === 3, + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText insted) + style: /red/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: a.getAttribute("href") === "/a", + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: input.value === "on", + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Will be defined later + deleteExpando: true, + optDisabled: false, + checkClone: false, + noCloneEvent: true, + noCloneChecked: true, + boxModel: null, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableHiddenOffsets: true + }; + + input.checked = true; + jQuery.support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as diabled) + select.disabled = true; + jQuery.support.optDisabled = !opt.disabled; + + var _scriptEval = null; + jQuery.support.scriptEval = function() { + if ( _scriptEval === null ) { + var root = document.documentElement, + script = document.createElement("script"), + id = "script" + jQuery.now(); + + try { + script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); + } catch(e) {} + + root.insertBefore( script, root.firstChild ); + + // Make sure that the execution of code works by injecting a script + // tag with appendChild/createTextNode + // (IE doesn't support this, fails, and uses .text instead) + if ( window[ id ] ) { + _scriptEval = true; + delete window[ id ]; + } else { + _scriptEval = false; + } + + root.removeChild( script ); + // release memory in IE + root = script = id = null; + } + + return _scriptEval; + }; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + + } catch(e) { + jQuery.support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent("onclick", function click() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + jQuery.support.noCloneEvent = false; + div.detachEvent("onclick", click); + }); + div.cloneNode(true).fireEvent("onclick"); + } + + div = document.createElement("div"); + div.innerHTML = ""; + + var fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; + + // Figure out if the W3C box model works as expected + // document.body must exist before we can do this + jQuery(function() { + var div = document.createElement("div"), + body = document.getElementsByTagName("body")[0]; + + // Frameset documents with no body should not run this code + if ( !body ) { + return; + } + + div.style.width = div.style.paddingLeft = "1px"; + body.appendChild( div ); + jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; + + if ( "zoom" in div.style ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2; + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
    "; + jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2; + } + + div.innerHTML = "
    t
    "; + var tds = div.getElementsByTagName("td"); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0; + + tds[0].style.display = ""; + tds[1].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE < 8 fail this test) + jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0; + div.innerHTML = ""; + + body.removeChild( div ).style.display = "none"; + div = tds = null; + }); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + var eventSupported = function( eventName ) { + var el = document.createElement("div"); + eventName = "on" + eventName; + + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( !el.attachEvent ) { + return true; + } + + var isSupported = (eventName in el); + if ( !isSupported ) { + el.setAttribute(eventName, "return;"); + isSupported = typeof el[eventName] === "function"; + } + el = null; + + return isSupported; + }; + + jQuery.support.submitBubbles = eventSupported("submit"); + jQuery.support.changeBubbles = eventSupported("change"); + + // release memory in IE + div = all = a = null; +})(); + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the pagebreak + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } else { + id = jQuery.expando; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); + } else { + cache[ id ] = jQuery.extend(cache[ id ], name); + } + } + + thisCache = cache[ id ]; + + // Internal jQuery data is stored in a separate object inside the object's data + // cache in order to avoid key collisions between internal data and user-defined + // data + if ( pvt ) { + if ( !thisCache[ internalKey ] ) { + thisCache[ internalKey ] = {}; + } + + thisCache = thisCache[ internalKey ]; + } + + if ( data !== undefined ) { + thisCache[ name ] = data; + } + + // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should + // not attempt to inspect the internal events object using jQuery.data, as this + // internal data object is undocumented and subject to change. + if ( name === "events" && !thisCache[name] ) { + return thisCache[ internalKey ] && thisCache[ internalKey ].events; + } + + return getByName ? thisCache[ name ] : thisCache; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; + + if ( thisCache ) { + delete thisCache[ name ]; + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !isEmptyDataObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( pvt ) { + delete cache[ id ][ internalKey ]; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + var internalCache = cache[ id ][ internalKey ]; + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + if ( jQuery.support.deleteExpando || cache != window ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the entire user cache at once because it's faster than + // iterating through each key, but we need to continue to persist internal + // data if it existed + if ( internalCache ) { + cache[ id ] = {}; + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + + cache[ id ][ internalKey ] = internalCache; + + // Otherwise, we need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + } else if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } else { + elem[ jQuery.expando ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 ) { + var attr = this[0].attributes, name; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = name.substr( 5 ); + dataAttr( this[0], name, data[ name ] ); + } + } + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), + args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + data = elem.getAttribute( "data-" + key ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + !jQuery.isNaN( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON +// property to be considered empty objects; this property always exists in +// order to make sure JSON.stringify does not expose internal metadata +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +jQuery.extend({ + queue: function( elem, type, data ) { + if ( !elem ) { + return; + } + + type = (type || "fx") + "queue"; + var q = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( !data ) { + return q || []; + } + + if ( !q || jQuery.isArray(data) ) { + q = jQuery._data( elem, type, jQuery.makeArray(data) ); + + } else { + q.push( data ); + } + + return q; + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(); + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue", true ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function( i ) { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspaces = /\s+/, + rreturn = /\r/g, + rspecialurl = /^(?:href|src|style)$/, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rradiocheck = /^(?:radio|checkbox)$/i; + +jQuery.props = { + "for": "htmlFor", + "class": "className", + readonly: "readOnly", + maxlength: "maxLength", + cellspacing: "cellSpacing", + rowspan: "rowSpan", + colspan: "colSpan", + tabindex: "tabIndex", + usemap: "useMap", + frameborder: "frameBorder" +}; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name, fn ) { + return this.each(function(){ + jQuery.attr( this, name, "" ); + if ( this.nodeType === 1 ) { + this.removeAttribute( name ); + } + }); + }, + + addClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.addClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( value && typeof value === "string" ) { + var classNames = (value || "").split( rspaces ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className ) { + elem.className = value; + + } else { + var className = " " + elem.className + " ", + setClass = elem.className; + + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { + setClass += " " + classNames[c]; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.removeClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + var classNames = (value || "").split( rspaces ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + var className = (" " + elem.className + " ").replace(rclass, " "); + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[c] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this); + self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspaces ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + if ( !arguments.length ) { + var elem = this[0]; + + if ( elem ) { + if ( jQuery.nodeName( elem, "option" ) ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + + // We need to handle select boxes special + if ( jQuery.nodeName( elem, "select" ) ) { + var index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery(option).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + } + + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { + return elem.getAttribute("value") === null ? "on" : elem.value; + } + + // Everything else, we just grab the value + return (elem.value || "").replace(rreturn, ""); + + } + + return undefined; + } + + var isFunction = jQuery.isFunction(value); + + return this.each(function(i) { + var self = jQuery(this), val = value; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call(this, i, self.val()); + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray(val) ) { + val = jQuery.map(val, function (value) { + return value == null ? "" : value + ""; + }); + } + + if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { + this.checked = jQuery.inArray( self.val(), val ) >= 0; + + } else if ( jQuery.nodeName( this, "select" ) ) { + var values = jQuery.makeArray(val); + + jQuery( "option", this ).each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + this.selectedIndex = -1; + } + + } else { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery(elem)[name](value); + } + + var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), + // Whether we are setting (or getting) + set = value !== undefined; + + // Try to normalize/fix the name + name = notxml && jQuery.props[ name ] || name; + + // Only do all the following if this is a node (faster for style) + if ( elem.nodeType === 1 ) { + // These attributes require special treatment + var special = rspecialurl.test( name ); + + // Safari mis-reports the default selected property of an option + // Accessing the parent's selectedIndex property fixes it + if ( name === "selected" && !jQuery.support.optSelected ) { + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + + // If applicable, access the attribute via the DOM 0 way + // 'in' checks fail in Blackberry 4.7 #6931 + if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) { + if ( set ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } + + if ( value === null ) { + if ( elem.nodeType === 1 ) { + elem.removeAttribute( name ); + } + + } else { + elem[ name ] = value; + } + } + + // browsers index elements by id/name on forms, give priority to attributes. + if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { + return elem.getAttributeNode( name ).nodeValue; + } + + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + if ( name === "tabIndex" ) { + var attributeNode = elem.getAttributeNode( "tabIndex" ); + + return attributeNode && attributeNode.specified ? + attributeNode.value : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + + return elem[ name ]; + } + + if ( !jQuery.support.style && notxml && name === "style" ) { + if ( set ) { + elem.style.cssText = "" + value; + } + + return elem.style.cssText; + } + + if ( set ) { + // convert the value to a string (all browsers do this but IE) see #1070 + elem.setAttribute( name, "" + value ); + } + + // Ensure that missing attributes return undefined + // Blackberry 4.7 returns "" from getAttribute #6938 + if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) { + return undefined; + } + + var attr = !jQuery.support.hrefNormalized && notxml && special ? + // Some attributes require a special call on IE + elem.getAttribute( name, 2 ) : + elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return attr === null ? undefined : attr; + } + // Handle everything which isn't a DOM element node + if ( set ) { + elem[ name ] = value; + } + return elem[ name ]; + } +}); + + + + +var rnamespaces = /\.(.*)$/, + rformElems = /^(?:textarea|input|select)$/i, + rperiod = /\./g, + rspace = / /g, + rescape = /[^\w\s.|`]/g, + fcleanup = function( nm ) { + return nm.replace(rescape, "\\$&"); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // TODO :: Use a try/catch until it's safe to pull this out (likely 1.6) + // Minor release fix for bug #8018 + try { + // For whatever reason, IE has trouble passing the window object + // around, causing it to be cloned in the process + if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) { + elem = window; + } + } + catch ( e ) {} + + if ( handler === false ) { + handler = returnFalse; + } else if ( !handler ) { + // Fixes bug #7229. Fix recommended by jdalton + return; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery._data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events, + eventHandle = elemData.handle; + + if ( !events ) { + elemData.events = events = {}; + } + + if ( !eventHandle ) { + elemData.handle = eventHandle = function() { + // Handle the second event of a trigger and when + // an event is called after a pagebreak has unloaded + return typeof jQuery !== "undefined" && !jQuery.event.triggered ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + if ( !handleObj.guid ) { + handleObj.guid = handler.guid; + } + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for global triggering + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem, undefined, true ); + } + } + }, + + // bubbling is internal + trigger: function( event, data, elem /*, bubbling */ ) { + // Event object or event type + var type = event.type || event, + bubbling = arguments[3]; + + if ( !bubbling ) { + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + jQuery.extend( jQuery.Event(type), event ) : + // Just the event type (string) + jQuery.Event(type); + + if ( type.indexOf("!") >= 0 ) { + event.type = type = type.slice(0, -1); + event.exclusive = true; + } + + // Handle a global trigger + if ( !elem ) { + // Don't bubble custom events when global (to avoid too much overhead) + event.stopPropagation(); + + // Only trigger if we've ever bound an event for it + if ( jQuery.event.global[ type ] ) { + // XXX This code smells terrible. event.js should not be directly + // inspecting the data cache + jQuery.each( jQuery.cache, function() { + // internalKey variable is just used to make it easier to find + // and potentially change this stuff later; currently it just + // points to jQuery.expando + var internalKey = jQuery.expando, + internalCache = this[ internalKey ]; + if ( internalCache && internalCache.events && internalCache.events[ type ] ) { + jQuery.event.trigger( event, data, internalCache.handle.elem ); + } + }); + } + } + + // Handle triggering a single element + + // don't do events on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + // Clean up in case it is reused + event.result = undefined; + event.target = elem; + + // Clone the incoming data, if any + data = jQuery.makeArray( data ); + data.unshift( event ); + } + + event.currentTarget = elem; + + // Trigger the event, it is assumed that "handle" is a function + var handle = jQuery._data( elem, "handle" ); + + if ( handle ) { + handle.apply( elem, data ); + } + + var parent = elem.parentNode || elem.ownerDocument; + + // Trigger an inline bound script + try { + if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { + if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) { + event.result = false; + event.preventDefault(); + } + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (inlineError) {} + + if ( !event.isPropagationStopped() && parent ) { + jQuery.event.trigger( event, data, parent, true ); + + } else if ( !event.isDefaultPrevented() ) { + var old, + target = event.target, + targetType = type.replace( rnamespaces, "" ), + isClick = jQuery.nodeName( target, "a" ) && targetType === "click", + special = jQuery.event.special[ targetType ] || {}; + + if ( (!special._default || special._default.call( elem, event ) === false) && + !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { + + try { + if ( target[ targetType ] ) { + // Make sure that we don't accidentally re-trigger the onFOO events + old = target[ "on" + targetType ]; + + if ( old ) { + target[ "on" + targetType ] = null; + } + + jQuery.event.triggered = true; + target[ targetType ](); + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (triggerError) {} + + if ( old ) { + target[ "on" + targetType ] = old; + } + + jQuery.event.triggered = false; + } + } + }, + + handle: function( event ) { + var all, handlers, namespaces, namespace_re, events, + namespace_sort = [], + args = jQuery.makeArray( arguments ); + + event = args[0] = jQuery.event.fix( event || window.event ); + event.currentTarget = this; + + // Namespaced event handlers + all = event.type.indexOf(".") < 0 && !event.exclusive; + + if ( !all ) { + namespaces = event.type.split("."); + event.type = namespaces.shift(); + namespace_sort = namespaces.slice(0).sort(); + namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.namespace = event.namespace || namespace_sort.join("."); + + events = jQuery._data(this, "events"); + + handlers = (events || {})[ event.type ]; + + if ( events && handlers ) { + // Clone the handlers to prevent manipulation + handlers = handlers.slice(0); + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Filter the functions by class + if ( all || namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + } + + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + // Fixes #1925 where srcElement might not be defined either + event.target = event.srcElement || document; + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var doc = document.documentElement, + body = document.body; + + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { + event.which = event.charCode != null ? event.charCode : event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, + liveConvert( handleObj.origType, handleObj.selector ), + jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); + }, + + remove: function( handleObj ) { + jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); + } + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + // Check if mouse(over|out) are still within the same parent element + var parent = event.relatedTarget; + + // Firefox sometimes assigns relatedTarget a XUL element + // which we cannot access the parentNode property of + try { + + // Chrome does something similar, the parentNode property + // can be accessed but is null. + if ( parent !== document && !parent.parentNode ) { + return; + } + // Traverse up the tree + while ( parent && parent !== this ) { + parent = parent.parentNode; + } + + if ( parent !== this ) { + // set the correct event type + event.type = event.data; + + // handle event if we actually just moused on to a non sub-element + jQuery.event.handle.apply( this, arguments ); + } + + // assuming we've left the element since we most likely mousedover a xul element + } catch(e) { } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var changeFilters, + + getVal = function( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( elem.nodeName.toLowerCase() === "select" ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery._data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery._data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + e.liveFired = undefined; + jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + beforedeactivate: testChange, + + click: function( e ) { + var elem = e.target, type = elem.type; + + if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { + testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = elem.type; + + if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information + beforeactivate: function( e ) { + var elem = e.target; + jQuery._data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return rformElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return rformElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; + + // Handle when the input is .focus()'d + changeFilters.focus = changeFilters.beforeactivate; +} + +function trigger( type, elem, args ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + // Don't pass args or remember liveFired; they apply to the donor event. + var event = jQuery.extend( {}, args[ 0 ] ); + event.type = type; + event.originalEvent = {}; + event.liveFired = undefined; + jQuery.event.handle.call( elem, event ); + if ( event.isDefaultPrevented() ) { + args[ 0 ].preventDefault(); + } +} + +// Create "bubbling" focus and blur events +if ( document.addEventListener ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + jQuery.event.special[ fix ] = { + setup: function() { + this.addEventListener( orig, handler, true ); + }, + teardown: function() { + this.removeEventListener( orig, handler, true ); + } + }; + + function handler( e ) { + e = jQuery.event.fix( e ); + e.type = fix; + return jQuery.event.handle.call( this, e ); + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( jQuery.isFunction( data ) || data === false ) { + fn = data; + data = undefined; + } + + var handler = name === "one" ? jQuery.proxy( fn, function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }) : fn; + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + var event = jQuery.Event( type ); + event.preventDefault(); + event.stopPropagation(); + jQuery.event.trigger( event, data, this[0] ); + return event.result; + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + i = 1; + + // link all the functions, so any of them can unbind this click handler + while ( i < args.length ) { + jQuery.proxy( fn, args[ i++ ] ); + } + + return this.click( jQuery.proxy( fn, function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + })); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( jQuery.isFunction( data ) ) { + fn = data; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( type === "focus" || type === "blur" ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +}); + +function liveHandler( event ) { + var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, + elems = [], + selectors = [], + events = jQuery._data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) + if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { + return; + } + + if ( event.namespace ) { + namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + close = match[i]; + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { + elem = close.elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + event.type = handleObj.preType; + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj, level: close.level }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + + if ( maxLevel && match.level > maxLevel ) { + break; + } + + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + ret = match.handleObj.origHandler.apply( match.elem, arguments ); + + if ( ret === false || event.isPropagationStopped() ) { + maxLevel = match.level; + + if ( ret === false ) { + stop = false; + } + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var match, + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var found, item, + filter = Expr.filter[ type ], + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return "text" === elem.getAttribute( 'type' ); + }, + radio: function( elem ) { + return "radio" === elem.type; + }, + + checkbox: function( elem ) { + return "checkbox" === elem.type; + }, + + file: function( elem ) { + return "file" === elem.type; + }, + password: function( elem ) { + return "password" === elem.type; + }, + + submit: function( elem ) { + return "submit" === elem.type; + }, + + image: function( elem ) { + return "image" === elem.type; + }, + + reset: function( elem ) { + return "reset" === elem.type; + }, + + button: function( elem ) { + return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + var first = match[2], + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // If the nodes are siblings (or identical) we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

    "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector, + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + if ( matches ) { + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + return matches.call( node, expr ); + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
    "; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var ret = this.pushStack( "", "find", selector ), + length = 0; + + for ( var i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( var n = length; n < ret.length; n++ ) { + for ( var r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && jQuery.filter( selector, this ).length > 0; + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + if ( jQuery.isArray( selectors ) ) { + var match, selector, + matches = {}, + level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[selector] ) { + matches[selector] = jQuery.expr.match.POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[selector]; + + if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + var pos = POS.test( selectors ) ? + jQuery( selectors, context || this.context ) : null; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique(ret) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +} + + + + +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /", "" ], + legend: [ 1, "
    ", "
    " ], + thead: [ 1, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + col: [ 2, "", "
    " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and "); +// } diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/lib/Staf.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/lib/Staf.php new file mode 100644 index 000000000..4420c7bc2 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/lib/Staf.php @@ -0,0 +1,58 @@ +]] COMMAND [PARMS ] + * @param $path + * @param $params + * @param $host + */ + public static function process_start($path, $params, $host='local', $wait=false){ + $cmd = "start shell command \\\"\"$path\"\\\" parms \\\"\"$params\"\\\""; + if($wait){ + $cmd.=" wait returnstdout returnstderr"; + } + return self::process($cmd, $host); + } + + /** + * STOP | HANDLE > [USING ] + * @param unknown_type $handle + * @param unknown_type $host + */ + public static function process_stop($handle, $host='local', $all=0){ + $cmd = $all ? "STOP ALL CONFIRM":"STOP HANDLE $handle"; + return self::process($cmd, $host); + } + + public static function queryHandle($browser){ + $filename = "temp\\$browser"; + if(file_exists($filename)){ + $handle = file_get_contents($filename); + delete($filename); + return $handle; + } + return false; + } + + public static function saveHandle($browser){ + $filename = "temp\\$browser"; + $fp = fopen($filename, 'w'); + fwrite($fp, 'test'); + fclose($fp); + } +} +?> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/lib/StafResult.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/lib/StafResult.php new file mode 100644 index 000000000..6942dd16b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/lib/StafResult.php @@ -0,0 +1,20 @@ +rc = $rc; + $this->info = $info; + } + + public function __toString() + { + return "return code : ".$rc.", return info : ".$info."\n"; + } + + public static function parse($result){ + return new StafResult(0, $result); + } +}?> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/list.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/list.php new file mode 100644 index 000000000..27b0450bb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/list.php @@ -0,0 +1,78 @@ + + + + + + + Ueditor Test Index Page + + + + + + + + + +
    +

    Ueditor Test Index Page

    + +

    + ueditor +

    +
    + + +
    + + + +
    + +
    + 自动下一个出错时终止 +
    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/log.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/log.php new file mode 100644 index 000000000..cf43ba0c5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/log.php @@ -0,0 +1,45 @@ + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/mail.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/mail.php new file mode 100644 index 000000000..be79bed14 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/mail.php @@ -0,0 +1,113 @@ + + * @version $Id: mail.php 156323 2011-11-28 02:57:21Z peng.shan $ + */ +class Mail { + function send_mail($to,$subject = "",$body = "") { + //error_reporting(E_STRICT); + date_default_timezone_set("Asia/Shanghai");//设定时区东八区 + require_once('../libs/phpmailer/class.phpmailer.php'); + include("../libs/phpmailer/class.pop3.php"); + $mail = new PHPMailer(); //new一个PHPMailer对象出来 + $body = str_replace("[\]",'',$body); //对邮件内容进行必要的过滤 + $mail->CharSet ="UTF-8";//设定邮件编码,默认ISO-8859-1,如果发中文此项必须设置,否则乱码 +// $mail->IsSMTP(); // 设定使用SMTP服务 +// $mail->SMTPDebug = 1; // 启用SMTP调试功能 + // 1 = errors and messages + // 2 = messages only + $mail->SMTPAuth = true; // 启用 SMTP 验证功能 + $mail->SMTPSecure = "ssl"; // 安全协议 + $mail->Host = "MAILBOX03.internal.baidu.com"; // SMTP 服务器 + $mail->Port = 465; // SMTP服务器的端口号 + $mail->Username = "zhuwemxuan"; // SMTP服务器用户名 + $mail->Password = "Zwx19840818"; // SMTP服务器密码 + $mail->SetFrom('zhuewnxuan@baidu.com', '朱文轩'); + $mail->AddReplyTo("zhuwenxuan@baidu.com","邮件回复人的名称"); + $mail->Subject = $subject; + $mail->AltBody = "To view the message, please use an HTML compatible email viewer! - From www.jiucool.com"; // optional, comment out and test + $mail->MsgHTML($body); + $address = $to; + $mail->AddAddress($address, "收件人名称"); + if(!$mail->Send()) { + echo "Mailer Error: " . $mail->ErrorInfo; + } else { + echo "Message sent!恭喜,邮件发送成功!"; + } + } + function new_send_mail(){ + mail("zhuwenxuan@baidu.com","asdfasdf","asdfasdf"); +// require_once('../libs/phpmailer/class.phpmailer.php'); +// $mail = new PHPMailer(); +// $body = "asdfdsf"; +// $body = str_replace("[\]",'',$body); +// $mail->SMTPAuth = true; // 启用 SMTP 验证功能 +// $mail->SMTPSecure = "ssl"; // 安全协议 +// $mail->IsSMTP(); +// $mail->CharSet='UTF-8'; +// $mail->SMTPDebug = 2; +// $mail->Host = 'smtp.baidu.com'; +// $mail->Port = 25; +// $mail->Username = "zhuwenxuan@baidu.com"; +// $mail->Password = "Zwx19840818"; +// $mail->SetFrom('zhuwenxuan@baidu.com', 'First Last'); +// +// $mail->AddReplyTo("zhuwen_xuan@126.com","First Last"); +// +// $mail->Subject = "PHPMailer Test Subject via POP before SMTP, basic"; +// +// $mail->AltBody = "To view the message, please use an HTML compatible email viewer!"; // optional, comment out and test +// +// $mail->MsgHTML($body); +// +// $address = "zhuwen_xuan@126.com"; +// $mail->AddAddress($address, "John Doe"); +// if(!$mail->Send()) { +// echo "Mailer Error: " . $mail->ErrorInfo; +// } else { +// echo "Message sent!"; +// } + } + + function sendMain126(){ + require_once('../libs/phpmailer/class.phpmailer.php'); + $mail = new PHPMailer(); + $body = "asdfdsf"; + $body = str_replace("[\]",'',$body); + $mail->SMTPAuth = true; // 启用 SMTP 验证功能 + $mail->SMTPSecure = "ssl"; // 安全协议 + $mail->IsSMTP(); + $mail->CharSet='UTF-8'; + $mail->SMTPDebug = 2; + $mail->Host = 'smtp.126.com'; + $mail->Port = 465; + $mail->Username = "zhuwen_xuan@126.com"; + $mail->Password = "zwx19840818"; + $mail->SetFrom('zhuwen_xuan@126.com', 'First Last'); + + $mail->AddReplyTo("zhuwenxuan@baidu.com","First Last"); + + $mail->Subject = "PHPMailer Test Subject via POP before SMTP, basic"; + + $mail->AltBody = "To view the message, please use an HTML compatible email viewer!"; // optional, comment out and test + + $mail->MsgHTML($body); + + $address = "zhuwenxuan@baidu.com"; + $mail->AddAddress($address, "John Doe"); + if(!$mail->Send()) { + echo "Mailer Error: " . $mail->ErrorInfo; + } else { + echo "Message sent!"; + } + } + +} +$m = new Mail(); +$m->new_send_mail(); + + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/read.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/read.php new file mode 100644 index 000000000..4fb5a2f72 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/read.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/record.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/record.php new file mode 100644 index 000000000..883860ad9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/record.php @@ -0,0 +1,95 @@ +testsuite as $testsuite){ + foreach ($testsuite->testcase as $testResult) { + // $totalCov = 0; + $browser =strval( $testResult['browserInfo']); + $host = strval($testResult['hostInfo']); + $caseName = strval($testResult['name']); + $fail = strval($testResult['failNumber']); + $total = strval($testResult['totalNumber']); + $cov = strval($testResult['cov']); + $recordCovForBrowser = strval($testResult['recordCovForBrowser']); + if (!array_key_exists($caseName, $caseList)) { //如果这个用例不存在 + $caseInfo = array ( + 'hostInfo' => $host, + 'fail' => $fail, + 'total' => $total, + 'cov' => $cov, + 'recordCovForBrowser' => $recordCovForBrowser + ); + // $totalCov += $cov; + $caseList[$caseName] = array ( + $browser => $caseInfo//, + // 'totalCov'=>$totalCov + ); + // $caseList['totalCov'] = $totalCov; + } else { //否则添加到相应的用例中去 + $foundCase = $caseList[$caseName]; //找到用例名称对应的array,$caseName为key + if (!array_key_exists($browser, $foundCase)) { //如果没有该浏览器信息,则添加 + // $totalCov += $cov; + $caseList[$caseName][$browser] = array ( + 'hostInfo' => $host, + 'fail' => $fail, + 'total' => $total, + 'cov' => $cov, + 'recordCovForBrowser' => $recordCovForBrowser + ); + // $caseList[$caseName]['totalCov'] = $totalCov; + } else { + $foundBrowser = $foundCase[$browser]; //有这个浏览器 + array_push($foundBrowser, array ( + 'hostInfo' => $host, + 'fail' => $fail, + 'total' => $total, + 'cov' => $cov, + 'recordCovForBrowser' => $recordCovForBrowser + )); + } + } + + } + } + + //根据需求添加仅记录失败情况的接口 + if($onlyfails){//如果仅考虑失败情况,此处根据用例情况过滤 + foreach($caseList as $name => $info){ + $all_success = true;//记录当前用例是否全部运行成功 + foreach($info as $b => $result){ + if($result['fail'] > 0) + $all_success = false;//如果有失败情况则终止循环并进入下一个用例分析 + break; + } + //if($all_success) //如果全部通过则从记录中移除 + //unset($caseList[$name]); + } + } + return $caseList; +} + +function record() +{ +// require_once 'geneXML.php'; + /*如果全部运行完毕,发送邮件*/ + $kissList = interXML(false); + require_once 'geneHTML.php'; + if (sizeof($kissList) > 0) { + //针对kissList过滤,移除全部正确用例 + $html = geneHTML($kissList); + $report = 'report.html'; + $handle = fopen("$report", "w"); + fwrite($handle, $html); + fclose($handle); +// require_once 'geneHistory.php'; +// geneHistory($html); + } +} +?> diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/report.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/report.php new file mode 100644 index 000000000..5162a8487 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/report.php @@ -0,0 +1,158 @@ +"; + return; +} + + +function match($fileName, $matcher ) +{ + if ( $matcher == '*' ) + return true; + $len = strlen( $matcher ); + + + $as = explode( ';' , $matcher ); + if ( sizeof( $as ) > 1 ) { + + //这里把或的逻辑改成与 + foreach ( $as as $matcher1 ) { + if ( match($fileName, $matcher1 ) ) + return true; + } + return false; + } + $ms = explode( ',' , $matcher ); + if ( sizeof( $ms ) > 1 ) { + //这里把或的逻辑改成与 + foreach ( $ms as $matcher1 ) { + if ( !match($fileName, $matcher1 ) ) + return false; + } + return true; + } + + /** + * 处理反向选择分支 + */ + if ( substr( $matcher , 0 , 1 ) == '!' ) { + $m = substr( $matcher , 1 ); + if ( substr( $fileName , 0 , strlen( $m ) ) == $m ) + return false; + return true; + } + + if ( $len > strlen( $fileName ) ) { + return false; + } + return substr( $fileName , 0 , $len ) == $matcher; +} +function report() +{ + /** + * for junit report + */ + $dom = new DOMDocument('1.0', 'utf-8'); + $suite = $dom->appendChild($dom->createElement('testsuite')); + $cfg = preg_split('/[&=]/', $_POST['config']); + $config = array(); + for ($i = 0; $i < sizeof($cfg); $i += 2) { + // echo "{$cfg[$i]} {$cfg[$i+1]}\r\n
    "; + $config[$cfg[$i]] = $cfg[$i + 1]; + $p = $suite->appendChild($dom->createElement("property")); + + $p->setAttribute('name', $cfg[$i]); + $p->setAttribute('value', $cfg[$i + 1]); + + } + $suite->setAttribute("name", $config['browser']); + $errors = 0; + $failures = 0; + $tests = 0; + $time = 0; + $filter = $config['filterRun']; + foreach ($_POST as $key => $value) { + if ($key == 'config') + continue; + echo $key.' '; + $info = explode(";", $value); + + if ($filter!='' && (!match($key,$filter))){ + continue; + } + //errornum + ',' + allnum + ','+ kissPerc || 0 + ',' + wb.kissstart + ','+ wb.kissend; + $casetime = ($info[4] - $info[3]) / 1000; + $time += $casetime; + $tests++; + $failure = (int)($info[0]); + $case = $suite->appendChild($dom->createElement('testcase')); + $case->setAttribute("name", str_replace('_','.',$key)); + $case->setAttribute("time", $casetime); + $case->setAttribute("cov", $info[2]); + $case->setAttribute('failNumber', $info[0]); + $case->setAttribute('totalNumber', $info[1]); + $case->setAttribute('recordCovForBrowser',$info[5]); + $case->setAttribute('browserInfo', $config['browser']); + $case->setAttribute('hostInfo', Config::$BROWSERS[$config['browser']][0]); + // covHtml( $config[ 'browser' ] . '/' . $key , $info[ 2 ] ); + if ($failure > 0) { + $failures++; + $failinfo = $case->appendChild($dom->createElement('failure')); + $failinfo->setAttribute('type', 'junit.framework.AssertionFailedError'); + //FROM php.net, You cannot simply overwrite $textContent, to replace the text content of a DOMNode, as the missing readonly flag suggests. + $kiss = join(".", split("/", $key)); + // $failinfo->appendChild( new DOMText( $value ) ); + $failinfo->appendChild(new DOMText("run")); + } + //TODO add more case info in xml + } + + $suite->setAttribute('time', $time); + $suite->setAttribute('failures', $failures); + $suite->setAttribute('tests', $tests); + +// $dirName = "report_{$config['filter']}"; + $dirName = str_replace('/','_',"report_{$config['filter']}"); + if (!is_dir($dirName)) + mkdir($dirName); + $dom->save($dirName."/{$config['browser']}.xml"); +} +include 'config.php'; +$config; +$configs = preg_split('/[&=]/', $_POST['config']); +for ($j = 0; $j < sizeof($configs); $j += 2) { + // echo "{$cfg[$i]} {$cfg[$i+1]}\r\n
    "; +// if(strcmp($configs[$j],'browserSet')==0){ + $config[$configs[$j]] = $configs[$j + 1]; +// } + +} +report(); + +$dom = new DOMDocument('1.0', 'utf-8'); +$testsuites = $dom->appendChild($dom->createElement('testsuites')); +$dirName = str_replace('/','_',"report_{$config['filter']}"); +foreach (Config::getBrowserSet($configBrowserSet) as $key => $value) { + + $file = $dirName."/$key.xml"; + if (!file_exists($file)) { + echo "wait for report : $file\r\n
    "; + return; + } +// Config::StopOne($key); + $xmlDoc = new DOMDocument('1.0', 'utf-8'); + $xmlDoc->load($file); + $xmlDom = $xmlDoc->documentElement; + //echo $xmlDom->nodeName; + $testsuites->appendChild($dom->importNode($xmlDom, true)); +} +$dom->save("report.xml"); +$browserNum = count(Config::getBrowserSet($configBrowserSet)); +require_once 'record.php'; +record(); + +Config::StopAll(); +?> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/run.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/run.php new file mode 100644 index 000000000..2d355eba5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/run.php @@ -0,0 +1,46 @@ +'; +} +; +require_once "case.class.php"; +$c = new Kiss( '../../../' , $_GET[ 'case' ] ); +$title = $c->name; +$cov = array_key_exists( 'cov' , $_GET ); +?> + + + + <?php print( "run case $title" );?> + print_js( $cov ); ?> + + +

    name );?>

    + +

    + +

    +
      + +
      + + + +
      + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/runC.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/runC.php new file mode 100644 index 000000000..3671cbb81 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/runC.php @@ -0,0 +1,46 @@ +'; +} +; +require_once "case.class.php"; +$c = new Kiss( '../../../' , $_GET[ 'case' ] ); +$title = $c->name; +$cov = array_key_exists( 'cov' , $_GET ); +?> + + + + <?php print( "run case $title" );?> + print_all_js( $cov ); ?> + + +

      name );?>

      + +

      + +

      +
        + +
        + + + +
        + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/runall.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/runall.php new file mode 100644 index 000000000..b1cf61e5e --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/runall.php @@ -0,0 +1,119 @@ +\n"; + } + } + } + closedir( $handle ); + if ( rmdir( $dirName ) ) echo "成功删除目录: $dirName
        \n"; + } +} + +if ( array_key_exists( 'clear' , $_GET ) ) { + print 'debug - clear report'; + //Config::StopAll(); + if ( file_exists( 'report' ) ) + delDirAndFile( 'report' ); +} +$reportfile = "report_{$_GET['filter']}"; +if ( file_exists( $reportfile ) ) { + // rmdir('report'); + $reports = scandir( $reportfile ); + /*自己和父节点*/ + print 'on batch run, please waiting : ' . ( sizeof( $reports ) - 2 ); + return; +} else { + mkdir( $reportfile ); +} + +if ( file_exists( "./coverage/source.js" ) ) { + if ( unlink( "./coverage/source.js" ) ) echo "成功删除文件:source.js"; +} +source(); + +if ( file_exists( "covreport.html" ) ) { + if ( unlink( "covreport.html" ) ) echo "成功删除覆盖率报告文件: covreport.html
        \n"; +} +if ( file_exists( "jshintReport.html" ) ) { + if ( unlink( "jshintReport.html" ) ) echo "成功删除: jshintReport.html
        \n"; +} +exec("python ../lib/jshunter_1.2.0.1/jshunter_dev/jshunter/hint.py jshintReport.html ../../../_src", $back); +echo "jshint: ".$back."
        \n"; +/*记录运行时信息*/ +$b = array_key_exists( 'browser' , $_GET ) ? $_GET[ 'browser' ] : 'all'; + +//if ( array_key_exists( 'cov' , $_GET ) ){ + + +if ( $b != 'all' ) { + run( $b , true ); +} else { + Config::StopAll(); //添加启动前结束浏览器步骤 + $browsers = array_key_exists( 'browserSet' , $_GET )?Config::getBrowserSet($_GET[ 'browserSet' ]):Config::$BROWSERS; + foreach ( $browsers as $b => $i ) { + run( $b ); + sleep(40); + } +} +?> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test1_1.txt b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test1_1.txt new file mode 100644 index 000000000..2814efbfe --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test1_1.txt @@ -0,0 +1,76 @@ +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + +

        +

        + 欢迎使用ueditor! + + +

        +

        + +

        +

        + 欢迎使用ueditor! + + +

        +

        + +

        +

        + 1. +欢迎使用ueditor! + + +

        +

        + 2. +欢迎使用ueditor! + + +

        +

        + +

        +

        + l 欢迎使用ueditor! + + +

        +

        + l 欢迎使用ueditor! + + +

        +

        \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test1_2.txt b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test1_2.txt new file mode 100644 index 000000000..34ebd9f70 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test1_2.txt @@ -0,0 +1,38 @@ +

        +

        + +

        +

        + 欢迎使用ueditor! + + +

        +

        + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test1_3.txt b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test1_3.txt new file mode 100644 index 000000000..81a09424b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test1_3.txt @@ -0,0 +1,65 @@ + + + + + + + + + + + +
        +

        欢迎使用ueditor!

        +
        +

         

        +
        +

         

        +
        +

         

        +
        +

         

        +
        +

        欢迎使用ueditor!

        +
        + +

        + +

        www.baidu.com

        \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test2_1.txt b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test2_1.txt new file mode 100644 index 000000000..a918d07de --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test2_1.txt @@ -0,0 +1,57 @@ +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 一、欢迎使用ueditor! + + +

        +

        + 二、欢迎使用ueditor! + + +

        +

        + l 欢迎使用ueditor! + + +

        +

        + l 欢迎使用ueditor! + + +

        +

        \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test2_2.txt b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test2_2.txt new file mode 100644 index 000000000..36a45ee8f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test2_2.txt @@ -0,0 +1,32 @@ +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        + 欢迎使用ueditor! + + +

        +

        \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test2_3.txt b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test2_3.txt new file mode 100644 index 000000000..b26ec40b0 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test2_3.txt @@ -0,0 +1,156 @@ +

        +

        +

        + +

        + + + + + +
        + + + + + + + + + +
        + + + + + +

        + 欢迎使用ueditor! + + +

        + +
        + +
        + + +

        + +

        + +
        + + + + + + + +
        + + +

        + +

        + +
        + + + + + + + +
        +
        + + + + + + + + +
        + + + + + +

        + +

        + +
        + + + + + + + +
        + + +

        + +

        + +
        + + + + + + + +
        + + +

        + 欢迎使用ueditor! + + +

        + +
        + + + + + + + +
        +
        +

        + + + +

        www.baidu.com
        +

        +

        \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test3_1.txt b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test3_1.txt new file mode 100644 index 000000000..24bc0bd06 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/br/txt/test3_1.txt @@ -0,0 +1,131 @@ + + +

        欢迎使用ueditor!

        + +

        欢迎使用ueditor!

        + +

         

        + +

        欢迎使用ueditor!

        + +

        欢迎使用ueditor!

        + + + + + + + + + + + + +
        +

        欢迎使用ueditor!

        +
        +

         

        +
        +

         

        +
        +

         

        +
        +

         

        +
        +

        欢迎使用ueditor!

        +
        + +

         

        \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/coverage/cov.bat b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/coverage/cov.bat new file mode 100644 index 000000000..3bc2d3f22 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/coverage/cov.bat @@ -0,0 +1,2 @@ +@echo off +jscoverage.exe --encoding=UTF-8 ../../../_src ../../coverage \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/coverage/jscoverage.exe b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/coverage/jscoverage.exe new file mode 100644 index 000000000..1151644a1 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/coverage/jscoverage.exe differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/data/frame.html b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/data/frame.html new file mode 100644 index 000000000..d5f7c5a3e --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/data/frame.html @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/data/frame.php b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/data/frame.php new file mode 100644 index 000000000..b5ec9a2f0 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/data/frame.php @@ -0,0 +1,16 @@ + + + + +"; +else +print ""; +?> + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/data/test.JPG b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/data/test.JPG new file mode 100644 index 000000000..68343f2d1 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/data/test.JPG differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/data/test.html b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/data/test.html new file mode 100644 index 000000000..ff34eec49 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/data/test.html @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/data/testReady.html b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/data/testReady.html new file mode 100644 index 000000000..27dcb3f17 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/data/testReady.html @@ -0,0 +1,10 @@ + + + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/ant_tangram_ext.jar b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/ant_tangram_ext.jar new file mode 100644 index 000000000..4cd595a13 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/ant_tangram_ext.jar differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/js.jar b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/js.jar new file mode 100644 index 000000000..2369f99a9 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/js.jar differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/check.cfg b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/check.cfg new file mode 100644 index 000000000..ddff6ad9b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/check.cfg @@ -0,0 +1,117 @@ +[option] +asi = true +#if automatic semicolon insertion should be tolerated +bitwise = false +#if bitwise operators should not be allowed +boss = true +# if advanced usage of assignments should be allowed +browser= true +# if the standard browser globals should be predefined +couch = true +# if CouchDB globals should be predefined +curly = false +# if curly braces around all blocks should be required +debug = false +# if debugger statements should be allowed +devel = false +# if logging globals should be predefined (console,alertetc.) +dojo = false +# if Dojo Toolkit globals should be predefined +eqeqeq = false +# if === should be required +eqnull = false +# if == null comparisons should be tolerated +es5 = false +# if ES5 syntax should be allowed +esnext = false +# if es.next specific syntax should be allowed +evil = true +# if eval should be allowed +expr = true +# if ExpressionStatement should be allowed as Programs +forin = false +# if for in statements must filter +funcscope = true +# if only function scope should be used for scope tests +globalstrict = true +# if global "use strict"; should be allowed (also enables 'strict') +immed = false +# if immediate invocations must be wrapped in parents +iterator = true +# if the `__iterator__` property should be allowed +jquery = true +# if jQuery globals should be predefined +lastsemic = true +# if semicolons may be ommitted for the trailing statements inside of a one-line blocks. +latedef= true +# if the use before definition should not be tolerated +laxbreak = true +# if line breaks should not be checked +loopfunc = false +# if functions should be allowed to be defined within loops +mootools = true +# if MooTools globals should be predefined +multistr = true +# allow multiline strings +newcap = false +# if constructor names must be capitalized +noarg = false +# if arguments.caller and arguments.callee should be disallowed +node = false +# if the Node.js environment globals should be predefined +noempty= false +# if empty blocks should be disallowed +nonew = true +# if using `new` for side-effects should be disallowed +nonstandard = true +# if non-standard (but widely adopted) globals should be predefined +nomen = false +# if names should be checked +onevar = true +# if only one var statement per function should be allowed +onecase= true +# if one case switch statements should be allowed +passfail = false +# if the scan should stop on first error +plusplus = false +# if increment/decrement should not be allowed +proto = true +# if the `__proto__` property should be allowed +prototypejs = true +# if Prototype and Scriptaculous globals should be predefined +regexdash = true +# if unescaped first/last dash (-) inside brackets should be tolerated +regexp = true +# if the . should not be allowed in regexp literals +rhino = true +# if the Rhino environment globals should be predefined +undef = false +# if variables should be declared before used +scripturl = true +# if script-targeted URLs should be tolerated +shadow = true +# if variable shadowing should be tolerated +strict = false +# require the "use strict"; pragma +sub = true +# if all forms of subscript notation are tolerated +supernew = true +# if `new function () { ... };` and `new Object;` should be tolerated +trailing = false +# if trailing whitespace rules apply +validthis = true +# if 'this' inside a non-constructor function is valid. This is a function scoped option only. +white = false +# if strict whitespace rules apply +wsh = true +# if the Windows Scripting Host environment globals should be predefined +[predef] +baidu = true +nuit = true +Ext = true +ko = true +_ = true +noah = true +Noah = true +Backbone = true +WdatePicker = true diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/custcheck.conf b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/custcheck.conf new file mode 100644 index 000000000..85cda0c46 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/custcheck.conf @@ -0,0 +1 @@ +[command] diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/ignore.list b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/ignore.list new file mode 100644 index 000000000..503cb6410 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/ignore.list @@ -0,0 +1,14 @@ +#there 3 level:ignore warning error +[level] +Unsafe character=ignore +Mixed spaces and tabs=warning +Too many var statements=ignore +Unclosed string=ignore +Missing semicolon=error +Unexpected dangling=ignore +to compare with=ignore +is not defined=ignore +Unexpected dangling=ignore +A constructor name should start with an uppercase letter=warning +Expected an assignment or function call and instead saw an expression=warning +Mixed spaces and tabs=ignore diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/omitfiles.conf b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/omitfiles.conf new file mode 100644 index 000000000..2b6f42ee2 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/omitfiles.conf @@ -0,0 +1,4 @@ +#[config format]:REGULAR:true|false,true means set filtering enabeld and false means not +#notice:REGULAR will be set in the command "find /top/dir -name REGULAR" +[omitfils] +*data*:true diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/customcheck/cust.sh b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/customcheck/cust.sh new file mode 100644 index 000000000..7c5482ffb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/customcheck/cust.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +echo $1'***222***444***555***666' diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/jshint/js.jar b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/jshint/js.jar new file mode 100644 index 000000000..c081d16b8 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/jshint/js.jar differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/jshint/jshint-rhino.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/jshint/jshint-rhino.js new file mode 100644 index 000000000..c7c9b2ec0 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/jshint/jshint-rhino.js @@ -0,0 +1,89 @@ +/*jshint boss: true, rhino: true */ +/*globals JSHINT*/ + + + +(function (args) { + var filenames = [], + optstr, // arg1=val1,arg2=val2,... + predef, // global1=override,global2,global3,... + opts = { rhino: true }, + retval = 0; + load(args[0]+"jshint.js"); + + for(var i=1;i ' + (err.evidence || '').replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1")); + //print(''); + //print("==========="); + //print(err.evidence); + //print(err.raw); + //print(err.a); + //print("==========="); + //var myReport = JSHINT.report(false); + //print(myReport); + } + retval = 1; + } + }); + + quit(retval); +}(arguments)); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/tpl/htmlpart.html b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/tpl/htmlpart.html new file mode 100644 index 000000000..51de2a626 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/tpl/htmlpart.html @@ -0,0 +1,15 @@ + + +
        {$title}
        +
        + + + + + + + + + [---to be replaced 2---] + +
        \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/tpl/toggle_tpl.html b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/tpl/toggle_tpl.html new file mode 100644 index 000000000..ce857cd1a --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/tpl/toggle_tpl.html @@ -0,0 +1,324 @@ + + + + + +JsHunter Check Report + + + + + + + + + +
        JSHunter Report
        +
        + +
        +
        + + + + + + + + + + + + + + + + + + + + + + +
        TOTAL PROBLEM:{$pnumber}
        IGNORED:{$ignumber}
        ERROR:{$errnumber}
        WARNING:{$warnumber}
        DATA TIME:{$timeData}
        +
        +

         

        +
        +
        + [---to be replace 1---] +
        + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/hint.py b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/hint.py new file mode 100644 index 000000000..cd9b718d6 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/hint.py @@ -0,0 +1,425 @@ +#!/usr/bin/python +#encoding=utf-8 +import sys,os +import ConfigParser +import commands +import time +import codecs + +htmlMap = {} +def processHtml(filename): + f = open(filename,"r") + if f is None: + raise Exception('open %s error!' % (filename)) + newName = os.sep.join(os.path.abspath(__file__).split(os.sep)[:-1]) + os.sep + "core" + os.sep + "data"+os.sep+os.path.basename(filename) + "." + str(time.time()) + #print newName + tmp = "" + flag=False + orig_num = 0 + new_num = 0 + for ln in f: + orig_num += 1 + if ln.find("") == -1: + flag=True + continue + if ln.find("") != -1: + flag=False + continue + if ln.find("") == -1: + flag=True + continue + if ln.find("") != -1: + flag=False + continue + if ln.find("") != -1: + flag=False + continue + if flag == True: + tmp += ln + new_num += 1 + htmlMap[filename+os.sep+str(orig_num)]=newName + os.sep + str(new_num) + if tmp == "": + print ('[WARNING]file %s not contain js code' % (filename)) + return "" + outfile = open(newName,"w") + if outfile is None: + raise Exception('open %s error!' % (newName)) + outfile.write(tmp) + #print htmlMap + return newName + +def clearTmpFiles(): + dels=[] + for key in htmlMap.keys(): + fn = os.sep.join(htmlMap[key].split(os.sep)[:-1]) + if not fn in dels: + dels.append(fn) + #print dels + for item in dels: + os.remove(item) +def isHiddenFile(path): + itms = path.split(os.sep) + for itm in itms: + if itm != "" and itm != "." and itm != ".." and itm[0]==".": + return True + return False +''' +@input +a file (or a top dir) to be checked +@process +recuresively read all the files of a dir.only support .html and .js. +if it is a html file then we only check the code between +if it is a js file then we check all the code +@return +file(or folder) to be checked +''' +def getFiles(paths): + #print paths + ret = [] + omitpath = os.path.dirname(__file__) + os.sep + "conf" + os.sep + "omitfiles.conf" + for path in paths: + path = path.rstrip(os.sep) + if not os.path.isdir(path): + omitfiles = getOmitedFiles(omitpath,os.sep.join(path.split(os.sep)[:-1])+os.sep) + if (os.path.getsize(path)==0) or (path in omitfiles): + continue + if path.find(".js") != -1 and isHiddenFile(path)==False: + ret.append(path) + elif path.find(".html") != -1 and isHiddenFile(path)==False: + np = processHtml(path) + if np != "": + ret.append(np) + else: + omitfiles = getOmitedFiles(omitpath,path) + for root, dirs, files in os.walk(path): + for f in files: + if (os.path.getsize(root + os.sep + f)==0) or ((root + os.sep + f) in omitfiles): + continue + if f.find(".js") != -1 and isHiddenFile(root + os.sep + f) == False: + ret.append(root + os.sep + f) + elif f.find(".html") != -1 and isHiddenFile(root + os.sep + f) == False: + np=processHtml(root + os.sep + f) + if np != "": + ret.append(np) + else: + continue + return ret + + +def getopt(path): + _opt=[] + _predef=[] + conf = ConfigParser.ConfigParser() + conf.read(path) + for item in conf.options('option'): + _opt.append("%s=%s"%(item,conf.get('option',item))) + for item in conf.options('predef'): + _predef.append("%s=%s"%(item,conf.get('predef',item))) + return "%s %s"%(",".join(_opt),",".join(_predef)) + +def getBlackList(path): + lst={} + conf = ConfigParser.ConfigParser() + conf.read(path) + for item in conf.options('level'): + lst[item]=conf.get('level',item) + return lst + +def printReport(rptstr): + if rptstr=="": + return + array = rptstr.split('\n') + for ln in array: + items = ln.split("***") + if items[1].find("Stopping") != -1: + print items[1] + else: + print "文件:%s\t错误原因:%s\t错误位置:第%s行\t错误语句:%s"%(items[0],items[1],items[2],items[4]) +def processItem(item,blacklst,hp): + itm = item + for key in hp.keys(): + if item[0]+os.sep+item[2] == hp[key]: + itm[0]=os.sep.join(key.split(os.sep)[:-1]) + itm[2]=key.split(os.sep)[-1] + #print "====",itm,"======" + itm.append("error") + for err in blacklst.keys(): + if itm[1].lower().find(err.lower())!=-1: + itm[5] = blacklst[err] + break + return itm +''' +parse jshint output +''' +def splitOutput(rptstr,blacklist,mp): + if rptstr=="": + return + array = rptstr.split('\n') + lst=[] + parsecnt = 0; + parsetotal=len(array) + for ln in array: + #print ln + if ln.find("***") == -1: + continue + items = processItem(ln.split("***"),blacklist,mp) + if items[1].find("Stopping") != -1: + print items[1] + else: + lst.append(items) + parsecnt = parsecnt + 1 + return (lst,parsecnt,parsetotal) +''' +get the table body according to the result-list +''' +def getBody(lst): + files={} + error=0 + warning=0 + ignore=0; + count=0 + for item in lst: + count = count + 1 + if len(item)<6: + continue + if not files.has_key(item[0]): + if item[5] == "ignore": + ignore = ignore + 1 + elif item[5] == "error": + error = error + 1 + files[item[0]] = getLine(item,count) + else: + files[item[0]] = getLine(item,count) + warning = warning + 1 + else: + if item[5] == "ignore": + ignore = ignore + 1 + elif item[5] == "error": + error = error + 1 + files[item[0]] = files[item[0]] + getLine(item,count) + else: + files[item[0]] = files[item[0]] + getLine(item,count) + warning = warning + 1 + return (files,ignore,warning,error) + +def generateHtml(rptstr,outfile,blacklst,mp): + print "start parsing jshint output..." + (lst,parsecnt,parsetotal) = splitOutput(rptstr,blacklst,mp) + print "prepare main tpl..." + tpl="" + tplPath=os.sep.join(os.path.abspath(__file__).split(os.sep)[:-1])+os.sep+"core"+os.sep+"tpl"+os.sep+"toggle_tpl.html" + if not os.path.exists(tplPath): + raise Exception('%s file does not exists!'%(tplPath)) + f=open(tplPath,"r") + if f is None: + raise Exception('open %s error!' % (tplPath)) + for ln in f: + tpl+=ln + strStartTime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + tpl=tpl.replace("{$pnumber}",str(len(lst))) + tpl=tpl.replace("{$timeData}",strStartTime) + f.close() + print "blacklist filtering..." + (files,ignore,warning,error) = getBody(lst) + tpl=tpl.replace("{$ignumber}","%s(%5.1f%%)"%(str(ignore),(float(ignore)/len(lst)*100))) + tpl=tpl.replace("{$errnumber}","%s(%5.1f%%)"%(str(error),(float(error)/len(lst)*100))) + tpl=tpl.replace("{$warnumber}","%s(%5.1f%%)"%(str(warning),(float(warning)/len(lst)*100))) + print "prepare body" + bodys="" + for key in files: + tblPath=os.sep.join(os.path.abspath(__file__).split(os.sep)[:-1])+os.sep+"core"+os.sep+"tpl"+os.sep+"htmlpart.html" + if not os.path.exists(tblPath): + raise Exception('%s file does not exists!'%(tblPath)) + f=open(tblPath,"r") + body='''''' + for ln in f: + body += ln + body = body.replace("{$title}",key) + body = body.replace("{$fname}",key) + f.close() + body = body.replace("[---to be replaced 2---]",files[key]) + bodys = bodys + body + if bodys=="": + #raise Exception('no report generated') + bodys = "no informatin maybe they are filtered" + tpl=tpl.replace("[---to be replace 1---]",bodys) + ts=str(int(time.time())) + resf=open(outfile,"w") + if resf is None: + raise Exception('open %s error!' % (outfile)) + resf.write(tpl) + resf.close() + print "generate html file %s OK!"%(outfile) + return ts + +def getLine(item,no): + #print item + text = '''%s%s%s%s%s'''%(str(no),item[5],item[1],item[2],item[4].replace("<","<").replace(">",">")) + return text + +def genReport(status,output,blackpath,outfile,htmlMap): + #if status == 0: + # print "[WARNING][NO ERROR DETECTED BY JSHUNTER]" + #else: + if output.find("open file") != -1: + raise Exception("File Not Found Error!") + print "[ERROR DETECTED BY JSHUNTER]" + blacklist = getBlackList(blackpath) + ts = generateHtml(output,outfile,blacklist,htmlMap) + return ts + +def checkJavaExist(): + cmd="java" + (status,output) = commands.getstatusoutput(cmd) + if status != 0: + raise Exception("jshunter depend on java enviroment.please make sure your java is OK") +def checkPythonExist(): + cmd="python -h" + (status,output) = commands.getstatusoutput(cmd) + if status != 0: + raise Exception("jshunter depend on python enviroment.please make sure your python is OK") + +def getCustomerCheckFiles(paths): + omitpath = os.path.dirname(__file__) + os.sep + "conf" + os.sep + "omitfiles.conf" + ret = [] + for path in paths: + path = path.rstrip(os.sep) + if not os.path.isdir(path): + omitfiles = getOmitedFiles(omitpath,os.sep.join(path.split(os.sep)[:-1])+os.sep) + if ((os.path.getsize(path)==0) or (path in omitfiles)): + continue + ret.append(path) + else: + omitfiles = getOmitedFiles(omitpath,path) + for root, dirs, files in os.walk(path): + for f in files: + if (os.path.getsize(root + os.sep + f)==0) or ((root + os.sep + f) in omitfiles): + continue + else: + ret.append(root + os.sep + f) + return ret +def getOmitedFiles(confpath,topdir): + _res = [] + _opt = [] + conf = ConfigParser.ConfigParser() + conf.read(confpath) + for item in conf.options('omitfils'): + if conf.get('omitfils',item) == "true": + _opt.append(item) + if (not os.path.isdir(topdir)) and (len(_opt) > 0): + return [] + for item in _opt: + cmd = 'find %s -name "%s"'%(topdir,item) + #print cmd + (status,output) = commands.getstatusoutput(cmd) + if status != 0: + raise Exception("[FATAL]cmd failed!%s"%(cmd)) + #print output + for ln in output.split("\n"): + _res.append(ln) + return _res + +def usage(): + print "====================================================================================================================" + print "[Usage]\n./hint outpath.html fileToCheck.js\t\t检查fileToCheck.js这个文件" + print "./hint outpath.html folderToCheck\t\t检查folderToCheck这个目录内的所有js文件和html文件(递归检查)" + print "./hint outpath.html folderToCheck/*.js\t\t检查folderToCheck一级目录下的所有js文件和html文件(忽略目录)" + print "[Notice]使用时请确保当前目录中包含jshint.js文件,建议cd到jshunter的目录中执行./hint.py" + print "[Contact] pankai01@baidu.com liulanying01@baidu.com" + print "====================================================================================================================" + +def doJsHint(_path): + fileToCheck=getFiles(_path) + step = 50 + javapath = "java" + jsjar = os.path.dirname(__file__) + os.sep + "core" + os.sep + "jshint" + os.sep + "js.jar" + rhino = os.path.dirname(__file__) + os.sep + "core" + os.sep + "jshint" + os.sep + "jshint-rhino.js" + confpath = os.path.dirname(__file__) + os.sep + "conf" + os.sep + "check.cfg" + blackpath = os.path.dirname(__file__) + os.sep + "conf" + os.sep + "ignore.list" + opt = getopt(confpath) + sz = len(fileToCheck) + if sz <= 0: + print "[WARNING]no file to be checked in doJsHint" + return "" + print "Files to be checked Number: %d"%(sz) + for i in range(0,sz): + print (i+1),":",fileToCheck[i] + output="" + if sz <= step: + opt = "%s %s"%(getopt(confpath)," ".join(fileToCheck[:])) + cmd = "%s -jar %s %s %s %s"%(javapath,jsjar,rhino,os.path.dirname(__file__) + os.sep,opt) + (status,output) = commands.getstatusoutput(cmd) + else: + rd=sz/step+1 + for j in range(0,rd): + if (j+1)*step>sz: + opt = "%s %s"%(getopt(confpath)," ".join(fileToCheck[j*step:sz])) + else: + opt = "%s %s"%(getopt(confpath)," ".join(fileToCheck[j*step:(j+1)*step])) + cmd = "%s -jar %s %s %s %s"%(javapath,jsjar,rhino,os.path.dirname(__file__) + os.sep,opt) + (status,output_tmp)=commands.getstatusoutput(cmd) + if status != 0 and output_tmp.find("open file") != -1: + raise Exception("File Not Found Error.ERRMSG:%s\n"%(output_tmp)) + else: + output = output + output_tmp + print "Finish %5.1f%%"%((j+1)*float(str(step))/sz*100.0) + return output + +def doCustomerCheck(_path): + confpath = os.path.dirname(__file__) + os.sep + "conf" + os.sep + "custcheck.conf" + custpath = os.path.dirname(__file__) + os.sep + "core" + os.sep + "customcheck" + os.sep + ops = getCustCheckOpt(confpath) + fileToCheck = getCustomerCheckFiles(_path) + sz = len(fileToCheck) + if sz == 0: + print "[WARNING]no file to be checked in doCustomerCheck" + return "" + custout = '' + #print ops + for item in ops: + for i in range(0,sz): + cmd = "%s %s"%(custpath+item,fileToCheck[i]) + #print cmd + (status,output_tmp)=commands.getstatusoutput(cmd) + for ln in output_tmp.split("\n"): + #print ln + if ln.find("***") != -1: + custout += (ln+"\n") + + #print custout + return custout + +def getCustCheckOpt(path): + _opt=[] + conf = ConfigParser.ConfigParser() + conf.read(path) + for item in conf.options('command'): + if conf.get('command',item) == "true": + _opt.append(item) + return _opt + +if __name__ == "__main__": + try: + #checkJavaExist() + #checkPythonExist() + #print "check enviroment ok" + if len(sys.argv) < 3: + usage() + raise Exception("arg number error!") + outfile=sys.argv[1] + if os.path.exists(outfile): + raise Exception('%s already exist!In order to avoid overwrite the file,please change a none-exist file!'%(outfile)) + blackpath = os.path.dirname(__file__) + os.sep + "conf" + os.sep + "ignore.list" + filepath = sys.argv[2:] + output1 = doJsHint(filepath) + output2 = doCustomerCheck(filepath) + output = output1 + output2 + if output != "": + ts = genReport(0,output,blackpath,outfile,htmlMap) + else: + print "[WARNING]%s"%("no error detected") + clearTmpFiles() + except Exception,err: + print "[FATAL]%s"%(err) + clearTmpFiles() + sys.exit(1) diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/jshint.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/jshint.js new file mode 100644 index 000000000..9b08c0df1 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/jshint.js @@ -0,0 +1,4278 @@ +/*! + * JSHint, by JSHint Community. + * + * Licensed under the same slightly modified MIT license that JSLint is. + * It stops evil-doers everywhere. + * + * JSHint is a derivative work of JSLint: + * + * Copyright (c) 2002 Douglas Crockford (www.JSLint.com) + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * The Software shall be used for Good, not Evil. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * JSHint was forked from 2010-12-16 edition of JSLint. + * + */ + +/* + JSHINT is a global function. It takes two parameters. + + var myResult = JSHINT(source, option); + + The first parameter is either a string or an array of strings. If it is a + string, it will be split on '\n' or '\r'. If it is an array of strings, it + is assumed that each string represents one line. The source can be a + JavaScript text or a JSON text. + + The second parameter is an optional object of options which control the + operation of JSHINT. Most of the options are booleans: They are all + optional and have a default value of false. One of the options, predef, + can be an array of names, which will be used to declare global variables, + or an object whose keys are used as global names, with a boolean value + that determines if they are assignable. + + If it checks out, JSHINT returns true. Otherwise, it returns false. + + If false, you can inspect JSHINT.errors to find out the problems. + JSHINT.errors is an array of objects containing these members: + + { + line : The line (relative to 0) at which the lint was found + character : The character (relative to 0) at which the lint was found + reason : The problem + evidence : The text line in which the problem occurred + raw : The raw message before the details were inserted + a : The first detail + b : The second detail + c : The third detail + d : The fourth detail + } + + If a fatal error was found, a null will be the last element of the + JSHINT.errors array. + + You can request a Function Report, which shows all of the functions + and the parameters and vars that they use. This can be used to find + implied global variables and other problems. The report is in HTML and + can be inserted in an HTML . + + var myReport = JSHINT.report(limited); + + If limited is true, then the report will be limited to only errors. + + You can request a data structure which contains JSHint's results. + + var myData = JSHINT.data(); + + It returns a structure with this form: + + { + errors: [ + { + line: NUMBER, + character: NUMBER, + reason: STRING, + evidence: STRING + } + ], + functions: [ + name: STRING, + line: NUMBER, + last: NUMBER, + param: [ + STRING + ], + closure: [ + STRING + ], + var: [ + STRING + ], + exception: [ + STRING + ], + outer: [ + STRING + ], + unused: [ + STRING + ], + global: [ + STRING + ], + label: [ + STRING + ] + ], + globals: [ + STRING + ], + member: { + STRING: NUMBER + }, + unuseds: [ + { + name: STRING, + line: NUMBER + } + ], + implieds: [ + { + name: STRING, + line: NUMBER + } + ], + urls: [ + STRING + ], + json: BOOLEAN + } + + Empty arrays will not be included. + +*/ + +/*jshint + evil: false, nomen: false, onevar: true, regexp: false, strict: false, boss: true, eqeqeq : false,bitwise: false,newcap: false,white: false, asi: true,trailing: false,funcscope: false,noarg:true,sub:true,loopfunc:true, +onevar: true, esnext: true,debug: false,laxbreak: trueundef: true, maxlen: 100, indent:4 +*/ + +/*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "(begin)", + "(breakage)", "(context)", "(error)", "(global)", "(identifier)", "(last)", + "(line)", "(loopage)", "(name)", "(onevar)", "(params)", "(scope)", + "(statement)", "(verb)", "*", "+", "++", "-", "--", "\/", "<", "<=", "==", + "===", ">", ">=", $, $$, $A, $F, $H, $R, $break, $continue, $w, Abstract, Ajax, + __filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView, Audio, + Autocompleter, Assets, Boolean, Builder, Buffer, Browser, COM, CScript, Canvas, + CustomAnimation, Class, Control, Chain, Color, Cookie, Core, DataView, Date, + Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMReady, Drag, + E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event, + Events, FadeAnimation, Field, Flash, Float32Array, Float64Array, Form, + FormField, Frame, FormData, Function, Fx, GetObject, Group, Hash, HotKey, + HTMLElement, HTMLAnchorElement, HTMLBaseElement, HTMLBlockquoteElement, + HTMLBodyElement, HTMLBRElement, HTMLButtonElement, HTMLCanvasElement, HTMLDirectoryElement, + HTMLDivElement, HTMLDListElement, HTMLFieldSetElement, + HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement, + HTMLHeadElement, HTMLHeadingElement, HTMLHRElement, HTMLHtmlElement, + HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLIsIndexElement, + HTMLLabelElement, HTMLLayerElement, HTMLLegendElement, HTMLLIElement, + HTMLLinkElement, HTMLMapElement, HTMLMenuElement, HTMLMetaElement, + HTMLModElement, HTMLObjectElement, HTMLOListElement, HTMLOptGroupElement, + HTMLOptionElement, HTMLParagraphElement, HTMLParamElement, HTMLPreElement, + HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLStyleElement, + HtmlTable, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement, + HTMLTableElement, HTMLTableRowElement, HTMLTableSectionElement, + HTMLTextAreaElement, HTMLTitleElement, HTMLUListElement, HTMLVideoElement + Iframe, IframeShim, Image, Int16Array, Int32Array, Int8Array, + Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E, + MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem, MoveAnimation, MooTools, Native, + NEGATIVE_INFINITY, Number, Object, ObjectRange, Option, Options, OverText, PI, + POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype, RangeError, + Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation, + SQRT1_2, SQRT2, ScrollBar, ScriptEngine, ScriptEngineBuildVersion, + ScriptEngineMajorVersion, ScriptEngineMinorVersion, Scriptaculous, Scroller, + Slick, Slider, Selector, SharedWorker, String, Style, SyntaxError, Sortable, Sortables, + SortableObserver, Sound, Spinner, System, Swiff, Text, TextArea, Template, + Timer, Tips, Type, TypeError, Toggle, Try, "use strict", unescape, URI, URIError, URL, + VBArray, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XPathEvaluator, + XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult, "\\", a, + addEventListener, address, alert, apply, applicationCache, arguments, arity, + asi, b, bitwise, block, blur, boolOptions, boss, browser, c, call, callee, + caller, cases, charAt, charCodeAt, character, clearInterval, clearTimeout, + close, closed, closure, comment, condition, confirm, console, constructor, + content, couch, create, css, curly, d, data, datalist, dd, debug, decodeURI, + decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document, + dojo, dijit, dojox, define, edition, else, emit, encodeURI, encodeURIComponent, + entityify, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil, + ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus, + forin, fragment, frames, from, fromCharCode, fud, funcscope, funct, function, functions, + g, gc, getComputedStyle, getRow, GLOBAL, global, globals, globalstrict, + hasOwnProperty, help, history, i, id, identifier, immed, implieds, importPackage, include, + indent, indexOf, init, ins, instanceOf, isAlpha, isApplicationRunning, isArray, + isDigit, isFinite, isNaN, iterator, java, join, jshint, + JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastsemic, laxbreak, + latedef, lbp, led, left, length, line, load, loadClass, localStorage, location, + log, loopfunc, m, match, maxerr, maxlen, member,message, meta, module, moveBy, + moveTo, mootools, multistr, name, navigator, new, newcap, noarg, node, noempty, nomen, + nonew, nonstandard, nud, onbeforeunload, onblur, onerror, onevar, onecase, onfocus, + onload, onresize, onunload, open, openDatabase, openURL, opener, opera, options, outer, param, + parent, parseFloat, parseInt, passfail, plusplus, predef, print, process, prompt, + proto, prototype, prototypejs, push, quit, range, raw, reach, reason, regexp, + readFile, readUrl, regexdash, removeEventListener, replace, report, require, + reserved, resizeBy, resizeTo, resolvePath, resumeUpdates, respond, rhino, right, + runCommand, scroll, screen, scripturl, scrollBy, scrollTo, scrollbar, search, seal, + send, serialize, sessionStorage, setInterval, setTimeout, shift, slice, sort,spawn, + split, stack, status, start, strict, sub, substr, supernew, shadow, supplant, sum, + sync, test, toLowerCase, toString, toUpperCase, toint32, token, top, trailing, type, + typeOf, Uint16Array, Uint32Array, Uint8Array, undef, unused, urls, validthis, value, valueOf, + var, version, WebSocket, white, window, Worker, wsh*/ + +/*global exports: false */ + +// We build the application inside a function so that we produce only a single +// global variable. That function will be invoked immediately, and its return +// value is the JSHINT function itself. + +var JSHINT = (function () { + "use strict"; + + var anonname, // The guessed name for anonymous functions. + +// These are operators that should not be used with the ! operator. + + bang = { + '<' : true, + '<=' : true, + '==' : true, + '===': true, + '!==': true, + '!=' : true, + '>' : true, + '>=' : true, + '+' : true, + '-' : true, + '*' : true, + '/' : true, + '%' : true + }, + + // These are the JSHint boolean options. + boolOptions = { + asi : true, // if automatic semicolon insertion should be tolerated + bitwise : true, // if bitwise operators should not be allowed + boss : true, // if advanced usage of assignments should be allowed + browser : true, // if the standard browser globals should be predefined + couch : true, // if CouchDB globals should be predefined + curly : true, // if curly braces around all blocks should be required + debug : true, // if debugger statements should be allowed + devel : true, // if logging globals should be predefined (console, + // alert, etc.) + dojo : true, // if Dojo Toolkit globals should be predefined + eqeqeq : true, // if === should be required + eqnull : true, // if == null comparisons should be tolerated + es5 : true, // if ES5 syntax should be allowed + esnext : true, // if es.next specific syntax should be allowed + evil : true, // if eval should be allowed + expr : true, // if ExpressionStatement should be allowed as Programs + forin : true, // if for in statements must filter + funcscope : true, // if only function scope should be used for scope tests + globalstrict: true, // if global "use strict"; should be allowed (also + // enables 'strict') + immed : true, // if immediate invocations must be wrapped in parens + iterator : true, // if the `__iterator__` property should be allowed + jquery : true, // if jQuery globals should be predefined + lastsemic : true, // if semicolons may be ommitted for the trailing + // statements inside of a one-line blocks. + latedef : true, // if the use before definition should not be tolerated + laxbreak : true, // if line breaks should not be checked + loopfunc : true, // if functions should be allowed to be defined within + // loops + mootools : true, // if MooTools globals should be predefined + multistr : true, // allow multiline strings + newcap : true, // if constructor names must be capitalized + noarg : true, // if arguments.caller and arguments.callee should be + // disallowed + node : true, // if the Node.js environment globals should be + // predefined + noempty : true, // if empty blocks should be disallowed + nonew : true, // if using `new` for side-effects should be disallowed + nonstandard : true, // if non-standard (but widely adopted) globals should + // be predefined + nomen : true, // if names should be checked + onevar : true, // if only one var statement per function should be + // allowed + onecase : true, // if one case switch statements should be allowed + passfail : true, // if the scan should stop on first error + plusplus : true, // if increment/decrement should not be allowed + proto : true, // if the `__proto__` property should be allowed + prototypejs : true, // if Prototype and Scriptaculous globals should be + // predefined + regexdash : true, // if unescaped first/last dash (-) inside brackets + // should be tolerated + regexp : true, // if the . should not be allowed in regexp literals + rhino : true, // if the Rhino environment globals should be predefined + undef : true, // if variables should be declared before used + scripturl : true, // if script-targeted URLs should be tolerated + shadow : true, // if variable shadowing should be tolerated + strict : true, // require the "use strict"; pragma + sub : true, // if all forms of subscript notation are tolerated + supernew : true, // if `new function () { ... };` and `new Object;` + // should be tolerated + trailing : true, // if trailing whitespace rules apply + validthis : true, // if 'this' inside a non-constructor function is valid. + // This is a function scoped option only. + white : true, // if strict whitespace rules apply + wsh : true // if the Windows Scripting Host environment globals + // should be predefined + }, + + // browser contains a set of global names which are commonly provided by a + // web browser environment. + browser = { + ArrayBuffer : false, + ArrayBufferView : false, + Audio : false, + addEventListener : false, + applicationCache : false, + blur : false, + clearInterval : false, + clearTimeout : false, + close : false, + closed : false, + DataView : false, + defaultStatus : false, + document : false, + event : false, + FileReader : false, + Float32Array : false, + Float64Array : false, + FormData : false, + focus : false, + frames : false, + getComputedStyle : false, + HTMLElement : false, + HTMLAnchorElement : false, + HTMLBaseElement : false, + HTMLBlockquoteElement : false, + HTMLBodyElement : false, + HTMLBRElement : false, + HTMLButtonElement : false, + HTMLCanvasElement : false, + HTMLDirectoryElement : false, + HTMLDivElement : false, + HTMLDListElement : false, + HTMLFieldSetElement : false, + HTMLFontElement : false, + HTMLFormElement : false, + HTMLFrameElement : false, + HTMLFrameSetElement : false, + HTMLHeadElement : false, + HTMLHeadingElement : false, + HTMLHRElement : false, + HTMLHtmlElement : false, + HTMLIFrameElement : false, + HTMLImageElement : false, + HTMLInputElement : false, + HTMLIsIndexElement : false, + HTMLLabelElement : false, + HTMLLayerElement : false, + HTMLLegendElement : false, + HTMLLIElement : false, + HTMLLinkElement : false, + HTMLMapElement : false, + HTMLMenuElement : false, + HTMLMetaElement : false, + HTMLModElement : false, + HTMLObjectElement : false, + HTMLOListElement : false, + HTMLOptGroupElement : false, + HTMLOptionElement : false, + HTMLParagraphElement : false, + HTMLParamElement : false, + HTMLPreElement : false, + HTMLQuoteElement : false, + HTMLScriptElement : false, + HTMLSelectElement : false, + HTMLStyleElement : false, + HTMLTableCaptionElement : false, + HTMLTableCellElement : false, + HTMLTableColElement : false, + HTMLTableElement : false, + HTMLTableRowElement : false, + HTMLTableSectionElement : false, + HTMLTextAreaElement : false, + HTMLTitleElement : false, + HTMLUListElement : false, + HTMLVideoElement : false, + history : false, + Int16Array : false, + Int32Array : false, + Int8Array : false, + Image : false, + length : false, + localStorage : false, + location : false, + moveBy : false, + moveTo : false, + name : false, + navigator : false, + onbeforeunload : true, + onblur : true, + onerror : true, + onfocus : true, + onload : true, + onresize : true, + onunload : true, + open : false, + openDatabase : false, + opener : false, + Option : false, + parent : false, + print : false, + removeEventListener : false, + resizeBy : false, + resizeTo : false, + screen : false, + scroll : false, + scrollBy : false, + scrollTo : false, + sessionStorage : false, + setInterval : false, + setTimeout : false, + SharedWorker : false, + status : false, + top : false, + Uint16Array : false, + Uint32Array : false, + Uint8Array : false, + WebSocket : false, + window : false, + Worker : false, + XMLHttpRequest : false, + XPathEvaluator : false, + XPathException : false, + XPathExpression : false, + XPathNamespace : false, + XPathNSResolver : false, + XPathResult : false + }, + + couch = { + "require" : false, + respond : false, + getRow : false, + emit : false, + send : false, + start : false, + sum : false, + log : false, + exports : false, + module : false + }, + + devel = { + alert : false, + confirm : false, + console : false, + Debug : false, + opera : false, + prompt : false + }, + + dojo = { + dojo : false, + dijit : false, + dojox : false, + define : false, + "require" : false + }, + + escapes = { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '/' : '\\/', + '\\': '\\\\' + }, + + funct, // The current function + + functionicity = [ + 'closure', 'exception', 'global', 'label', + 'outer', 'unused', 'var' + ], + + functions, // All of the functions + + global, // The global scope + implied, // Implied globals + inblock, + indent, + jsonmode, + + jquery = { + '$' : false, + jQuery : false + }, + + lines, + lookahead, + member, + membersOnly, + + mootools = { + '$' : false, + '$$' : false, + Assets : false, + Browser : false, + Chain : false, + Class : false, + Color : false, + Cookie : false, + Core : false, + Document : false, + DomReady : false, + DOMReady : false, + Drag : false, + Element : false, + Elements : false, + Event : false, + Events : false, + Fx : false, + Group : false, + Hash : false, + HtmlTable : false, + Iframe : false, + IframeShim : false, + InputValidator : false, + instanceOf : false, + Keyboard : false, + Locale : false, + Mask : false, + MooTools : false, + Native : false, + Options : false, + OverText : false, + Request : false, + Scroller : false, + Slick : false, + Slider : false, + Sortables : false, + Spinner : false, + Swiff : false, + Tips : false, + Type : false, + typeOf : false, + URI : false, + Window : false + }, + + nexttoken, + + node = { + __filename : false, + __dirname : false, + Buffer : false, + console : false, + exports : false, + GLOBAL : false, + global : false, + module : false, + process : false, + require : false, + setTimeout : false, + clearTimeout : false, + setInterval : false, + clearInterval : false + }, + + noreach, + option, + predefined, // Global variables defined by option + prereg, + prevtoken, + + prototypejs = { + '$' : false, + '$$' : false, + '$A' : false, + '$F' : false, + '$H' : false, + '$R' : false, + '$break' : false, + '$continue' : false, + '$w' : false, + Abstract : false, + Ajax : false, + Class : false, + Enumerable : false, + Element : false, + Event : false, + Field : false, + Form : false, + Hash : false, + Insertion : false, + ObjectRange : false, + PeriodicalExecuter: false, + Position : false, + Prototype : false, + Selector : false, + Template : false, + Toggle : false, + Try : false, + Autocompleter : false, + Builder : false, + Control : false, + Draggable : false, + Draggables : false, + Droppables : false, + Effect : false, + Sortable : false, + SortableObserver : false, + Sound : false, + Scriptaculous : false + }, + + rhino = { + defineClass : false, + deserialize : false, + gc : false, + help : false, + importPackage: false, + "java" : false, + load : false, + loadClass : false, + print : false, + quit : false, + readFile : false, + readUrl : false, + runCommand : false, + seal : false, + serialize : false, + spawn : false, + sync : false, + toint32 : false, + version : false + }, + + scope, // The current scope + src, + stack, + + // standard contains the global names that are provided by the + // ECMAScript standard. + standard = { + Array : false, + Boolean : false, + Date : false, + decodeURI : false, + decodeURIComponent : false, + encodeURI : false, + encodeURIComponent : false, + Error : false, + 'eval' : false, + EvalError : false, + Function : false, + hasOwnProperty : false, + isFinite : false, + isNaN : false, + JSON : false, + Math : false, + Number : false, + Object : false, + parseInt : false, + parseFloat : false, + RangeError : false, + ReferenceError : false, + RegExp : false, + String : false, + SyntaxError : false, + TypeError : false, + URIError : false + }, + + // widely adopted global names that are not part of ECMAScript standard + nonstandard = { + escape : false, + unescape : false + }, + + standard_member = { + E : true, + LN2 : true, + LN10 : true, + LOG2E : true, + LOG10E : true, + MAX_VALUE : true, + MIN_VALUE : true, + NEGATIVE_INFINITY : true, + PI : true, + POSITIVE_INFINITY : true, + SQRT1_2 : true, + SQRT2 : true + }, + + directive, + syntax = {}, + tab, + token, + urls, + useESNextSyntax, + warnings, + + wsh = { + ActiveXObject : true, + Enumerator : true, + GetObject : true, + ScriptEngine : true, + ScriptEngineBuildVersion : true, + ScriptEngineMajorVersion : true, + ScriptEngineMinorVersion : true, + VBArray : true, + WSH : true, + WScript : true, + XDomainRequest : true + }; + + // Regular expressions. Some of these are stupidly long. + var ax, cx, tx, nx, nxg, lx, ix, jx, ft; + (function () { + /*jshint maxlen:300 */ + + // unsafe comment or string + ax = /@cc|<\/?|script|\]\s*\]|<\s*!|</i; + + // unsafe characters that are silently deleted by one or more browsers + cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; + + // token + tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jshint|jslint|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/; + + // characters in strings that need escapement + nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; + nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; + + // star slash + lx = /\*\/|\/\*/; + + // identifier + ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/; + + // javascript url + jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i; + + // catches /* falls through */ comments + ft = /^\s*\/\*\s*falls\sthrough\s*\*\/\s*$/; + }()); + + function F() {} // Used by Object.create + + function is_own(object, name) { + +// The object.hasOwnProperty method fails when the property under consideration +// is named 'hasOwnProperty'. So we have to use this more convoluted form. + + return Object.prototype.hasOwnProperty.call(object, name); + } + +// Provide critical ES5 functions to ES3. + + if (typeof Array.isArray !== 'function') { + Array.isArray = function (o) { + return Object.prototype.toString.apply(o) === '[object Array]'; + }; + } + + if (typeof Object.create !== 'function') { + Object.create = function (o) { + F.prototype = o; + return new F(); + }; + } + + if (typeof Object.keys !== 'function') { + Object.keys = function (o) { + var a = [], k; + for (k in o) { + if (is_own(o, k)) { + a.push(k); + } + } + return a; + }; + } + +// Non standard methods + + if (typeof String.prototype.entityify !== 'function') { + String.prototype.entityify = function () { + return this + .replace(/&/g, '&') + .replace(//g, '>'); + }; + } + + if (typeof String.prototype.isAlpha !== 'function') { + String.prototype.isAlpha = function () { + return (this >= 'a' && this <= 'z\uffff') || + (this >= 'A' && this <= 'Z\uffff'); + }; + } + + if (typeof String.prototype.isDigit !== 'function') { + String.prototype.isDigit = function () { + return (this >= '0' && this <= '9'); + }; + } + + if (typeof String.prototype.supplant !== 'function') { + String.prototype.supplant = function (o) { + return this.replace(/\{([^{}]*)\}/g, function (a, b) { + var r = o[b]; + return typeof r === 'string' || typeof r === 'number' ? r : a; + }); + }; + } + + if (typeof String.prototype.name !== 'function') { + String.prototype.name = function () { + +// If the string looks like an identifier, then we can return it as is. +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can simply slap some quotes around it. +// Otherwise we must also replace the offending characters with safe +// sequences. + + if (ix.test(this)) { + return this; + } + if (nx.test(this)) { + return '"' + this.replace(nxg, function (a) { + var c = escapes[a]; + if (c) { + return c; + } + return '\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4); + }) + '"'; + } + return '"' + this + '"'; + }; + } + + + function combine(t, o) { + var n; + for (n in o) { + if (is_own(o, n)) { + t[n] = o[n]; + } + } + } + + function assume() { + if (option.couch) { + combine(predefined, couch); + } + + if (option.rhino) { + combine(predefined, rhino); + } + + if (option.prototypejs) { + combine(predefined, prototypejs); + } + + if (option.node) { + combine(predefined, node); + } + + if (option.devel) { + combine(predefined, devel); + } + + if (option.dojo) { + combine(predefined, dojo); + } + + if (option.browser) { + combine(predefined, browser); + } + + if (option.nonstandard) { + combine(predefined, nonstandard); + } + + if (option.jquery) { + combine(predefined, jquery); + } + + if (option.mootools) { + combine(predefined, mootools); + } + + if (option.wsh) { + combine(predefined, wsh); + } + + if (option.esnext) { + useESNextSyntax(); + } + + if (option.globalstrict && option.strict !== false) { + option.strict = true; + } + } + + + // Produce an error warning. + function quit(message, line, chr) { + var percentage = Math.floor((line / lines.length) * 100); + + throw { + name: 'JSHintError', + line: line, + character: chr, + message: message + " (" + percentage + "% scanned)." + }; + } + + function warning(m, t, a, b, c, d) { + var ch, l, w; + t = t || nexttoken; + if (t.id === '(end)') { // `~ + t = token; + } + l = t.line || 0; + ch = t.from || 0; + w = { + id: '(error)', + raw: m, + evidence: lines[l - 1] || '', + line: l, + character: ch, + a: a, + b: b, + c: c, + d: d + }; + w.reason = m.supplant(w); + JSHINT.errors.push(w); + if (option.passfail) { + quit('Stopping. ', l, ch); + } + warnings += 1; + if (warnings >= option.maxerr) { + quit("Too many errors.", l, ch); + } + return w; + } + + function warningAt(m, l, ch, a, b, c, d) { + return warning(m, { + line: l, + from: ch + }, a, b, c, d); + } + + function error(m, t, a, b, c, d) { + var w = warning(m, t, a, b, c, d); + } + + function errorAt(m, l, ch, a, b, c, d) { + return error(m, { + line: l, + from: ch + }, a, b, c, d); + } + + + +// lexical analysis and token construction + + var lex = (function lex() { + var character, from, line, s; + +// Private lex methods + + function nextLine() { + var at, + tw; // trailing whitespace check + + if (line >= lines.length) + return false; + + character = 1; + s = lines[line]; + line += 1; + at = s.search(/ \t|\t /); + + if (at >= 0) + warningAt("Mixed spaces and tabs.", line, at + 1); + + s = s.replace(/\t/g, tab); + at = s.search(cx); + + if (at >= 0) + warningAt("Unsafe character.", line, at); + + if (option.maxlen && option.maxlen < s.length) + warningAt("Line too long.", line, s.length); + + // Check for trailing whitespaces + tw = /\s+$/.test(s); + if (option.trailing && tw && !/^\s+$/.test(s)) { + warningAt("Trailing whitespace.", line, tw); + } + return true; + } + +// Produce a token object. The token inherits from a syntax symbol. + + function it(type, value) { + var i, t; + if (type === '(color)' || type === '(range)') { + t = {type: type}; + } else if (type === '(punctuator)' || + (type === '(identifier)' && is_own(syntax, value))) { + t = syntax[value] || syntax['(error)']; + } else { + t = syntax[type]; + } + t = Object.create(t); + if (type === '(string)' || type === '(range)') { + if (!option.scripturl && jx.test(value)) { + warningAt("Script URL.", line, from); + } + } + if (type === '(identifier)') { + t.identifier = true; + if (value === '__proto__' && !option.proto) { + warningAt("The '{a}' property is deprecated.", + line, from, value); + } else if (value === '__iterator__' && !option.iterator) { + warningAt("'{a}' is only available in JavaScript 1.7.", + line, from, value); + } else if (option.nomen && (value.charAt(0) === '_' || + value.charAt(value.length - 1) === '_')) { + if (!option.node || token.id == '.' || + (value != '__dirname' && value != '__filename')) { + warningAt("Unexpected {a} in '{b}'.", line, from, "dangling '_'", value); + } + } + } + t.value = value; + t.line = line; + t.character = character; + t.from = from; + i = t.id; + if (i !== '(endline)') { + prereg = i && + (('(,=:[!&|?{};'.indexOf(i.charAt(i.length - 1)) >= 0) || + i === 'return' || + i === 'case'); + } + return t; + } + + // Public lex methods + return { + init: function (source) { + if (typeof source === 'string') { + lines = source + .replace(/\r\n/g, '\n') + .replace(/\r/g, '\n') + .split('\n'); + } else { + lines = source; + } + + // If the first line is a shebang (#!), make it a blank and move on. + // Shebangs are used by Node scripts. + if (lines[0] && lines[0].substr(0, 2) == '#!') + lines[0] = ''; + + line = 0; + nextLine(); + from = 1; + }, + + range: function (begin, end) { + var c, value = ''; + from = character; + if (s.charAt(0) !== begin) { + errorAt("Expected '{a}' and instead saw '{b}'.", + line, character, begin, s.charAt(0)); + } + for (;;) { + s = s.slice(1); + character += 1; + c = s.charAt(0); + switch (c) { + case '': + errorAt("Missing '{a}'.", line, character, c); + break; + case end: + s = s.slice(1); + character += 1; + return it('(range)', value); + case '\\': + warningAt("Unexpected '{a}'.", line, character, c); + } + value += c; + } + + }, + + + // token -- this is called by advance to get the next token + token: function () { + var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange; + + function match(x) { + var r = x.exec(s), r1; + if (r) { + l = r[0].length; + r1 = r[1]; + c = r1.charAt(0); + s = s.substr(l); + from = character + l - r1.length; + character += l; + return r1; + } + } + + function string(x) { + var c, j, r = '', allowNewLine = false; + + if (jsonmode && x !== '"') { + warningAt("Strings must use doublequote.", + line, character); + } + + function esc(n) { + var i = parseInt(s.substr(j + 1, n), 16); + j += n; + if (i >= 32 && i <= 126 && + i !== 34 && i !== 92 && i !== 39) { + warningAt("Unnecessary escapement.", line, character); + } + character += n; + c = String.fromCharCode(i); + } + j = 0; + for (;;) { + while (j >= s.length) { + j = 0; + if (allowNewLine) { + allowNewLine = false; + } else { + warningAt("Unclosed string.", line, from); + } + if (!nextLine()) { + errorAt("Unclosed string.", line, from); + } + } + c = s.charAt(j); + if (c === x) { + character += 1; + s = s.substr(j + 1); + return it('(string)', r, x); + } + if (c < ' ') { + if (c === '\n' || c === '\r') { + break; + } + warningAt("Control character in string: {a}.", + line, character + j, s.slice(0, j)); + } else if (c === '\\') { + j += 1; + character += 1; + c = s.charAt(j); + switch (c) { + case '\\': + case '"': + case '/': + break; + case '\'': + if (jsonmode) { + warningAt("Avoid \\'.", line, character); + } + break; + case 'b': + c = '\b'; + break; + case 'f': + c = '\f'; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'u': + esc(4); + break; + case 'v': + if (jsonmode) { + warningAt("Avoid \\v.", line, character); + } + c = '\v'; + break; + case 'x': + if (jsonmode) { + warningAt("Avoid \\x-.", line, character); + } + esc(2); + break; + case '': + // last character is escape character + // always allow new line if escaped, but show + // warning if option is not set + allowNewLine = true; + if (option.multistr) { + if (jsonmode) { + warningAt("Avoid EOL escapement.", line, character); + } + c = ''; + character -= 1; + break; + } + warningAt("Bad escapement of EOL. Use option multistr if needed.", + line, character); + break; + default: + warningAt("Bad escapement.", line, character); + } + } + r += c; + character += 1; + j += 1; + } + } + + for (;;) { + if (!s) { + return it(nextLine() ? '(endline)' : '(end)', ''); + } + t = match(tx); + if (!t) { + t = ''; + c = ''; + while (s && s < '!') { + s = s.substr(1); + } + if (s) { + errorAt("Unexpected '{a}'.", line, character, s.substr(0, 1)); + } + } else { + + // identifier + + if (c.isAlpha() || c === '_' || c === '$') { + return it('(identifier)', t); + } + + // number + + if (c.isDigit()) { + if (!isFinite(Number(t))) { + warningAt("Bad number '{a}'.", + line, character, t); + } + if (s.substr(0, 1).isAlpha()) { + warningAt("Missing space after '{a}'.", + line, character, t); + } + if (c === '0') { + d = t.substr(1, 1); + if (d.isDigit()) { + if (token.id !== '.') { + warningAt("Don't use extra leading zeros '{a}'.", + line, character, t); + } + } else if (jsonmode && (d === 'x' || d === 'X')) { + warningAt("Avoid 0x-. '{a}'.", + line, character, t); + } + } + if (t.substr(t.length - 1) === '.') { + warningAt( +"A trailing decimal point can be confused with a dot '{a}'.", line, character, t); + } + return it('(number)', t); + } + switch (t) { + + // string + + case '"': + case "'": + return string(t); + + // // comment + + case '//': + if (src) { + warningAt("Unexpected comment.", line, character); + } + s = ''; + token.comment = true; + break; + + // /* comment + + case '/*': + if (src) { + warningAt("Unexpected comment.", line, character); + } + for (;;) { + i = s.search(lx); + if (i >= 0) { + break; + } + if (!nextLine()) { + errorAt("Unclosed comment.", line, character); + } + } + character += i + 2; + if (s.substr(i, 1) === '/') { + errorAt("Nested comment.", line, character); + } + s = s.substr(i + 2); + token.comment = true; + break; + + // /*members /*jshint /*global + + case '/*members': + case '/*member': + case '/*jshint': + case '/*jslint': + case '/*global': + case '*/': + return { + value: t, + type: 'special', + line: line, + character: character, + from: from + }; + + case '': + break; + // / + case '/': + if (token.id === '/=') { + errorAt( +"A regular expression literal can be confused with '/='.", line, from); + } + if (prereg) { + depth = 0; + captures = 0; + l = 0; + for (;;) { + b = true; + c = s.charAt(l); + l += 1; + switch (c) { + case '': + errorAt("Unclosed regular expression.", + line, from); + return; + case '/': + if (depth > 0) { + warningAt("Unescaped '{a}'.", + line, from + l, '/'); + } + c = s.substr(0, l - 1); + q = { + g: true, + i: true, + m: true + }; + while (q[s.charAt(l)] === true) { + q[s.charAt(l)] = false; + l += 1; + } + character += l; + s = s.substr(l); + q = s.charAt(0); + if (q === '/' || q === '*') { + errorAt("Confusing regular expression.", + line, from); + } + return it('(regexp)', c); + case '\\': + c = s.charAt(l); + if (c < ' ') { + warningAt( +"Unexpected control character in regular expression.", line, from + l); + } else if (c === '<') { + warningAt( +"Unexpected escaped character '{a}' in regular expression.", line, from + l, c); + } + l += 1; + break; + case '(': + depth += 1; + b = false; + if (s.charAt(l) === '?') { + l += 1; + switch (s.charAt(l)) { + case ':': + case '=': + case '!': + l += 1; + break; + default: + warningAt( +"Expected '{a}' and instead saw '{b}'.", line, from + l, ':', s.charAt(l)); + } + } else { + captures += 1; + } + break; + case '|': + b = false; + break; + case ')': + if (depth === 0) { + warningAt("Unescaped '{a}'.", + line, from + l, ')'); + } else { + depth -= 1; + } + break; + case ' ': + q = 1; + while (s.charAt(l) === ' ') { + l += 1; + q += 1; + } + if (q > 1) { + warningAt( +"Spaces are hard to count. Use {{a}}.", line, from + l, q); + } + break; + case '[': + c = s.charAt(l); + if (c === '^') { + l += 1; + if (option.regexp) { + warningAt("Insecure '{a}'.", + line, from + l, c); + } else if (s.charAt(l) === ']') { + errorAt("Unescaped '{a}'.", + line, from + l, '^'); + } + } + if (c === ']') { + warningAt("Empty class.", line, + from + l - 1); + } + isLiteral = false; + isInRange = false; +klass: do { + c = s.charAt(l); + l += 1; + switch (c) { + case '[': + case '^': + warningAt("Unescaped '{a}'.", + line, from + l, c); + if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + break; + case '-': + if (isLiteral && !isInRange) { + isLiteral = false; + isInRange = true; + } else if (isInRange) { + isInRange = false; + } else if (s.charAt(l) === ']') { + isInRange = true; + } else { + if (option.regexdash !== (l === 2 || (l === 3 && + s.charAt(2) === '^'))) { + warningAt("Unescaped '{a}'.", + line, from + l - 1, '-'); + } + isLiteral = true; + } + break; + case ']': + if (isInRange && !option.regexdash) { + warningAt("Unescaped '{a}'.", + line, from + l - 1, '-'); + } + break klass; + case '\\': + c = s.charAt(l); + if (c < ' ') { + warningAt( +"Unexpected control character in regular expression.", line, from + l); + } else if (c === '<') { + warningAt( +"Unexpected escaped character '{a}' in regular expression.", line, from + l, c); + } + l += 1; + + // \w, \s and \d are never part of a character range + if (/[wsd]/i.test(c)) { + if (isInRange) { + warningAt("Unescaped '{a}'.", + line, from + l, '-'); + isInRange = false; + } + isLiteral = false; + } else if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + break; + case '/': + warningAt("Unescaped '{a}'.", + line, from + l - 1, '/'); + + if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + break; + case '<': + if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + break; + default: + if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + } + } while (c); + break; + case '.': + if (option.regexp) { + warningAt("Insecure '{a}'.", line, + from + l, c); + } + break; + case ']': + case '?': + case '{': + case '}': + case '+': + case '*': + warningAt("Unescaped '{a}'.", line, + from + l, c); + } + if (b) { + switch (s.charAt(l)) { + case '?': + case '+': + case '*': + l += 1; + if (s.charAt(l) === '?') { + l += 1; + } + break; + case '{': + l += 1; + c = s.charAt(l); + if (c < '0' || c > '9') { + warningAt( +"Expected a number and instead saw '{a}'.", line, from + l, c); + } + l += 1; + low = +c; + for (;;) { + c = s.charAt(l); + if (c < '0' || c > '9') { + break; + } + l += 1; + low = +c + (low * 10); + } + high = low; + if (c === ',') { + l += 1; + high = Infinity; + c = s.charAt(l); + if (c >= '0' && c <= '9') { + l += 1; + high = +c; + for (;;) { + c = s.charAt(l); + if (c < '0' || c > '9') { + break; + } + l += 1; + high = +c + (high * 10); + } + } + } + if (s.charAt(l) !== '}') { + warningAt( +"Expected '{a}' and instead saw '{b}'.", line, from + l, '}', c); + } else { + l += 1; + } + if (s.charAt(l) === '?') { + l += 1; + } + if (low > high) { + warningAt( +"'{a}' should not be greater than '{b}'.", line, from + l, low, high); + } + } + } + } + c = s.substr(0, l - 1); + character += l; + s = s.substr(l); + return it('(regexp)', c); + } + return it('(punctuator)', t); + + // punctuator + + case '#': + return it('(punctuator)', t); + default: + return it('(punctuator)', t); + } + } + } + } + }; + }()); + + + function addlabel(t, type) { + + if (t === 'hasOwnProperty') { + warning("'hasOwnProperty' is a really bad name."); + } + +// Define t in the current function in the current scope. + + if (is_own(funct, t) && !funct['(global)']) { + if (funct[t] === true) { + if (option.latedef) + warning("'{a}' was used before it was defined.", nexttoken, t); + } else { + if (!option.shadow) + warning("'{a}' is already defined.", nexttoken, t); + } + } + + funct[t] = type; + if (funct['(global)']) { + global[t] = funct; + if (is_own(implied, t)) { + if (option.latedef) + warning("'{a}' was used before it was defined.", nexttoken, t); + delete implied[t]; + } + } else { + scope[t] = funct; + } + } + + + function doOption() { + var b, obj, filter, o = nexttoken.value, t, v; + switch (o) { + case '*/': + error("Unbegun comment."); + break; + case '/*members': + case '/*member': + o = '/*members'; + if (!membersOnly) { + membersOnly = {}; + } + obj = membersOnly; + break; + case '/*jshint': + case '/*jslint': + obj = option; + filter = boolOptions; + break; + case '/*global': + obj = predefined; + break; + default: + error("What?"); + } + t = lex.token(); +loop: for (;;) { + for (;;) { + if (t.type === 'special' && t.value === '*/') { + break loop; + } + if (t.id !== '(endline)' && t.id !== ',') { + break; + } + t = lex.token(); + } + if (t.type !== '(string)' && t.type !== '(identifier)' && + o !== '/*members') { + error("Bad option.", t); + } + v = lex.token(); + if (v.id === ':') { + v = lex.token(); + if (obj === membersOnly) { + error("Expected '{a}' and instead saw '{b}'.", + t, '*/', ':'); + } + if (t.value === 'indent' && (o === '/*jshint' || o === '/*jslint')) { + b = +v.value; + if (typeof b !== 'number' || !isFinite(b) || b <= 0 || + Math.floor(b) !== b) { + error("Expected a small integer and instead saw '{a}'.", + v, v.value); + } + obj.white = true; + obj.indent = b; + } else if (t.value === 'maxerr' && (o === '/*jshint' || o === '/*jslint')) { + b = +v.value; + if (typeof b !== 'number' || !isFinite(b) || b <= 0 || + Math.floor(b) !== b) { + error("Expected a small integer and instead saw '{a}'.", + v, v.value); + } + obj.maxerr = b; + } else if (t.value === 'maxlen' && (o === '/*jshint' || o === '/*jslint')) { + b = +v.value; + if (typeof b !== 'number' || !isFinite(b) || b <= 0 || + Math.floor(b) !== b) { + error("Expected a small integer and instead saw '{a}'.", + v, v.value); + } + obj.maxlen = b; + } else if (t.value == 'validthis') { + if (funct['(global)']) { + error("Option 'validthis' can't be used in a global scope."); + } else { + if (v.value === 'true' || v.value === 'false') + obj[t.value] = v.value === 'true'; + else + error("Bad option value.", v); + } + } else if (v.value === 'true') { + obj[t.value] = true; + } else if (v.value === 'false') { + obj[t.value] = false; + } else { + error("Bad option value.", v); + } + t = lex.token(); + } else { + if (o === '/*jshint' || o === '/*jslint') { + error("Missing option value.", t); + } + obj[t.value] = false; + t = v; + } + } + if (filter) { + assume(); + } + } + + +// We need a peek function. If it has an argument, it peeks that much farther +// ahead. It is used to distinguish +// for ( var i in ... +// from +// for ( var i = ... + + function peek(p) { + var i = p || 0, j = 0, t; + + while (j <= i) { + t = lookahead[j]; + if (!t) { + t = lookahead[j] = lex.token(); + } + j += 1; + } + return t; + } + + + +// Produce the next token. It looks for programming errors. + + function advance(id, t) { + switch (token.id) { + case '(number)': + if (nexttoken.id === '.') { + warning("A dot following a number can be confused with a decimal point.", token); + } + break; + case '-': + if (nexttoken.id === '-' || nexttoken.id === '--') { + warning("Confusing minusses."); + } + break; + case '+': + if (nexttoken.id === '+' || nexttoken.id === '++') { + warning("Confusing plusses."); + } + break; + } + + if (token.type === '(string)' || token.identifier) { + anonname = token.value; + } + + if (id && nexttoken.id !== id) { + if (t) { + if (nexttoken.id === '(end)') { + warning("Unmatched '{a}'.", t, t.id); + } else { + warning("Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.", + nexttoken, id, t.id, t.line, nexttoken.value); + } + } else if (nexttoken.type !== '(identifier)' || + nexttoken.value !== id) { + warning("Expected '{a}' and instead saw '{b}'.", + nexttoken, id, nexttoken.value); + } + } + + prevtoken = token; + token = nexttoken; + for (;;) { + nexttoken = lookahead.shift() || lex.token(); + if (nexttoken.id === '(end)' || nexttoken.id === '(error)') { + return; + } + if (nexttoken.type === 'special') { + doOption(); + } else { + if (nexttoken.id !== '(endline)') { + break; + } + } + } + } + + +// This is the heart of JSHINT, the Pratt parser. In addition to parsing, it +// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is +// like .nud except that it is only used on the first token of a statement. +// Having .fud makes it much easier to define statement-oriented languages like +// JavaScript. I retained Pratt's nomenclature. + +// .nud Null denotation +// .fud First null denotation +// .led Left denotation +// lbp Left binding power +// rbp Right binding power + +// They are elements of the parsing method called Top Down Operator Precedence. + + function expression(rbp, initial) { + var left, isArray = false; + + if (nexttoken.id === '(end)') + error("Unexpected early end of program.", token); + + advance(); + if (initial) { + anonname = 'anonymous'; + funct['(verb)'] = token.value; + } + if (initial === true && token.fud) { + left = token.fud(); + } else { + if (token.nud) { + left = token.nud(); + } else { + if (nexttoken.type === '(number)' && token.id === '.') { + warning("A leading decimal point can be confused with a dot: '.{a}'.", + token, nexttoken.value); + advance(); + return token; + } else { + error("Expected an identifier and instead saw '{a}'.", + token, token.id); + } + } + while (rbp < nexttoken.lbp) { + isArray = token.value == 'Array'; + advance(); + if (isArray && token.id == '(' && nexttoken.id == ')') + warning("Use the array literal notation [].", token); + if (token.led) { + left = token.led(left); + } else { + error("Expected an operator and instead saw '{a}'.", + token, token.id); + } + } + } + return left; + } + + +// Functions for conformance of style. + + function adjacent(left, right) { + left = left || token; + right = right || nexttoken; + if (option.white) { + if (left.character !== right.from && left.line === right.line) { + warning("Unexpected space after '{a}'.", right, left.value); + } + } + } + + function nobreak(left, right) { + left = left || token; + right = right || nexttoken; + if (option.white && (left.character !== right.from || left.line !== right.line)) { + warning("Unexpected space before '{a}'.", right, right.value); + } + } + + function nospace(left, right) { + left = left || token; + right = right || nexttoken; + if (option.white && !left.comment) { + if (left.line === right.line) { + adjacent(left, right); + } + } + } + + function nonadjacent(left, right) { + if (option.white) { + left = left || token; + right = right || nexttoken; + if (left.line === right.line && left.character === right.from) { + left.from += (left.character - left.from); + warning("Missing space after '{a}'.", + left, left.value); + } + } + } + + function nobreaknonadjacent(left, right) { + left = left || token; + right = right || nexttoken; + if (!option.laxbreak && left.line !== right.line) { + warning("Bad line breaking before '{a}'.", right, right.id); + } else if (option.white) { + left = left || token; + right = right || nexttoken; + if (left.character === right.from) { + left.from += (left.character - left.from); + warning("Missing space after '{a}'.", + left, left.value); + } + } + } + + function indentation(bias) { + var i; + if (option.white && nexttoken.id !== '(end)') { + i = indent + (bias || 0); + if (nexttoken.from !== i) { + warning( +"Expected '{a}' to have an indentation at {b} instead at {c}.", + nexttoken, nexttoken.value, i, nexttoken.from); + } + } + } + + function nolinebreak(t) { + t = t || token; + if (t.line !== nexttoken.line) { + warning("Line breaking error '{a}'.", t, t.value); + } + } + + + function comma() { + if (token.line !== nexttoken.line) { + if (!option.laxbreak) { + warning("Bad line breaking before '{a}'.", token, nexttoken.id); + } + } else if (token.character !== nexttoken.from && option.white) { + warning("Unexpected space after '{a}'.", nexttoken, token.value); + } + advance(','); + nonadjacent(token, nexttoken); + } + + +// Functional constructors for making the symbols that will be inherited by +// tokens. + + function symbol(s, p) { + var x = syntax[s]; + if (!x || typeof x !== 'object') { + syntax[s] = x = { + id: s, + lbp: p, + value: s + }; + } + return x; + } + + + function delim(s) { + return symbol(s, 0); + } + + + function stmt(s, f) { + var x = delim(s); + x.identifier = x.reserved = true; + x.fud = f; + return x; + } + + + function blockstmt(s, f) { + var x = stmt(s, f); + x.block = true; + return x; + } + + + function reserveName(x) { + var c = x.id.charAt(0); + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + x.identifier = x.reserved = true; + } + return x; + } + + + function prefix(s, f) { + var x = symbol(s, 150); + reserveName(x); + x.nud = (typeof f === 'function') ? f : function () { + this.right = expression(150); + this.arity = 'unary'; + if (this.id === '++' || this.id === '--') { + if (option.plusplus) { + warning("Unexpected use of '{a}'.", this, this.id); + } else if ((!this.right.identifier || this.right.reserved) && + this.right.id !== '.' && this.right.id !== '[') { + warning("Bad operand.", this); + } + } + return this; + }; + return x; + } + + + function type(s, f) { + var x = delim(s); + x.type = s; + x.nud = f; + return x; + } + + + function reserve(s, f) { + var x = type(s, f); + x.identifier = x.reserved = true; + return x; + } + + + function reservevar(s, v) { + return reserve(s, function () { + if (typeof v === 'function') { + v(this); + } + return this; + }); + } + + + function infix(s, f, p, w) { + var x = symbol(s, p); + reserveName(x); + x.led = function (left) { + if (!w) { + nobreaknonadjacent(prevtoken, token); + nonadjacent(token, nexttoken); + } + if (typeof f === 'function') { + return f(left, this); + } else { + this.left = left; + this.right = expression(p); + return this; + } + }; + return x; + } + + + function relation(s, f) { + var x = symbol(s, 100); + x.led = function (left) { + nobreaknonadjacent(prevtoken, token); + nonadjacent(token, nexttoken); + var right = expression(100); + if ((left && left.id === 'NaN') || (right && right.id === 'NaN')) { + warning("Use the isNaN function to compare with NaN.", this); + } else if (f) { + f.apply(this, [left, right]); + } + if (left.id === '!') { + warning("Confusing use of '{a}'.", left, '!'); + } + if (right.id === '!') { + warning("Confusing use of '{a}'.", left, '!'); + } + this.left = left; + this.right = right; + return this; + }; + return x; + } + + + function isPoorRelation(node) { + return node && + ((node.type === '(number)' && +node.value === 0) || + (node.type === '(string)' && node.value === '') || + (node.type === 'null' && !option.eqnull) || + node.type === 'true' || + node.type === 'false' || + node.type === 'undefined'); + } + + + function assignop(s, f) { + symbol(s, 20).exps = true; + return infix(s, function (left, that) { + var l; + that.left = left; + if (predefined[left.value] === false && + scope[left.value]['(global)'] === true) { + warning("Read only.", left); + } else if (left['function']) { + warning("'{a}' is a function.", left, left.value); + } + if (left) { + if (option.esnext && funct[left.value] === 'const') { + warning("Attempting to override '{a}' which is a constant", left, left.value); + } + if (left.id === '.' || left.id === '[') { + if (!left.left || left.left.value === 'arguments') { + warning('Bad assignment.', that); + } + that.right = expression(19); + return that; + } else if (left.identifier && !left.reserved) { + if (funct[left.value] === 'exception') { + warning("Do not assign to the exception parameter.", left); + } + that.right = expression(19); + return that; + } + if (left === syntax['function']) { + warning( +"Expected an identifier in an assignment and instead saw a function invocation.", + token); + } + } + error("Bad assignment.", that); + }, 20); + } + + + function bitwise(s, f, p) { + var x = symbol(s, p); + reserveName(x); + x.led = (typeof f === 'function') ? f : function (left) { + if (option.bitwise) { + warning("Unexpected use of '{a}'.", this, this.id); + } + this.left = left; + this.right = expression(p); + return this; + }; + return x; + } + + + function bitwiseassignop(s) { + symbol(s, 20).exps = true; + return infix(s, function (left, that) { + if (option.bitwise) { + warning("Unexpected use of '{a}'.", that, that.id); + } + nonadjacent(prevtoken, token); + nonadjacent(token, nexttoken); + if (left) { + if (left.id === '.' || left.id === '[' || + (left.identifier && !left.reserved)) { + expression(19); + return that; + } + if (left === syntax['function']) { + warning( +"Expected an identifier in an assignment, and instead saw a function invocation.", + token); + } + return that; + } + error("Bad assignment.", that); + }, 20); + } + + + function suffix(s, f) { + var x = symbol(s, 150); + x.led = function (left) { + if (option.plusplus) { + warning("Unexpected use of '{a}'.", this, this.id); + } else if ((!left.identifier || left.reserved) && + left.id !== '.' && left.id !== '[') { + warning("Bad operand.", this); + } + this.left = left; + return this; + }; + return x; + } + + + // fnparam means that this identifier is being defined as a function + // argument (see identifier()) + function optionalidentifier(fnparam) { + if (nexttoken.identifier) { + advance(); + if (token.reserved && !option.es5) { + // `undefined` as a function param is a common pattern to protect + // against the case when somebody does `undefined = true` and + // help with minification. More info: https://gist.github.com/315916 + if (!fnparam || token.value != 'undefined') { + warning("Expected an identifier and instead saw '{a}' (a reserved word).", + token, token.id); + } + } + return token.value; + } + } + + // fnparam means that this identifier is being defined as a function + // argument + function identifier(fnparam) { + var i = optionalidentifier(fnparam); + if (i) { + return i; + } + if (token.id === 'function' && nexttoken.id === '(') { + warning("Missing name in function declaration."); + } else { + error("Expected an identifier and instead saw '{a}'.", + nexttoken, nexttoken.value); + } + } + + + function reachable(s) { + var i = 0, t; + if (nexttoken.id !== ';' || noreach) { + return; + } + for (;;) { + t = peek(i); + if (t.reach) { + return; + } + if (t.id !== '(endline)') { + if (t.id === 'function') { + warning( +"Inner functions should be listed at the top of the outer function.", t); + break; + } + warning("Unreachable '{a}' after '{b}'.", t, t.value, s); + break; + } + i += 1; + } + } + + + function statement(noindent) { + var i = indent, r, s = scope, t = nexttoken; + +// We don't like the empty statement. + + if (t.id === ';') { + warning("Unnecessary semicolon.", t); + advance(';'); + return; + } + +// Is this a labelled statement? + + if (t.identifier && !t.reserved && peek().id === ':') { + advance(); + advance(':'); + scope = Object.create(s); + addlabel(t.value, 'label'); + if (!nexttoken.labelled) { + warning("Label '{a}' on {b} statement.", + nexttoken, t.value, nexttoken.value); + } + if (jx.test(t.value + ':')) { + warning("Label '{a}' looks like a javascript url.", + t, t.value); + } + nexttoken.label = t.value; + t = nexttoken; + } + +// Parse the statement. + + if (!noindent) { + indentation(); + } + r = expression(0, true); + + // Look for the final semicolon. + if (!t.block) { + if (!option.expr && (!r || !r.exps)) { + warning("Expected an assignment or function call and instead saw an expression.", + token); + } else if (option.nonew && r.id === '(' && r.left.id === 'new') { + warning("Do not use 'new' for side effects."); + } + + if (nexttoken.id !== ';') { + if (!option.asi) { + // If this is the last statement in a block that ends on + // the same line *and* option lastsemic is on, ignore the warning. + // Otherwise, complain about missing semicolon. + if (!option.lastsemic || nexttoken.id != '}' || + nexttoken.line != token.line) { + warningAt("Missing semicolon.", token.line, token.from + + token.value.length); + } + } + } else { + adjacent(token, nexttoken); + advance(';'); + nonadjacent(token, nexttoken); + } + } + +// Restore the indentation. + + indent = i; + scope = s; + return r; + } + + + function statements(startLine) { + var a = [], f, p; + + while (!nexttoken.reach && nexttoken.id !== '(end)') { + if (nexttoken.id === ';') { + warning("Unnecessary semicolon."); + advance(';'); + } else { + a.push(statement(startLine === nexttoken.line)); + } + } + return a; + } + + + /* + * read all directives + * recognizes a simple form of asi, but always + * warns, if it is used + */ + function directives() { + var i, p, pn; + + for (;;) { + if (nexttoken.id === "(string)") { + p = peek(0); + if (p.id === "(endline)") { + i = 1; + do { + pn = peek(i); + i = i + 1; + } while (pn.id === "(endline)"); + + if (pn.id !== ";") { + if (pn.id !== "(string)" && pn.id !== "(number)" && + pn.id !== "(regexp)" && pn.identifier !== true && + pn.id !== "}") { + break; + } + warning("Missing semicolon.", nexttoken); + } else { + p = pn; + } + } else if (p.id === "}") { + // directive with no other statements, warn about missing semicolon + warning("Missing semicolon.", p); + } else if (p.id !== ";") { + break; + } + + indentation(); + advance(); + if (directive[token.value]) { + warning("Unnecessary directive \"{a}\".", token, token.value); + } + + if (token.value === "use strict") { + option.newcap = true; + option.undef = true; + } + + // there's no directive negation, so always set to true + directive[token.value] = true; + + if (p.id === ";") { + advance(";"); + } + continue; + } + break; + } + } + + + /* + * Parses a single block. A block is a sequence of statements wrapped in + * braces. + * + * ordinary - true for everything but function bodies and try blocks. + * stmt - true if block can be a single statement (e.g. in if/for/while). + * isfunc - true if block is a function body + */ + function block(ordinary, stmt, isfunc) { + var a, + b = inblock, + old_indent = indent, + m, + s = scope, + t, + line, + d; + + inblock = ordinary; + if (!ordinary || !option.funcscope) scope = Object.create(scope); + nonadjacent(token, nexttoken); + t = nexttoken; + + if (nexttoken.id === '{') { + advance('{'); + line = token.line; + if (nexttoken.id !== '}') { + indent += option.indent; + while (!ordinary && nexttoken.from > indent) { + indent += option.indent; + } + + if (isfunc) { + m = {}; + for (d in directive) { + if (is_own(directive, d)) { + m[d] = directive[d]; + } + } + directives(); + + if (option.strict && funct['(context)']['(global)']) { + if (!m["use strict"] && !directive["use strict"]) { + warning("Missing \"use strict\" statement."); + } + } + } + + a = statements(line); + + if (isfunc) { + directive = m; + } + + indent -= option.indent; + if (line !== nexttoken.line) { + indentation(); + } + } else if (line !== nexttoken.line) { + indentation(); + } + advance('}', t); + indent = old_indent; + } else if (!ordinary) { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, '{', nexttoken.value); + } else { + if (!stmt || option.curly) + warning("Expected '{a}' and instead saw '{b}'.", + nexttoken, '{', nexttoken.value); + + noreach = true; + indent += option.indent; + // test indentation only if statement is in new line + a = [statement(nexttoken.line === token.line)]; + indent -= option.indent; + noreach = false; + } + funct['(verb)'] = null; + if (!ordinary || !option.funcscope) scope = s; + inblock = b; + if (ordinary && option.noempty && (!a || a.length === 0)) { + warning("Empty block."); + } + return a; + } + + + function countMember(m) { + if (membersOnly && typeof membersOnly[m] !== 'boolean') { + warning("Unexpected /*member '{a}'.", token, m); + } + if (typeof member[m] === 'number') { + member[m] += 1; + } else { + member[m] = 1; + } + } + + + function note_implied(token) { + var name = token.value, line = token.line, a = implied[name]; + if (typeof a === 'function') { + a = false; + } + if (!a) { + a = [line]; + implied[name] = a; + } else if (a[a.length - 1] !== line) { + a.push(line); + } + } + + + // Build the syntax table by declaring the syntactic elements of the language. + + type('(number)', function () { + return this; + }); + + type('(string)', function () { + return this; + }); + + syntax['(identifier)'] = { + type: '(identifier)', + lbp: 0, + identifier: true, + nud: function () { + var v = this.value, + s = scope[v], + f; + + if (typeof s === 'function') { + // Protection against accidental inheritance. + s = undefined; + } else if (typeof s === 'boolean') { + f = funct; + funct = functions[0]; + addlabel(v, 'var'); + s = funct; + funct = f; + } + + // The name is in scope and defined in the current function. + if (funct === s) { + // Change 'unused' to 'var', and reject labels. + switch (funct[v]) { + case 'unused': + funct[v] = 'var'; + break; + case 'unction': + funct[v] = 'function'; + this['function'] = true; + break; + case 'function': + this['function'] = true; + break; + case 'label': + warning("'{a}' is a statement label.", token, v); + break; + } + } else if (funct['(global)']) { + // The name is not defined in the function. If we are in the global + // scope, then we have an undefined variable. + // + // Operators typeof and delete do not raise runtime errors even if + // the base object of a reference is null so no need to display warning + // if we're inside of typeof or delete. + if (anonname != 'typeof' && anonname != 'delete' && + option.undef && typeof predefined[v] !== 'boolean') { + warning("'{a}' is not defined.", token, v); + } + note_implied(token); + } else { + // If the name is already defined in the current + // function, but not as outer, then there is a scope error. + + switch (funct[v]) { + case 'closure': + case 'function': + case 'var': + case 'unused': + warning("'{a}' used out of scope.", token, v); + break; + case 'label': + warning("'{a}' is a statement label.", token, v); + break; + case 'outer': + case 'global': + break; + default: + // If the name is defined in an outer function, make an outer entry, + // and if it was unused, make it var. + if (s === true) { + funct[v] = true; + } else if (s === null) { + warning("'{a}' is not allowed.", token, v); + note_implied(token); + } else if (typeof s !== 'object') { + // Operators typeof and delete do not raise runtime errors even + // if the base object of a reference is null so no need to + // display warning if we're inside of typeof or delete. + if (anonname != 'typeof' && anonname != 'delete' && option.undef) { + warning("'{a}' is not defined.", token, v); + } else { + funct[v] = true; + } + note_implied(token); + } else { + switch (s[v]) { + case 'function': + case 'unction': + this['function'] = true; + s[v] = 'closure'; + funct[v] = s['(global)'] ? 'global' : 'outer'; + break; + case 'var': + case 'unused': + s[v] = 'closure'; + funct[v] = s['(global)'] ? 'global' : 'outer'; + break; + case 'closure': + case 'parameter': + funct[v] = s['(global)'] ? 'global' : 'outer'; + break; + case 'label': + warning("'{a}' is a statement label.", token, v); + } + } + } + } + return this; + }, + led: function () { + error("Expected an operator and instead saw '{a}'.", + nexttoken, nexttoken.value); + } + }; + + type('(regexp)', function () { + return this; + }); + + +// ECMAScript parser + + delim('(endline)'); + delim('(begin)'); + delim('(end)').reach = true; + delim(''); + delim('(error)').reach = true; + delim('}').reach = true; + delim(')'); + delim(']'); + delim('"').reach = true; + delim("'").reach = true; + delim(';'); + delim(':').reach = true; + delim(','); + delim('#'); + delim('@'); + reserve('else'); + reserve('case').reach = true; + reserve('catch'); + reserve('default').reach = true; + reserve('finally'); + reservevar('arguments', function (x) { + if (directive['use strict'] && funct['(global)']) { + warning("Strict violation.", x); + } + }); + reservevar('eval'); + reservevar('false'); + reservevar('Infinity'); + reservevar('NaN'); + reservevar('null'); + reservevar('this', function (x) { + if (directive['use strict'] && !option.validthis && ((funct['(statement)'] && + funct['(name)'].charAt(0) > 'Z') || funct['(global)'])) { + warning("Possible strict violation.", x); + } + }); + reservevar('true'); + reservevar('undefined'); + assignop('=', 'assign', 20); + assignop('+=', 'assignadd', 20); + assignop('-=', 'assignsub', 20); + assignop('*=', 'assignmult', 20); + assignop('/=', 'assigndiv', 20).nud = function () { + error("A regular expression literal can be confused with '/='."); + }; + assignop('%=', 'assignmod', 20); + bitwiseassignop('&=', 'assignbitand', 20); + bitwiseassignop('|=', 'assignbitor', 20); + bitwiseassignop('^=', 'assignbitxor', 20); + bitwiseassignop('<<=', 'assignshiftleft', 20); + bitwiseassignop('>>=', 'assignshiftright', 20); + bitwiseassignop('>>>=', 'assignshiftrightunsigned', 20); + infix('?', function (left, that) { + that.left = left; + that.right = expression(10); + advance(':'); + that['else'] = expression(10); + return that; + }, 30); + + infix('||', 'or', 40); + infix('&&', 'and', 50); + bitwise('|', 'bitor', 70); + bitwise('^', 'bitxor', 80); + bitwise('&', 'bitand', 90); + relation('==', function (left, right) { + var eqnull = option.eqnull && (left.value == 'null' || right.value == 'null'); + + if (!eqnull && option.eqeqeq) + warning("Expected '{a}' and instead saw '{b}'.", this, '===', '=='); + else if (isPoorRelation(left)) + warning("Use '{a}' to compare with '{b}'.", this, '===', left.value); + else if (isPoorRelation(right)) + warning("Use '{a}' to compare with '{b}'.", this, '===', right.value); + + return this; + }); + relation('==='); + relation('!=', function (left, right) { + var eqnull = option.eqnull && + (left.value == 'null' || right.value == 'null'); + + if (!eqnull && option.eqeqeq) { + warning("Expected '{a}' and instead saw '{b}'.", + this, '!==', '!='); + } else if (isPoorRelation(left)) { + warning("Use '{a}' to compare with '{b}'.", + this, '!==', left.value); + } else if (isPoorRelation(right)) { + warning("Use '{a}' to compare with '{b}'.", + this, '!==', right.value); + } + return this; + }); + relation('!=='); + relation('<'); + relation('>'); + relation('<='); + relation('>='); + bitwise('<<', 'shiftleft', 120); + bitwise('>>', 'shiftright', 120); + bitwise('>>>', 'shiftrightunsigned', 120); + infix('in', 'in', 120); + infix('instanceof', 'instanceof', 120); + infix('+', function (left, that) { + var right = expression(130); + if (left && right && left.id === '(string)' && right.id === '(string)') { + left.value += right.value; + left.character = right.character; + if (!option.scripturl && jx.test(left.value)) { + warning("JavaScript URL.", left); + } + return left; + } + that.left = left; + that.right = right; + return that; + }, 130); + prefix('+', 'num'); + prefix('+++', function () { + warning("Confusing pluses."); + this.right = expression(150); + this.arity = 'unary'; + return this; + }); + infix('+++', function (left) { + warning("Confusing pluses."); + this.left = left; + this.right = expression(130); + return this; + }, 130); + infix('-', 'sub', 130); + prefix('-', 'neg'); + prefix('---', function () { + warning("Confusing minuses."); + this.right = expression(150); + this.arity = 'unary'; + return this; + }); + infix('---', function (left) { + warning("Confusing minuses."); + this.left = left; + this.right = expression(130); + return this; + }, 130); + infix('*', 'mult', 140); + infix('/', 'div', 140); + infix('%', 'mod', 140); + + suffix('++', 'postinc'); + prefix('++', 'preinc'); + syntax['++'].exps = true; + + suffix('--', 'postdec'); + prefix('--', 'predec'); + syntax['--'].exps = true; + prefix('delete', function () { + var p = expression(0); + if (!p || (p.id !== '.' && p.id !== '[')) { + warning("Variables should not be deleted."); + } + this.first = p; + return this; + }).exps = true; + prefix('console', function () { + if (!option.debug) { + warning("All 'console' statements should be removed."); + } + return this; + }).exps = true; + prefix('alert', function () { + if (!option.debug) { + warning("All 'alert' statements should be removed."); + } + return this; + }).exps = true; + prefix('~', function () { + if (option.bitwise) { + warning("Unexpected '{a}'.", this, '~'); + } + expression(150); + return this; + }); + + prefix('!', function () { + this.right = expression(150); + this.arity = 'unary'; + if (bang[this.right.id] === true) { + warning("Confusing use of '{a}'.", this, '!'); + } + return this; + }); + prefix('typeof', 'typeof'); + prefix('new', function () { + var c = expression(155), i; + if (c && c.id !== 'function') { + if (c.identifier) { + c['new'] = true; + switch (c.value) { + case 'Object': + warning("Use the object literal notation {}.", token); + break; + case 'Number': + case 'String': + case 'Boolean': + case 'Math': + case 'JSON': + warning("Do not use {a} as a constructor.", token, c.value); + break; + case 'Function': + if (!option.evil) { + warning("The Function constructor is eval."); + } + break; + case 'Date': + case 'RegExp': + break; + default: + if (c.id !== 'function') { + i = c.value.substr(0, 1); + if (option.newcap && (i < 'A' || i > 'Z')) { + warning("A constructor name should start with an uppercase letter.", + token); + } + } + } + } else { + if (c.id !== '.' && c.id !== '[' && c.id !== '(') { + warning("Bad constructor.", token); + } + } + } else { + if (!option.supernew) + warning("Weird construction. Delete 'new'.", this); + } + adjacent(token, nexttoken); + if (nexttoken.id !== '(' && !option.supernew) { + warning("Missing '()' invoking a constructor."); + } + this.first = c; + return this; + }); + syntax['new'].exps = true; + + prefix('void').exps = true; + + infix('.', function (left, that) { + adjacent(prevtoken, token); + nobreak(); + var m = identifier(); + if (typeof m === 'string') { + countMember(m); + } + that.left = left; + that.right = m; + if (left && left.value === 'arguments' && (m === 'callee' || m === 'caller')) { + if (option.noarg) + warning("Avoid arguments.{a}.", left, m); + else if (directive['use strict']) + error('Strict violation.'); + } else if (!option.evil && left && left.value === 'document' && + (m === 'write' || m === 'writeln')) { + warning("document.write can be a form of eval.", left); + } + if (!option.evil && (m === 'eval' || m === 'execScript')) { + warning('eval is evil.'); + } + return that; + }, 160, true); + + infix('(', function (left, that) { + if (prevtoken.id !== '}' && prevtoken.id !== ')') { + nobreak(prevtoken, token); + } + nospace(); + if (option.immed && !left.immed && left.id === 'function') { + warning("Wrap an immediate function invocation in parentheses " + + "to assist the reader in understanding that the expression " + + "is the result of a function, and not the function itself."); + } + var n = 0, + p = []; + if (left) { + if (left.type === '(identifier)') { + if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) { + if (left.value !== 'Number' && left.value !== 'String' && + left.value !== 'Boolean' && + left.value !== 'Date') { + if (left.value === 'Math') { + warning("Math is not a function.", left); + } else if (option.newcap) { + warning( +"Missing 'new' prefix when invoking a constructor.", left); + } + } + } + } + } + if (nexttoken.id !== ')') { + for (;;) { + p[p.length] = expression(10); + n += 1; + if (nexttoken.id !== ',') { + break; + } + comma(); + } + } + advance(')'); + nospace(prevtoken, token); + if (typeof left === 'object') { + if (left.value === 'parseInt' && n === 1) { + warning("Missing radix parameter.", left); + } + if (!option.evil) { + if (left.value === 'eval' || left.value === 'Function' || + left.value === 'execScript') { + warning("eval is evil.", left); + } else if (p[0] && p[0].id === '(string)' && + (left.value === 'setTimeout' || + left.value === 'setInterval')) { + warning( + "Implied eval is evil. Pass a function instead of a string.", left); + } + } + if (!left.identifier && left.id !== '.' && left.id !== '[' && + left.id !== '(' && left.id !== '&&' && left.id !== '||' && + left.id !== '?') { + warning("Bad invocation.", left); + } + } + that.left = left; + return that; + }, 155, true).exps = true; + + prefix('(', function () { + nospace(); + if (nexttoken.id === 'function') { + nexttoken.immed = true; + } + var v = expression(0); + advance(')', this); + nospace(prevtoken, token); + if (option.immed && v.id === 'function') { + if (nexttoken.id === '(') { + warning( +"Move the invocation into the parens that contain the function.", nexttoken); + } else { + warning( +"Do not wrap function literals in parens unless they are to be immediately invoked.", + this); + } + } + return v; + }); + + infix('[', function (left, that) { + nobreak(prevtoken, token); + nospace(); + var e = expression(0), s; + if (e && e.type === '(string)') { + if (!option.evil && (e.value === 'eval' || e.value === 'execScript')) { + warning("eval is evil.", that); + } + countMember(e.value); + if (!option.sub && ix.test(e.value)) { + s = syntax[e.value]; + if (!s || !s.reserved) { + warning("['{a}'] is better written in dot notation.", + e, e.value); + } + } + } + advance(']', that); + nospace(prevtoken, token); + that.left = left; + that.right = e; + return that; + }, 160, true); + + prefix('[', function () { + var b = token.line !== nexttoken.line; + this.first = []; + if (b) { + indent += option.indent; + if (nexttoken.from === indent + option.indent) { + indent += option.indent; + } + } + while (nexttoken.id !== '(end)') { + while (nexttoken.id === ',') { + warning("Extra comma."); + advance(','); + } + if (nexttoken.id === ']') { + break; + } + if (b && token.line !== nexttoken.line) { + indentation(); + } + this.first.push(expression(10)); + if (nexttoken.id === ',') { + comma(); + if (nexttoken.id === ']' && !option.es5) { + warning("Extra comma.", token); + break; + } + } else { + break; + } + } + if (b) { + indent -= option.indent; + indentation(); + } + advance(']', this); + return this; + }, 160); + + + function property_name() { + var id = optionalidentifier(true); + if (!id) { + if (nexttoken.id === '(string)') { + id = nexttoken.value; + advance(); + } else if (nexttoken.id === '(number)') { + id = nexttoken.value.toString(); + advance(); + } + } + return id; + } + + + function functionparams() { + var i, t = nexttoken, p = []; + advance('('); + nospace(); + if (nexttoken.id === ')') { + advance(')'); + nospace(prevtoken, token); + return; + } + for (;;) { + i = identifier(true); + p.push(i); + addlabel(i, 'parameter'); + if (nexttoken.id === ',') { + comma(); + } else { + advance(')', t); + nospace(prevtoken, token); + return p; + } + } + } + + + function doFunction(i, statement) { + var f, + oldOption = option, + oldScope = scope; + + option = Object.create(option); + scope = Object.create(scope); + + funct = { + '(name)' : i || '"' + anonname + '"', + '(line)' : nexttoken.line, + '(context)' : funct, + '(breakage)' : 0, + '(loopage)' : 0, + '(scope)' : scope, + '(statement)': statement + }; + f = funct; + token.funct = funct; + functions.push(funct); + if (i) { + addlabel(i, 'function'); + } + funct['(params)'] = functionparams(); + + block(false, false, true); + scope = oldScope; + option = oldOption; + funct['(last)'] = token.line; + funct = funct['(context)']; + return f; + } + + + (function (x) { + x.nud = function () { + var b, f, i, j, p, seen = {}, t; + + b = token.line !== nexttoken.line; + if (b) { + indent += option.indent; + if (nexttoken.from === indent + option.indent) { + indent += option.indent; + } + } + for (;;) { + if (nexttoken.id === '}') { + break; + } + if (b) { + indentation(); + } + if (nexttoken.value === 'get' && peek().id !== ':') { + advance('get'); + if (!option.es5) { + error("get/set are ES5 features."); + } + i = property_name(); + if (!i) { + error("Missing property name."); + } + t = nexttoken; + adjacent(token, nexttoken); + f = doFunction(); + if (!option.loopfunc && funct['(loopage)']) { + warning("Don't make functions within a loop.", t); + } + p = f['(params)']; + if (p) { + warning("Unexpected parameter '{a}' in get {b} function.", t, p[0], i); + } + adjacent(token, nexttoken); + advance(','); + indentation(); + advance('set'); + j = property_name(); + if (i !== j) { + error("Expected {a} and instead saw {b}.", token, i, j); + } + t = nexttoken; + adjacent(token, nexttoken); + f = doFunction(); + p = f['(params)']; + if (!p || p.length !== 1 || p[0] !== 'value') { + warning("Expected (value) in set {a} function.", t, i); + } + } else { + i = property_name(); + if (typeof i !== 'string') { + break; + } + advance(':'); + nonadjacent(token, nexttoken); + expression(10); + } + if (seen[i] === true) { + warning("Duplicate member '{a}'.", nexttoken, i); + } + seen[i] = true; + countMember(i); + if (nexttoken.id === ',') { + comma(); + if (nexttoken.id === ',') { + warning("Extra comma.", token); + } else if (nexttoken.id === '}' && !option.es5) { + warning("Extra comma.", token); + } + } else { + break; + } + } + if (b) { + indent -= option.indent; + indentation(); + } + advance('}', this); + return this; + }; + x.fud = function () { + error("Expected to see a statement and instead saw a block.", token); + }; + }(delim('{'))); + +// This Function is called when esnext option is set to true +// it adds the `const` statement to JSHINT + + useESNextSyntax = function () { + var conststatement = stmt('const', function (prefix) { + var id, name, value; + + this.first = []; + for (;;) { + nonadjacent(token, nexttoken); + id = identifier(); + if (funct[id] === "const") { + warning("const '" + id + "' has already been declared"); + } + if (funct['(global)'] && predefined[id] === false) { + warning("Redefinition of '{a}'.", token, id); + } + addlabel(id, 'const'); + if (prefix) { + break; + } + name = token; + this.first.push(token); + + if (nexttoken.id !== "=") { + warning("const " + + "'{a}' is initialized to 'undefined'.", token, id); + } + + if (nexttoken.id === '=') { + nonadjacent(token, nexttoken); + advance('='); + nonadjacent(token, nexttoken); + if (nexttoken.id === 'undefined') { + warning("It is not necessary to initialize " + + "'{a}' to 'undefined'.", token, id); + } + if (peek(0).id === '=' && nexttoken.identifier) { + error("Constant {a} was not declared correctly.", + nexttoken, nexttoken.value); + } + value = expression(0); + name.first = value; + } + + if (nexttoken.id !== ',') { + break; + } + comma(); + } + return this; + }); + conststatement.exps = true; + }; + + var varstatement = stmt('var', function (prefix) { + // JavaScript does not have block scope. It only has function scope. So, + // declaring a variable in a block can have unexpected consequences. + var id, name, value; + + if (funct['(onevar)'] && option.onevar) { + warning("Too many var statements."); + } else if (!funct['(global)']) { + funct['(onevar)'] = true; + } + this.first = []; + for (;;) { + nonadjacent(token, nexttoken); + id = identifier(); + if (option.esnext && funct[id] === "const") { + warning("const '" + id + "' has already been declared"); + } + if (funct['(global)'] && predefined[id] === false) { + warning("Redefinition of '{a}'.", token, id); + } + addlabel(id, 'unused'); + if (prefix) { + break; + } + name = token; + this.first.push(token); + if (nexttoken.id === '=') { + nonadjacent(token, nexttoken); + advance('='); + nonadjacent(token, nexttoken); + if (nexttoken.id === 'undefined') { + warning("It is not necessary to initialize '{a}' to 'undefined'.", token, id); + } + if (peek(0).id === '=' && nexttoken.identifier) { + error("Variable {a} was not declared correctly.", + nexttoken, nexttoken.value); + } + value = expression(0); + name.first = value; + } + if (nexttoken.id !== ',') { + break; + } + comma(); + } + return this; + }); + varstatement.exps = true; + + blockstmt('function', function () { + if (inblock) { + warning("Function declarations should not be placed in blocks. " + + "Use a function expression or move the statement to the top of " + + "the outer function.", token); + + } + var i = identifier(); + if (option.esnext && funct[i] === "const") { + warning("const '" + i + "' has already been declared"); + } + adjacent(token, nexttoken); + addlabel(i, 'unction'); + doFunction(i, true); + if (nexttoken.id === '(' && nexttoken.line === token.line) { + error( +"Function declarations are not invocable. Wrap the whole function invocation in parens."); + } + return this; + }); + + prefix('function', function () { + var i = optionalidentifier(); + if (i) { + adjacent(token, nexttoken); + } else { + nonadjacent(token, nexttoken); + } + doFunction(i); + if (!option.loopfunc && funct['(loopage)']) { + warning("Don't make functions within a loop."); + } + return this; + }); + + blockstmt('if', function () { + var t = nexttoken; + advance('('); + nonadjacent(this, t); + nospace(); + expression(20); + if (nexttoken.id === '=') { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance('='); + expression(20); + } + advance(')', t); + nospace(prevtoken, token); + block(true, true); + if (nexttoken.id === 'else') { + nonadjacent(token, nexttoken); + advance('else'); + if (nexttoken.id === 'if' || nexttoken.id === 'switch') { + statement(true); + } else { + block(true, true); + } + } + return this; + }); + + blockstmt('try', function () { + var b, e, s; + + block(false); + if (nexttoken.id === 'catch') { + advance('catch'); + nonadjacent(token, nexttoken); + advance('('); + s = scope; + scope = Object.create(s); + e = nexttoken.value; + if (nexttoken.type !== '(identifier)') { + warning("Expected an identifier and instead saw '{a}'.", + nexttoken, e); + } else { + addlabel(e, 'exception'); + } + advance(); + advance(')'); + block(false); + b = true; + scope = s; + } + if (nexttoken.id === 'finally') { + advance('finally'); + block(false); + return; + } else if (!b) { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, 'catch', nexttoken.value); + } + return this; + }); + + blockstmt('while', function () { + var t = nexttoken; + funct['(breakage)'] += 1; + funct['(loopage)'] += 1; + advance('('); + nonadjacent(this, t); + nospace(); + expression(20); + if (nexttoken.id === '=') { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance('='); + expression(20); + } + advance(')', t); + nospace(prevtoken, token); + block(true, true); + funct['(breakage)'] -= 1; + funct['(loopage)'] -= 1; + return this; + }).labelled = true; + + reserve('with'); + + blockstmt('switch', function () { + var t = nexttoken, + g = false; + funct['(breakage)'] += 1; + advance('('); + nonadjacent(this, t); + nospace(); + this.condition = expression(20); + advance(')', t); + nospace(prevtoken, token); + nonadjacent(token, nexttoken); + t = nexttoken; + advance('{'); + nonadjacent(token, nexttoken); + indent += option.indent; + this.cases = []; + for (;;) { + switch (nexttoken.id) { + case 'case': + switch (funct['(verb)']) { + case 'break': + case 'case': + case 'continue': + case 'return': + case 'switch': + case 'throw': + break; + default: + // You can tell JSHint that you don't use break intentionally by + // adding a comment /* falls through */ on a line just before + // the next `case`. + if (!ft.test(lines[nexttoken.line - 2])) { + warning( + "Expected a 'break' statement before 'case'.", + token); + } + } + indentation(-option.indent); + advance('case'); + this.cases.push(expression(20)); + g = true; + advance(':'); + funct['(verb)'] = 'case'; + break; + case 'default': + switch (funct['(verb)']) { + case 'break': + case 'continue': + case 'return': + case 'throw': + break; + default: + if (!ft.test(lines[nexttoken.line - 2])) { + warning( + "Expected a 'break' statement before 'default'.", + token); + } + } + indentation(-option.indent); + advance('default'); + g = true; + advance(':'); + break; + case '}': + indent -= option.indent; + indentation(); + advance('}', t); + if (this.cases.length === 1 || this.condition.id === 'true' || + this.condition.id === 'false') { + if (!option.onecase) + warning("This 'switch' should be an 'if'.", this); + } + funct['(breakage)'] -= 1; + funct['(verb)'] = undefined; + return; + case '(end)': + error("Missing '{a}'.", nexttoken, '}'); + return; + default: + if (g) { + switch (token.id) { + case ',': + error("Each value should have its own case label."); + return; + case ':': + g = false; + statements(); + break; + default: + error("Missing ':' on a case clause.", token); + return; + } + } else { + if (token.id === ':') { + advance(':'); + error("Unexpected '{a}'.", token, ':'); + statements(); + } else { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, 'case', nexttoken.value); + return; + } + } + } + } + }).labelled = true; + + stmt('debugger', function () { + if (!option.debug) { + warning("All 'debugger' statements should be removed."); + } + return this; + }).exps = true; +// stmt('alert', function () { +// if (!option.debug) { +// warning("All 'alert' statements should be removed."); +// } +// return this; +// }).exps = true; +// stmt('console', function () { +// if (!option.debug) { +// warning("All 'console' statements should be removed."); +// } +// return this; +// }).exps = true; + + (function () { + var x = stmt('do', function () { + funct['(breakage)'] += 1; + funct['(loopage)'] += 1; + this.first = block(true); + advance('while'); + var t = nexttoken; + nonadjacent(token, t); + advance('('); + nospace(); + expression(20); + if (nexttoken.id === '=') { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance('='); + expression(20); + } + advance(')', t); + nospace(prevtoken, token); + funct['(breakage)'] -= 1; + funct['(loopage)'] -= 1; + return this; + }); + x.labelled = true; + x.exps = true; + }()); + + blockstmt('for', function () { + var s, t = nexttoken; + funct['(breakage)'] += 1; + funct['(loopage)'] += 1; + advance('('); + nonadjacent(this, t); + nospace(); + if (peek(nexttoken.id === 'var' ? 1 : 0).id === 'in') { + if (nexttoken.id === 'var') { + advance('var'); + varstatement.fud.call(varstatement, true); + } else { + switch (funct[nexttoken.value]) { + case 'unused': + funct[nexttoken.value] = 'var'; + break; + case 'var': + break; + default: + warning("Bad for in variable '{a}'.", + nexttoken, nexttoken.value); + } + advance(); + } + advance('in'); + expression(20); + advance(')', t); + s = block(true, true); + if (option.forin && (s.length > 1 || typeof s[0] !== 'object' || + s[0].value !== 'if')) { + warning("The body of a for in should be wrapped in an if statement to filter " + + "unwanted properties from the prototype.", this); + } + funct['(breakage)'] -= 1; + funct['(loopage)'] -= 1; + return this; + } else { + if (nexttoken.id !== ';') { + if (nexttoken.id === 'var') { + advance('var'); + varstatement.fud.call(varstatement); + } else { + for (;;) { + expression(0, 'for'); + if (nexttoken.id !== ',') { + break; + } + comma(); + } + } + } + nolinebreak(token); + advance(';'); + if (nexttoken.id !== ';') { + expression(20); + if (nexttoken.id === '=') { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance('='); + expression(20); + } + } + nolinebreak(token); + advance(';'); + if (nexttoken.id === ';') { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, ')', ';'); + } + if (nexttoken.id !== ')') { + for (;;) { + expression(0, 'for'); + if (nexttoken.id !== ',') { + break; + } + comma(); + } + } + advance(')', t); + nospace(prevtoken, token); + block(true, true); + funct['(breakage)'] -= 1; + funct['(loopage)'] -= 1; + return this; + } + }).labelled = true; + + + stmt('break', function () { + var v = nexttoken.value; + + if (funct['(breakage)'] === 0) + warning("Unexpected '{a}'.", nexttoken, this.value); + + if (!option.asi) + nolinebreak(this); + + if (nexttoken.id !== ';') { + if (token.line === nexttoken.line) { + if (funct[v] !== 'label') { + warning("'{a}' is not a statement label.", nexttoken, v); + } else if (scope[v] !== funct) { + warning("'{a}' is out of scope.", nexttoken, v); + } + this.first = nexttoken; + advance(); + } + } + reachable('break'); + return this; + }).exps = true; + + + stmt('continue', function () { + var v = nexttoken.value; + + if (funct['(breakage)'] === 0) + warning("Unexpected '{a}'.", nexttoken, this.value); + + if (!option.asi) + nolinebreak(this); + + if (nexttoken.id !== ';') { + if (token.line === nexttoken.line) { + if (funct[v] !== 'label') { + warning("'{a}' is not a statement label.", nexttoken, v); + } else if (scope[v] !== funct) { + warning("'{a}' is out of scope.", nexttoken, v); + } + this.first = nexttoken; + advance(); + } + } else if (!funct['(loopage)']) { + warning("Unexpected '{a}'.", nexttoken, this.value); + } + reachable('continue'); + return this; + }).exps = true; + + + stmt('return', function () { + if (this.line === nexttoken.line) { + if (nexttoken.id === '(regexp)') + warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator."); + + if (nexttoken.id !== ';' && !nexttoken.reach) { + nonadjacent(token, nexttoken); + this.first = expression(0); + } + } else if (!option.asi) { + nolinebreak(this); // always warn (Line breaking error) + } + reachable('return'); + return this; + }).exps = true; + + + stmt('throw', function () { + nolinebreak(this); + nonadjacent(token, nexttoken); + this.first = expression(20); + reachable('throw'); + return this; + }).exps = true; + +// Superfluous reserved words + + reserve('class'); + reserve('const'); + reserve('enum'); + reserve('export'); + reserve('extends'); + reserve('import'); + reserve('super'); + + reserve('let'); + reserve('yield'); + reserve('implements'); + reserve('interface'); + reserve('package'); + reserve('private'); + reserve('protected'); + reserve('public'); + reserve('static'); + + +// Parse JSON + + function jsonValue() { + + function jsonObject() { + var o = {}, t = nexttoken; + advance('{'); + if (nexttoken.id !== '}') { + for (;;) { + if (nexttoken.id === '(end)') { + error("Missing '}' to match '{' from line {a}.", + nexttoken, t.line); + } else if (nexttoken.id === '}') { + warning("Unexpected comma.", token); + break; + } else if (nexttoken.id === ',') { + error("Unexpected comma.", nexttoken); + } else if (nexttoken.id !== '(string)') { + warning("Expected a string and instead saw {a}.", + nexttoken, nexttoken.value); + } + if (o[nexttoken.value] === true) { + warning("Duplicate key '{a}'.", + nexttoken, nexttoken.value); + } else if ((nexttoken.value === '__proto__' && + !option.proto) || (nexttoken.value === '__iterator__' && + !option.iterator)) { + warning("The '{a}' key may produce unexpected results.", + nexttoken, nexttoken.value); + } else { + o[nexttoken.value] = true; + } + advance(); + advance(':'); + jsonValue(); + if (nexttoken.id !== ',') { + break; + } + advance(','); + } + } + advance('}'); + } + + function jsonArray() { + var t = nexttoken; + advance('['); + if (nexttoken.id !== ']') { + for (;;) { + if (nexttoken.id === '(end)') { + error("Missing ']' to match '[' from line {a}.", + nexttoken, t.line); + } else if (nexttoken.id === ']') { + warning("Unexpected comma.", token); + break; + } else if (nexttoken.id === ',') { + error("Unexpected comma.", nexttoken); + } + jsonValue(); + if (nexttoken.id !== ',') { + break; + } + advance(','); + } + } + advance(']'); + } + + switch (nexttoken.id) { + case '{': + jsonObject(); + break; + case '[': + jsonArray(); + break; + case 'true': + case 'false': + case 'null': + case '(number)': + case '(string)': + advance(); + break; + case '-': + advance('-'); + if (token.character !== nexttoken.from) { + warning("Unexpected space after '-'.", token); + } + adjacent(token, nexttoken); + advance('(number)'); + break; + default: + error("Expected a JSON value.", nexttoken); + } + } + + +// The actual JSHINT function itself. + + var itself = function (s, o, g) { + var a, i, k; + JSHINT.errors = []; + predefined = Object.create(standard); + combine(predefined, g || {}); + if (o) { + a = o.predef; + if (a) { + if (Array.isArray(a)) { + for (i = 0; i < a.length; i += 1) { + predefined[a[i]] = true; + } + } else if (typeof a === 'object') { + k = Object.keys(a); + for (i = 0; i < k.length; i += 1) { + predefined[k[i]] = !!a[k[i]]; + } + } + } + option = o; + } else { + option = {}; + } + option.indent = option.indent || 4; + option.maxerr = option.maxerr || 5000000; + + tab = ''; + for (i = 0; i < option.indent; i += 1) { + tab += ' '; + } + indent = 1; + global = Object.create(predefined); + scope = global; + funct = { + '(global)': true, + '(name)': '(global)', + '(scope)': scope, + '(breakage)': 0, + '(loopage)': 0 + }; + functions = [funct]; + urls = []; + src = false; + stack = null; + member = {}; + membersOnly = null; + implied = {}; + inblock = false; + lookahead = []; + jsonmode = false; + warnings = 0; + lex.init(s); + prereg = true; + directive = {}; + + prevtoken = token = nexttoken = syntax['(begin)']; + assume(); + + // combine the passed globals after we've assumed all our options + combine(predefined, g || {}); + + try { + advance(); + switch (nexttoken.id) { + case '{': + case '[': + option.laxbreak = true; + jsonmode = true; + jsonValue(); + break; + default: + directives(); + if (directive["use strict"] && !option.globalstrict) { + warning("Use the function form of \"use strict\".", prevtoken); + } + + statements(); + } + advance('(end)'); + } catch (e) { + if (e) { + JSHINT.errors.push({ + reason : e.message, + line : e.line || nexttoken.line, + character : e.character || nexttoken.from + }, null); + } + } + return JSHINT.errors.length === 0; + }; + + // Data summary. + itself.data = function () { + + var data = { functions: [], options: option }, fu, globals, implieds = [], f, i, j, + members = [], n, unused = [], v; + if (itself.errors.length) { + data.errors = itself.errors; + } + + if (jsonmode) { + data.json = true; + } + + for (n in implied) { + if (is_own(implied, n)) { + implieds.push({ + name: n, + line: implied[n] + }); + } + } + if (implieds.length > 0) { + data.implieds = implieds; + } + + if (urls.length > 0) { + data.urls = urls; + } + + globals = Object.keys(scope); + if (globals.length > 0) { + data.globals = globals; + } + + for (i = 1; i < functions.length; i += 1) { + f = functions[i]; + fu = {}; + for (j = 0; j < functionicity.length; j += 1) { + fu[functionicity[j]] = []; + } + for (n in f) { + if (is_own(f, n) && n.charAt(0) !== '(') { + v = f[n]; + if (v === 'unction') { + v = 'unused'; + } + if (Array.isArray(fu[v])) { + fu[v].push(n); + if (v === 'unused') { + unused.push({ + name: n, + line: f['(line)'], + 'function': f['(name)'] + }); + } + } + } + } + for (j = 0; j < functionicity.length; j += 1) { + if (fu[functionicity[j]].length === 0) { + delete fu[functionicity[j]]; + } + } + fu.name = f['(name)']; + fu.param = f['(params)']; + fu.line = f['(line)']; + fu.last = f['(last)']; + data.functions.push(fu); + } + + if (unused.length > 0) { + data.unused = unused; + } + + members = []; + for (n in member) { + if (typeof member[n] === 'number') { + data.member = member; + break; + } + } + + return data; + }; + + itself.report = function (option) { + var data = itself.data(); + + var a = [], c, e, err, f, i, k, l, m = '', n, o = [], s; + + function detail(h, array) { + var b, i, singularity; + if (array) { + o.push('
        ' + h + ' '); + array = array.sort(); + for (i = 0; i < array.length; i += 1) { + if (array[i] !== singularity) { + singularity = array[i]; + o.push((b ? ', ' : '') + singularity); + b = true; + } + } + o.push('
        '); + } + } + + + if (data.errors || data.implieds || data.unused) { + err = true; + o.push('
        Error:'); + if (data.errors) { + for (i = 0; i < data.errors.length; i += 1) { + c = data.errors[i]; + if (c) { + e = c.evidence || ''; + o.push('

        Problem' + (isFinite(c.line) ? ' at line ' + + c.line + ' character ' + c.character : '') + + ': ' + c.reason.entityify() + + '

        ' + + (e && (e.length > 80 ? e.slice(0, 77) + '...' : + e).entityify()) + '

        '); + } + } + } + + if (data.implieds) { + s = []; + for (i = 0; i < data.implieds.length; i += 1) { + s[i] = '' + data.implieds[i].name + ' ' + + data.implieds[i].line + ''; + } + o.push('

        Implied global: ' + s.join(', ') + '

        '); + } + + if (data.unused) { + s = []; + for (i = 0; i < data.unused.length; i += 1) { + s[i] = '' + data.unused[i].name + ' ' + + data.unused[i].line + ' ' + + data.unused[i]['function'] + ''; + } + o.push('

        Unused variable: ' + s.join(', ') + '

        '); + } + if (data.json) { + o.push('

        JSON: bad.

        '); + } + o.push('
        '); + } + + if (!option) { + + o.push('
        '); + + if (data.urls) { + detail("URLs
        ", data.urls, '
        '); + } + + if (data.json && !err) { + o.push('

        JSON: good.

        '); + } else if (data.globals) { + o.push('
        Global ' + + data.globals.sort().join(', ') + '
        '); + } else { + o.push('
        No new global variables introduced.
        '); + } + + for (i = 0; i < data.functions.length; i += 1) { + f = data.functions[i]; + + o.push('
        ' + f.line + '-' + + f.last + ' ' + (f.name || '') + '(' + + (f.param ? f.param.join(', ') : '') + ')
        '); + detail('Unused', f.unused); + detail('Closure', f.closure); + detail('Variable', f['var']); + detail('Exception', f.exception); + detail('Outer', f.outer); + detail('Global', f.global); + detail('Label', f.label); + } + + if (data.member) { + a = Object.keys(data.member); + if (a.length) { + a = a.sort(); + m = '
        /*members ';
        +                    l = 10;
        +                    for (i = 0; i < a.length; i += 1) {
        +                        k = a[i];
        +                        n = k.name();
        +                        if (l + n.length > 72) {
        +                            o.push(m + '
        '); + m = ' '; + l = 1; + } + l += n.length + 2; + if (data.member[k] === 1) { + n = '' + n + ''; + } + if (i < a.length - 1) { + n += ', '; + } + m += n; + } + o.push(m + '
        */
        '); + } + o.push('
        '); + } + } + return o.join(''); + }; + + itself.jshint = itself; + itself.edition = '2011-04-16'; + + return itself; +}()); + +// Make JSHINT a Node module, if possible. +if (typeof exports == 'object' && exports) + exports.JSHINT = JSHINT; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/version b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/version new file mode 100644 index 000000000..93b9d970b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/version @@ -0,0 +1,22 @@ +#beta version +version:1.2.0.1 + +[changelog] +1.ָļѾܾ飬ԷԴļǵ +2.ֵ֧ݹĿ¼ڵļ +3.ּ֧htmlļеjs루ȡͬһʱѭһbug +5.޸isHiddenжϼĿ¼..ʱbug +6.޸·bug +7.˱Ҫdebug +8.޸Ŀ¼ṹconfĿ¼core/data/Ŀ¼ +9.˷ɨĹ +10.htmlļʽ⣨֮ǰĴļ<>Ҫת壬룩 +11.ɨ +12.˺ִ󼶱error,warning,ignoreignore +13.еĺ֣ά +14.warningerrorĸͰٷֱ +15.޸˴ļбΪδ +16.[1.2.0]ļ˹ +17.[1.2.0]ûԶù +18.[1.2.0.1]ȥ˻鲽 diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jslint4java-2.0.2.jar b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jslint4java-2.0.2.jar new file mode 100644 index 000000000..710551645 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jslint4java-2.0.2.jar differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jslint4java-ant-1.4.2.jar b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jslint4java-ant-1.4.2.jar new file mode 100644 index 000000000..5f6bd7ec9 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/jslint4java-ant-1.4.2.jar differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/npPlugintest.dll b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/npPlugintest.dll new file mode 100644 index 000000000..07df0b3ec Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/_test/tools/lib/npPlugintest.dll differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/autotypesetbutton.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/autotypesetbutton.js new file mode 100644 index 000000000..74dbb5735 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/autotypesetbutton.js @@ -0,0 +1,53 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-4-12 + * Time: 下午4:44 + * To change this template use File | Settings | File Templates. + */ +module( 'ui.autotypeset' ); +test( 'AutoTypeSetButton/AutoTypeSetPicker', function() { + //打开一个自动排版的对话框 + var editor = new baidu.editor.ui.Editor(); + editor.render("editor"); + editor.ready(function(){ + var autotypesetButton = new te.obj[0].AutoTypeSetButton({editor:editor}); + te.dom[0].innerHTML = autotypesetButton.renderHtml(); + autotypesetButton.postRender(); + autotypesetButton.showPopup(); + equal(autotypesetButton.popup._hidden,false,'窗口显示'); +// 检查每个input的选中情况是否和editor.options里设置的一样 + + var AutoPickerBodyInput = document.getElementsByClassName("edui-autotypesetpicker-body")[0].getElementsByTagName('input'); + for(var i=0;ixx

        xxx

        " ); + var doc = editor.document, + range = new baidu.editor.dom.Range( doc ), + p = doc.getElementsByTagName( 'p' )[1]; + range.setStart( p, 0 ).setEnd( p, 1 ).select(); + var r = editor.selection.getRange(); + var dom = $( '#'+document.getElementsByClassName("edui-for-insertimage")[0].id+'_body' )[0]; + ua.click( dom ); + setTimeout(function(){ + var dialog = editor.ui._dialogs['insertimageDialog']; + ok(dialog.title===editor.getLang("labelMap.insertimage"),"dialog的标题是否一致"); + ok(dialog.closeDialog === editor.getLang("closeDialog"),"关闭dialog的title是否一致"); + ok(dialog.buttons[0].label === editor.getLang("ok") && dialog.buttons[1].label === editor.getLang("cancel"),"确认取消按钮是否一致"); + setTimeout( function () { + var dialogDoc = document.getElementById(dialog.id + "_iframe").contentWindow.document; + var ids = editor.getLang("insertimage.static"); + for(var i in ids){ + if(i==="imgSearchTxt"){ + equal(dialogDoc.getElementById(i).value,ids[i].value,"图片搜索文字是否一致") + } + if(i==="imgSearchBtn"){ + equal(dialogDoc.getElementById(i).value,ids[i].value,"图片搜索按钮文字是否一致") + } + } + ua.click(document.getElementById(dialog.closeButton.id+"_body")); + var newRange = editor.selection.getRange(); + ok( r.startContainer === newRange.startContainer, "dialog开闭前后选区是否一致" ); + start(); + }, 1500 ) + },100); + + } ) +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/colorbutton.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/colorbutton.js new file mode 100644 index 000000000..27d9bee91 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/colorbutton.js @@ -0,0 +1,79 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-4-12 + * Time: 下午4:47 + * To change this template use File | Settings | File Templates. + */ +module( 'ui.colorbutton' ); +test( 'colorpicker的功能', function () { + var testButton = document.body.appendChild( document.createElement( 'div' ) ); + var editor = new te.obj[0].Editor(); + editor.render("editor"); + editor.ready(function(){ + var colorButton = new te.obj[0].ColorButton({editor:editor}); + testButton.innerHTML = colorButton.renderHtml(); + colorButton.postRender(); + //_onTableClick + colorButton.showPopup(); + var pick = document.getElementById(colorButton.popup.content.id).getElementsByTagName( 'table' )[0].firstChild.childNodes[2].childNodes[1].firstChild; + equal( document.getElementById(colorButton.id+'_colorlump').style.backgroundColor, '', 'edui-colorlump 默认颜色' ); + ua.click( pick ); + var bgcolor = $('#'+colorButton.id+'_colorlump').css( 'backgroundColor' ); + ok( bgcolor == 'rgb(127,127,127)' || bgcolor == '#7f7f7f'||bgcolor== 'rgb(127, 127, 127)' , '检查_onTableClick选择的颜色edui-colorlump' ); + equal( $('#'+colorButton.id+'_colorlump').length, 1, '检查edui-colorlump个数' ); + equal( colorButton.popup._hidden, true, '点击按钮后,关闭窗口' ); +//_onTableOver&_onTableClick + pick = document.getElementById(colorButton.popup.content.id).getElementsByTagName( 'table' )[0].firstChild.childNodes[2].childNodes[2].firstChild; + equal( document.getElementById(colorButton.popup.content.id+'_preview').style.backgroundColor, '', 'edui-colorpicker-preview 默认颜色' ); + ua.mouseover( pick ); +//colorButton.popup.content.id + bgcolor = $( '#'+colorButton.popup.content.id+'_preview' ).css( 'backgroundColor' ); + ok( bgcolor == 'rgb(221, 217, 195)' || bgcolor == '#ddd9c3'||bgcolor=='rgb(221,217,195)', '检查_onTableClick选择的颜色edui-colorlump' ); + equal($('#'+colorButton.popup.content.id+'_preview' ).length, 1, '检查edui-colorlump个数' ); + equal( colorButton.popup._hidden, true, '点击按钮后,关闭窗口' ); + ua.click( pick ); + bgcolor = $('#'+colorButton.id+'_colorlump').css( 'backgroundColor' ); + ok( bgcolor == 'rgb(221, 217, 195)' || bgcolor == '#ddd9c3'||bgcolor == 'rgb(221,217,195)' , '再次选择颜色' ); + ua.mouseout( pick ); + equal( document.getElementById(colorButton.popup.content.id+'_preview').style.backgroundColor, '', '鼠标移开,edui-colorpicker-preview 恢复默认颜色' ); + //_onPickNoColor + colorButton.showPopup(); + pick = document.getElementsByClassName( 'edui-colorpicker-nocolor' )[0]; + ua.click( pick ); + equal( colorButton.popup._hidden, true, '点击PickNoColor按钮后,关闭窗口' ); +// editor.destroy(); + var ed = document.getElementById('editor'); + ed.parentNode.removeChild(ed); + start(); + }); + stop(); +} ); + +test( 'colorbutton', function () { + //检查colorButton的属性 + var editor = new baidu.editor.ui.Editor(); + stop(); + setTimeout(function(){ + var colorButton = new te.obj[0].ColorButton({editor:editor}); + equal( colorButton.popup.content.noColorText, editor.getLang("clearColor"), '检查colorButton的文本 ' ); + start(); + },50); +} ); + +test( 'colorpicker', function () { + //检查colorPicker的属性 + var editor = new baidu.editor.ui.Editor(); + stop(); + setTimeout(function(){ + var colorPicker = new te.obj[0].ColorPicker({editor:editor}); + equal( colorPicker.noColorText, editor.getLang("clearColor")); + //检查colorPicker生成的html代码的内容 + colorPicker.render(te.dom[0]); + var testPicker = te.dom[0]; + equal( testPicker.getElementsByTagName( 'table' )[0].className, 'edui-box edui-'+editor.options.theme,'' ); + start(); + },50); +} ); + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/combox.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/combox.js new file mode 100644 index 000000000..728f637de --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/combox.js @@ -0,0 +1,73 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-4-12 + * Time: 下午4:44 + * To change this template use File | Settings | File Templates. + */ +module( 'ui.combox' ); +test( 'combox', function() { + var editor = new baidu.editor.ui.Editor(); + editor.render("editor"); +//设置菜单内容 + var list = [ + ['1',[1]], + ['0',[0]], + ['宋体',['宋体', 'SimSun']], + ['楷体',['楷体', '楷体_GB2312', 'SimKai']], + ['黑体',['黑体', 'SimHei']], + ['隶书',['隶书', 'SimLi']], + ['andale mono',['andale mono']], + ['arial',['arial', 'helvetica', 'sans-serif']], + ['arial black',['arial black', 'avant garde']], + ['comic sans ms',['comic sans ms']], + ['impact',['impact', 'chicago']], + ['times new roman',['times new roman']] + ]; + var title = list ; + + for(var i=0,ci,items=[];ci=list[i++];){ + + (function(key,val){ + items.push({ + label: key, + value: val, + renderLabelHtml: function (){ + return '
        ' + (this.label || '') + '
        '; + } + }); + })(ci[0],ci[1]) + } + editor.ready(function(){ + var combox = new te.obj[0].Combox({editor:editor,items :items,title: title, initValue:'字体',className: 'edui-for-fontfamily'}); + + te.dom[0].innerHTML = combox.renderHtml(); + combox.postRender(); + combox.showPopup(); + //////// getItem + equal(combox.getItem(0).label,'1','检查item内容'); + equal(combox.getItem(0).value[0],1,''); +///////getValue setValue + combox.setValue(list[4][1]); + equal(combox.getValue(),list[4][1],'设置内容'); + equal(combox.label,'黑体',''); + equal(combox.getDom('button_body').innerHTML,"黑体",''); + ////////getLabelForUnknowValue + combox.setValue(['黑体', 'chicago']); + equal(combox.getValue()[0],"黑体",'设置一个不在原来列表的内容'); + equal(combox.getValue()[1],'chicago',''); + equal(combox.getValue(),combox.label,''); + equal(combox.getDom('button_body').innerHTML,"黑体,chicago",''); + /////selectByIndex + combox.popup.items[2].onclick(); + equal(combox.getValue()[0],'宋体','检查onclick,设定选中内容'); + equal(combox.getValue()[1],'SimSun',''); + equal(items[2].label,combox.label,''); + equal(combox.selectedIndex,2,''); + combox.popup.hide(); + start(); + + }); +stop(); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/css/DEFAULT.css b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/css/DEFAULT.css new file mode 100644 index 000000000..ba689b4dc --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/css/DEFAULT.css @@ -0,0 +1,12 @@ +/* common layer */ +.cssloaded { + width: 20px; +} +/* for IE6 fixed */ +body { + background: url('about:blank') fixed; +} + +.edui-editor { + width: 843px; +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/editor.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/editor.js new file mode 100644 index 000000000..648e2c080 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/editor.js @@ -0,0 +1,188 @@ + +module( 'ui.editor' ); +//test('图片浮层',function(){ +// var ue1 = new baidu.editor.ui.Editor({theme:'default'}); +// var div = document.createElement("div"); +// document.body.appendChild(div); +// ue1.render(div); +// stop(); +// ue1.ready(function(){ +// editor.execCommand( 'insertimage', {src:'http://img.baidu.com/hi/jx2/j_0001.gif', width:50, height:51} ); +// }); +//}); + +test('拖拽', function(){ + var sc = document.createElement("script"); + sc.id="sc"; + sc.type = "text/plain"; + document.body.appendChild(sc); + var ue = new UE.ui.Editor({'autoHeightEnabled':false,'autoFloatEnabled':false,'scaleEnabled':true}); + ue.render('sc'); + stop(); + ue.ready(function(){ + var me =this; + var offset = 100; + setTimeout(function(){ + //保存现有的编辑器宽,高 + var editorWidth = $(this.document.getElementById(me.ui.id)).css('width'); + var editorHeight = $(this.document.getElementById(me.ui.id)).css('height'); + //取得拖拽的元素 + var scaleDiv = this.document.getElementById(me.ui.id+'_scale'); + + //从拖拽元素的右下角开始,拖拽到向下,向右20px + var mouseX = $(scaleDiv).offset().left + parseInt($(scaleDiv).css('width'));//+editorBorderHeight; + var mouseY = $(scaleDiv).offset().top + parseInt($(scaleDiv).css('height'));//+editorBorderWidth; + ua.dragto(scaleDiv,{startX:mouseX,startY:mouseY,endX:mouseX+offset,endY:mouseY+offset}); + setTimeout(function(){ + //取编辑器的边框 + var editorBorderWidth = parseInt($(this.document.getElementById(me.ui.id)).css('border-left-width'))+parseInt($(this.document.getElementById(me.ui.id)).css('border-right-width')); + var editorBorderHeight = parseInt($(this.document.getElementById(me.ui.id)).css('border-top-width'))+parseInt($(this.document.getElementById(me.ui.id)).css('border-bottom-width')); + var border = me.options.theme=='default'?1:0; + var bd = parseInt(editorHeight) + offset - 2 -editorBorderWidth + border; + var height = parseInt($(this.document.getElementById(me.ui.id)).css('height')); + equal(parseInt($(this.document.getElementById(me.ui.id)).css('width')),parseInt(editorWidth) + offset - 2 -editorBorderHeight + border,'宽'); + ok(height==bd||height==bd-1,'高'+height); + setTimeout(function () { + UE.delEditor('sc'); + sc = document.getElementById('sc'); + sc && sc.parentNode.removeChild(sc); + start(); + }, 100); + },1800); + },100); + }); +}); + +test('编辑器皮肤',function(){ + if(ua.browser.ie<8 && ua.browser.ie>0) return 0; + var ue1 = new baidu.editor.ui.Editor({theme:'default'}); + var sc1 = document.createElement("script"); + sc1.id="sc1"; + document.body.appendChild(sc1); + ue1.render(sc1); + stop(); + ue1.ready(function(){ + var id = document.getElementById('sc1').firstChild.id; + equal(document.getElementById('sc1').firstChild.className,'edui-editor edui-default','第一个editor的classname'); + equal(document.getElementById(id+'_toolbarbox').className,'edui-editor-toolbarbox edui-default','第一个editor toolbar的classname'); + equal(document.getElementById(id+'_iframeholder').className,'edui-editor-iframeholder edui-default','第一个editor iframeholder的classname'); + equal(document.getElementById(id+'_bottombar').className,'edui-editor-bottomContainer edui-default','第一个editor bottombar的classname'); + equal(document.getElementById(id+'_scalelayer').className,'edui-default','第一个editor scalelayer的classname'); + sc1 = document.getElementById('sc1'); + sc1.parentNode.removeChild(sc1); + var ue2 = new baidu.editor.ui.Editor({theme:'modern'}); + var sc2 = document.createElement("script"); + sc2.id="sc2"; + document.body.appendChild(sc2); + ue2.render('sc2'); + ue2.ready(function(){ + id = document.getElementById('sc2').firstChild.id; + equal(document.getElementById('sc2').firstChild.className,'edui-editor edui-modern','第二个editor的classname'); + equal(document.getElementById(id+'_toolbarbox').className,'edui-editor-toolbarbox edui-modern','第二个editor toolbar的classname'); + equal(document.getElementById(id+'_iframeholder').className,'edui-editor-iframeholder edui-modern','第二个editor iframeholder的classname'); + equal(document.getElementById(id+'_bottombar').className,'edui-editor-bottomContainer edui-modern','第二个editor bottombar的classname'); + equal(document.getElementById(id+'_scalelayer').className,'edui-modern','第二个editor scalelayer的classname'); + sc2 = document.getElementById('sc2'); + sc2.parentNode.removeChild(sc2); + start(); + }); + }); +}); + +test( '判断render有内容时,显示render内容(script)', function() { + var ue3 = new baidu.editor.ui.Editor(); + var sc3 = document.createElement("script"); + sc3.id="sc3"; + sc3.type="text/plain"; +// if(sc3.text) + sc3.text= 'renderinnerhtml'; +// else +// sc3.textContent='renderinnerhtml'; + document.body.appendChild(sc3); + ue3.render('sc3'); + stop(); + ue3.ready(function(){ + equal(ue3.body.firstChild.innerHTML.toLowerCase(),"renderinnerhtml",'标签有内容,显示标签内容'); + sc3 = document.getElementById('sc3'); + sc3.parentNode.removeChild(sc3); + start(); + }); +} ); + +test( 'render没有内容时,显示initialContent', function() { + var ue4 = new baidu.editor.ui.Editor({initialContent:'
        '}); + var sc4 = document.createElement("script"); + sc4.id="sc4"; + document.body.appendChild(sc4); + ue4.render(sc4); + stop(); + ue4.ready(function(){ + equal(ue4.body.firstChild.innerHTML.toLowerCase(),ue4.options.initialContent.toLowerCase(),'标签没有内容,显示initialContent'); + sc4 = document.getElementById('sc4'); + sc4.parentNode.removeChild(sc4); + start(); + }); +} ); + +test('判断dialogs对象名包含"Dialog"字符', function(){ + var ue5 = new baidu.editor.ui.Editor(); + var sc5 = document.createElement("script"); + sc5.id="sc5"; + document.body.appendChild(sc5); + ue5.render(sc5); + stop(); + ue5.ready(function(){ + var array=ue5.ui._dialogs; + for(var p in array){ + ok(p.indexOf('Dialog')!=-1, p); + } + sc5 = document.getElementById('sc5'); + sc5.parentNode.removeChild(sc5); + start(); + }); +}); + +test('getEditor--delEditor',function(){ + var ue7 = UE.ui.Editor(); + var div = document.createElement('div'); + div.id='editor2'; + document.body.appendChild(div); + ue7.render('editor2'); + ue7.ready(function(){ + var ue8=UE.getEditor('editor2'); + equal(ue8.uid,ue7.uid); +// UE.delEditor('editor2'); +// equal(document.getElementById('editor1').tagName.toLowerCase(),'textarea'); + }); +}) + +//test('多层div 全屏',function(){ +// var div1 = document.createElement('div'); +// document.body.appendChild(div1); +// div1.id = 'div1'; +// div1.innerHTML = '
        '; +// div1.firstChild.innerHTML='
        '; +// var div2 = div1.firstChild.firstChild; +// var ue6 = new baidu.editor.ui.Editor({autoFloatEnabled:false}); +// ue6.render(div2); +// stop(); +// ue6.ready(function(){ +// var me = document.getElementById(ue6.ui.id); +// var left = $(me).offset().left; +// var top = $(me).offset().top; +// ue6.ui.setFullScreen( true ); +// setTimeout(function(){ +// ue6.ui.setFullScreen( false ); +// setTimeout(function(){ +// me = document.getElementById(ue6.ui.id); +// ok(left==$(me).offset().left,'left不变'+$(me).offset().left); +// ok(top==$(me).offset().top,'top不变'+$(me).offset().top); +// ue6.focus(); +// ua.checkResult(ue6.selection.getRange(), ue6.body.firstChild.firstChild, ue6.body.firstChild.firstChild, 0, 0, 1); +// me = document.getElementById(ue6.ui.id); +// me.parentNode.removeChild(me); +// start(); +// },50); +// },50); +// }); +//}) \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/editorui.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/editorui.js new file mode 100644 index 000000000..ff49f4935 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/editorui.js @@ -0,0 +1,11 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-4-12 + * Time: 下午4:45 + * To change this template use File | Settings | File Templates. + */ +module( 'ui.editorui' ); +test( '', function() { + equal('','',''); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/mask.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/mask.js new file mode 100644 index 000000000..eccbd0264 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/mask.js @@ -0,0 +1,11 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-4-12 + * Time: 下午4:45 + * To change this template use File | Settings | File Templates. + */ +module( 'ui.mask' ); +test( '', function() { + equal('','',''); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/menu.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/menu.js new file mode 100644 index 000000000..a2fcdfe3f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/menu.js @@ -0,0 +1,327 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-4-12 + * Time: 下午4:45 + * To change this template use File | Settings | File Templates. + */ +module( 'ui.menu' ); +test( 'menu,submenu的显示', function() { +//设置菜单内容\ + var editor = new te.obj[0].Editor(); + var items=[ + { + label:'删除', + cmdName:'delete' + }, + { + label:'全选', + cmdName:'selectall' + }, + { + label:'删除代码', + cmdName:'highlightcode', + icon:'deletehighlightcode' + }, + { + label:'清空文档', + cmdName:'cleardoc', + exec:function () { + + if ( confirm( '确定清空文档吗?' ) ) { + + this.execCommand( 'cleardoc' ); + } + } + }, + '-', + { + label:'取消链接', + cmdName:'unlink' + }, + '-', + { + label:'段落格式', + icon:'justifyjustify', + subMenu:{ + items: [{ + label:'居左对齐', + cmdName:'justify', + value:'left', + editor:editor + }, + { + label:'居右对齐', + cmdName:'justify', + value:'right', + editor:editor + }, + { + label:'居中对齐', + cmdName:'justify', + value:'center', + editor:editor + }, + { + label:'两端对齐', + cmdName:'justify', + value:'justify', + editor:editor + }], + editor:editor + } + } + ]; + var menu = new te.obj[0].Menu({className : 'edui-for-lineheight',items :items,editor:te.obj[0].Editor()}); + menu.render(te.dom[0]); + menu.postRender(); + menu.show(); + var menuBody = document.getElementsByClassName("edui-menu-body")[0]; + equal(menuBody.childNodes[0].className,"edui-menuitem edui-"+editor.options.theme,'menu窗口显示'); + equal(menuBody.childNodes[0].firstChild.lastChild.innerHTML,"删除",'menu窗口显示'); +//edui-menuitem edui-menuseparator + equal(menuBody.childNodes[4].className,"edui-menuitem edui-menuseparator edui-"+editor.options.theme,'menu窗口显示'); + equal(menuBody.childNodes[4].firstChild.className,"edui-menuseparator-inner edui-"+editor.options.theme,'menu窗口显示');//edui-menuitem edui-hassubmenu + equal(menuBody.childNodes[7].className,"edui-menuitem edui-"+editor.options.theme + " edui-hassubmenu edui-hassubmenu",'第7个menu有子menu'); + //submenu + var menuid1 = menu.items[7].id; + var submenu1 = menu.items[7].subMenu.id; + equal(document.getElementById(submenu1).style.display,'none','submenu初始的display值:"none"'); + if(ua.browser.ie){ + ua.mouseenter(menuBody.childNodes[7]); + } + else{ + ua.mouseover(menuBody.childNodes[7]); } + setTimeout(function (){ + equal(document.getElementById(submenu1).style.display,'','显示submenu,检查submenu的display值:""'); + equal(getElementsByClassName_2(document.getElementById(submenu1),'div','edui-menu-body')[0].childNodes.length,4,'检查submenu的menuitems数量'); + equal(getElementsByClassName_2(document.getElementById(submenu1),'div','edui-menu-body')[0].firstChild.className,'edui-menuitem edui-'+editor.options.theme,'检查submenu的内容'); + equal(getElementsByClassName_2(document.getElementById(submenu1),'div','edui-menuitem')[0].firstChild.lastChild.innerHTML,'居左对齐','检查menuitem的内容'); + var menuClass = document.getElementById(menuid1).className; + equal(menuClass,"edui-menuitem edui-"+editor.options.theme+" edui-hassubmenu edui-hassubmenu edui-state-hover edui-state-opened",''); + if(ua.browser.ie){ + ua.mouseleave(document.getElementById(menuid1)); + } + else{ + ua.mouseout(document.getElementById(menuid1)); + } + setTimeout(function (){ + equal(document.getElementById(submenu1).style.display,'none','显示submenu,检查submenu的display值:""'); + menuClass = document.getElementById(menuid1).className; + ok(menuClass.indexOf('edui-state-hover')==-1&&menuClass.indexOf('edui-state-opened')==-1,''); + document.getElementById(submenu1).parentNode.removeChild(document.getElementById(submenu1)); + start(); + }, 450); + }, 300); + stop(); + function getElementsByClassName_2(oElm, strTagName, strClassName){ + var arrElements = (strTagName == "*" && oElm.all)? oElm.all : + oElm.getElementsByTagName(strTagName); + var arrReturnElements = new Array(); + strClassName = strClassName.replace(/\-/g, "\\-"); + var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)"); + var oElement; + for(var i=0; i < arrElements.length; i++){ + oElement = arrElements[i]; + if(oRegExp.test(oElement.className)){ + arrReturnElements.push(oElement); + } + } + return (arrReturnElements); + } +} ); +test( '先打开一个submenu,再打开另一个submenu', function() { +var editor = new te.obj[0].Editor(); +//设置菜单内容 + var items=[ + { + label:'删除', + cmdName:'delete' + }, + { + label:'段落格式', + icon:'justifyjustify', + subMenu:{ + items: [{ + label:'居左对齐', + cmdName:'justify', + value:'left' + + }, + { + label:'居右对齐', + cmdName:'justify', + value:'right' + }, + { + label:'居中对齐', + cmdName:'justify', + value:'center' + }, + { + label:'两端对齐', + cmdName:'justify', + value:'justify' + }], + editor:editor + } + }, + { + label:'表格', + subMenu:{ + items: [{ + label:'居左对齐', + cmdName:'justify', + value:'left' + }, + { + label:'居右对齐', + cmdName:'justify', + value:'right' + }], + editor:editor + } + } + ]; + var menu = new te.obj[0].Menu({className : 'edui-for-lineheight',items :items,editor:editor}); + menu.render(te.dom[0]); + menu.postRender(); + menu.show(); + var menuBody = document.getElementsByClassName("edui-menu-body")[0]; + //submenu + var menuid1 = menu.items[1].id; + var menuid2 = menu.items[2].id; + var submenu1 = menu.items[1].subMenu.id; + var submenu2 = menu.items[2].subMenu.id; + equal(document.getElementById(submenu1).style.display,'none','submenu初始的display值:"none"'); + //打开一个submenu + if(ua.browser.ie){ + ua.mouseenter(document.getElementById(menuid1)); + } + else{ + ua.mouseover(document.getElementById(menuid1)); + } + setTimeout(function (){ + //检查第一个submenu的内容显示 + equal(document.getElementById(submenu1).style.display,'','显示第一个submenu,检查submenu的display值:""'); + var menuClass = document.getElementById(menuid1).className; + equal(menuClass,"edui-menuitem edui-"+editor.options.theme+" edui-hassubmenu edui-hassubmenu edui-state-hover edui-state-opened",'检查第一个submenu的打开状态'); + //打开第二个submenu + if(ua.browser.ie){ + ua.mouseenter(document.getElementById(menuid2)); + } + else{ + ua.mouseover(document.getElementById(menuid2)); + } + setTimeout(function (){ + equal(document.getElementById(submenu1).style.display,'none','第一个submenu关闭,display值:"none"'); + menuClass = document.getElementById(menuid1).className; + ok(menuClass.indexOf('edui-state-opened')==-1,'检查第一个submenu的关闭状态'); + equal(document.getElementById(submenu2).style.display,'','第二个submenu显示,检查submenu的display值:""'); + var menuClass = document.getElementById(menuid2).className; + equal(menuClass,"edui-menuitem edui-"+editor.options.theme+" edui-hassubmenu edui-hassubmenu edui-state-hover edui-state-opened",'检查第二个submenu的打开状态'); + document.getElementById(submenu1).parentNode.removeChild(document.getElementById(submenu2)); + start(); + }, 450); + }, 300); + stop(); +} ); +test( 'dispose', function() { + var editor = new te.obj[0].Editor(); +//设置菜单内容 + var items=[ + { + label:'删除', + cmdName:'delete' + }, + { + label:'全选', + cmdName:'selectall' + }, + { + label:'删除代码', + cmdName:'highlightcode', + icon:'deletehighlightcode' + }, + { + label:'清空文档', + cmdName:'cleardoc', + exec:function () { + if ( confirm( '确定清空文档吗?' ) ) { + this.execCommand( 'cleardoc' ); + } + } + }, + '-', + { + label:'取消链接', + cmdName:'unlink' + }, + { + label:'表格', + subMenu:{ + items: [{ + label:'居左对齐', + cmdName:'justify', + value:'left' + }, + { + label:'居右对齐', + cmdName:'justify', + value:'right' + }], + editor:editor + } + } + ]; + var menu = new te.obj[0].Menu({className : 'edui-for-lineheight',items :items,editor:editor}); + te.dom[0].innerHTML = menu.renderHtml(); + menu.postRender(); + menu.show(); + equal(menu.items.length,7,'检查menu里的items'); + equal(document.getElementById(menu.id).style.display,'','显示menu,检查menu的display值:""'); + menu.dispose(); + equal(menu.items.length,0,'dispose后,检查menu里的items'); + equal(document.getElementById(menu.id),null,'menu不在页面中'); +} ); +test( '_onClick', function() { + var editor = new te.obj[0].Editor(); +//设置菜单内容 + var items=[ + { + label:'取消链接', + cmdName:'unlink' + }, + { + label:'表格', + subMenu:{ + items: [{ + label:'居左对齐', + cmdName:'justify', + value:'left' + }, + { + label:'居右对齐', + cmdName:'justify', + value:'right' + }], + editor:editor + + } + } + ]; + var menu = new te.obj[0].Menu({className : 'edui-for-lineheight',items :items,editor:editor}); + menu.render(te.dom[0]); + menu.postRender(); + menu.show(); + var menuid1 = menu.items[1].id; + var submenu1 = menu.items[1].subMenu.id; + equal(document.getElementById(submenu1).style.display,'none','submenu初始的display值:"none"'); + ua.click(document.getElementById(menuid1)); + setTimeout(function (){ + equal(document.getElementById(submenu1).style.display,'','显示submenu,检查submenu的display值:""'); + document.getElementById(submenu1).parentNode.removeChild(document.getElementById(submenu1)); + start(); + }, 300); + stop(); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/menubutton.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/menubutton.js new file mode 100644 index 000000000..e325114da --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/menubutton.js @@ -0,0 +1,73 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-4-27 + * Time: 下午5:46 + * To change this template use File | Settings | File Templates. + */ +module( 'ui.menubutton' ); +test( 'menubutton', function() { + var editor = new baidu.editor.ui.Editor(); + editor.render("editor"); +//设置菜单内容 + var val=['1', '1.5','1.75','2', '3', '4', '5']; + for(var i=0,ci,items=[];ci = val[i++];){ + items.push({ + label : ci, + value: ci, + onclick:function(){ + } + }) + } + editor.ready(function(){ + var menuButton = new te.obj[0].MenuButton({editor:editor,className : 'edui-for-lineheight',items :items}); + var value = val[1]; + menuButton.setValue(value); + te.dom[0].innerHTML = menuButton.renderHtml(); + menuButton.postRender(); + menuButton.showPopup(); + equal(menuButton.popup.getDom().style.display,"",'窗口显示'); + equal(document.getElementsByClassName("edui-popup edui-menu")[0].style.display,"",'menu窗口显示'); +//检查初始化的显示 + equal(document.getElementsByClassName("edui-menuitem edui-"+editor.options.theme+" edui-state-checked").length,1,'设定已经选中一个value'); + equal(document.getElementsByClassName('edui-menuitem edui-'+editor.options.theme+' edui-state-checked')[0].firstChild.lastChild.innerHTML,value,'检查选中的value'); +//click + ua.click(document.getElementsByClassName("edui-menu-body")[0].childNodes[2]); + equal(menuButton.popup.getDom().style.display,"none",'窗口关闭'); + equal(document.getElementsByClassName("edui-popup edui-menu")[0].style.display,"none",'menu窗口关闭'); + menuButton.showPopup(); + if(ua.browser.ie){ + ua.mouseenter(document.getElementsByClassName("edui-menu-body")[0].childNodes[2],{relatedTarget:document.getElementsByClassName('edui-popup edui-menu')[0]}); + ok(document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-hover')&&!document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-active'),'mouseover加上hover样式'); + ua.mousedown(document.getElementsByClassName("edui-menu-body")[0].childNodes[2],{relatedTarget:document.getElementsByClassName('edui-popup edui-menu')[0]}); + ok(document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-hover')&&document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-active'),'mousedown加上active样式');//edui-state-active + ua.mouseleave(document.getElementsByClassName("edui-menu-body")[0].childNodes[2],{relatedTarget:document.getElementsByClassName('edui-popup edui-menu')[0]}); + ok(!document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-hover')&&!document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-active'),' mouseout去掉hover和active样式'); +////////mouseover->mouseout + ua.mouseenter(document.getElementsByClassName("edui-menu-body")[0].childNodes[2],{relatedTarget:document.getElementsByClassName('edui-popup edui-menu')[0]}); + ua.mouseleave(document.getElementsByClassName("edui-menu-body")[0].childNodes[2],{relatedTarget:document.getElementsByClassName('edui-popup edui-menu')[0]}); + ok(!document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-hover')&&!document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-active'),'mouseout去掉hover和active样式'); + } + else{ +//mouseover->mousedown->mouseout + ua.mouseover(document.getElementsByClassName("edui-menu-body")[0].childNodes[2],{relatedTarget:document.getElementsByClassName('edui-popup edui-menu')[0]}); + ok(document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-hover')&&!document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-active'),'mouseover加上hover样式'); + ua.mousedown(document.getElementsByClassName("edui-menu-body")[0].childNodes[2],{relatedTarget:document.getElementsByClassName('edui-popup edui-menu')[0]}); + ok(document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-hover')&&document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-active'),'mousedown加上active样式');//edui-state-active + ua.mouseout(document.getElementsByClassName("edui-menu-body")[0].childNodes[2],{relatedTarget:document.getElementsByClassName('edui-popup edui-menu')[0]}); + ok(!document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-hover')&&!document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-active'),' mouseout去掉hover和active样式'); +////////mouseover->mouseout + ua.mouseover(document.getElementsByClassName("edui-menu-body")[0].childNodes[2],{relatedTarget:document.getElementsByClassName('edui-popup edui-menu')[0]}); + ua.mouseout(document.getElementsByClassName("edui-menu-body")[0].childNodes[2],{relatedTarget:document.getElementsByClassName('edui-popup edui-menu')[0]}); + ok(!document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-hover')&&!document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-active'),'mouseout去掉hover和active样式'); + } + /////mousedown->mouseup + ua.mousedown(document.getElementsByClassName("edui-menu-body")[0].childNodes[2],{relatedTarget:document.getElementsByClassName('edui-popup edui-menu')[0]}); + ok(!document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-hover')&&document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-active'),'mousedown加上active样式'); + ua.mouseup(document.getElementsByClassName("edui-menu-body")[0].childNodes[2],{relatedTarget:document.getElementsByClassName('edui-popup edui-menu')[0]}); + ok(!document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-hover')&&!document.getElementsByClassName("edui-menu-body")[0].childNodes[2].className.match('edui-state-active'),'mouseup去掉active样式'); + menuButton.popup.hide(); + start(); + }); + stop(); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/popup.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/popup.js new file mode 100644 index 000000000..fcb1d3796 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/popup.js @@ -0,0 +1,84 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-4-12 + * Time: 下午4:47 + * To change this template use File | Settings | File Templates. + */ +module( 'ui.popup' ); +test( '检查显示内容和隐藏方法:getContentHtmlTpl,show(),hide(),isHidden()', function() { + var editor = new baidu.editor.ui.Editor(); + stop(); + setTimeout(function(){ + var autoTypeSetPicker = new baidu.editor.ui.AutoTypeSetPicker({editor:editor}); + + var popup = new te.obj[0].Popup({content: autoTypeSetPicker,'editor':editor}); + var content = autoTypeSetPicker.getHtmlTpl().replace(/##/g, autoTypeSetPicker.id) + .replace(/%%/g, (autoTypeSetPicker.uiName ? 'edui-'+autoTypeSetPicker.uiName : '') + ' ' + autoTypeSetPicker.className); + equal(popup.getContentHtmlTpl(),content, '检查popup的内容'); + equal(popup.getDom(),null,'popup初始不显示'); + + popup.show(); + equal(popup.getDom().style.display,'','popup显示成功'); + var popupContent = document.getElementById(popup.id+'_content'); + equal(popupContent.firstChild.id,autoTypeSetPicker.id,'popup内容autoTypeSetPicker显示'); + equal(popup.isHidden(),false,'isHidden==false'); + + popup.hide(); + equal(popup.getDom().style.display,'none','popup隐藏成功'); + equal(popup.isHidden(),true,'isHidden==true'); + + autoTypeSetPicker.dispose(); + popup.dispose(); + start(); + },50); + + +} ); +test( '定位显示popup;mousedown时隐藏popup', function() { + var editor = new baidu.editor.ui.Editor(); + editor.render('editor'); + editor.ready(function(){ + var autoTypeSetPicker = new baidu.editor.ui.AutoTypeSetPicker({editor:editor}); + var popup = new te.obj[0].Popup({content: autoTypeSetPicker,'editor':editor}); + var uiUtils = baidu.editor.ui.uiUtils; + var leftLocation = 20; + var topLocation = 100; + popup.showAt({left:leftLocation,top:topLocation}); + equal($(popup.getDom()).css('top'),topLocation+'px','popup位置:top'); + equal($(popup.getDom()).css('left'),leftLocation+'px','popup位置:left'); + equal($(popup.getDom()).css('width'),uiUtils.getClientRect(popup.getDom('content')).width+'px','popup位置:width'); + ok(uiUtils.getClientRect(popup.getDom('content')).width>uiUtils.getClientRect(autoTypeSetPicker.getDom()).width,'popup的width大于其内容的width'); + equal($(popup.getDom()).css('height'),uiUtils.getClientRect(popup.getDom('content')).height+'px','popup位置:height'); + ok(uiUtils.getClientRect(popup.getDom('content')).height>uiUtils.getClientRect(autoTypeSetPicker.getDom()).height,'popup的height大于其内容的height'); + + var popup2 = new te.obj[0].Popup({content: autoTypeSetPicker,'editor':editor}); +// var flag = 0; +// popup2.addListener('postRenderAfter',function(){ +// flag = 1; +// }); +// popup2.postRender(); + popup2.show(); + ua.mousedown(document.getElementById(popup.id+'_content')); + equal(popup.isHidden(),false,'在popup上mousedown,popup不隐藏'); + equal(popup2.isHidden(),true,'在popup上mousedown,popup2隐藏'); + popup.show(); + popup2.show(); + ua.mousedown(document.getElementById('editor')); + equal(popup.isHidden(),true,'在其他位置mousedown,popup隐藏'); + equal(popup2.isHidden(),true,'在其他位置mousedown,popup隐藏'); + popup.show(); + popup2.show(); +// $('#editor').scroll(); +//// window.scrollTo( 0, document.body.scrollHeight ); +// equal(popup.isHidden(),true); +// equal(popup2.isHidden(),true); + autoTypeSetPicker.dispose(); + popup.dispose(); + popup2.dispose(); + start(); + }); + stop(); + + +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/separator.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/separator.js new file mode 100644 index 000000000..b6ccb282d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/separator.js @@ -0,0 +1,11 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-4-12 + * Time: 下午4:46 + * To change this template use File | Settings | File Templates. + */ +module( 'ui.separator' ); +test( '', function() { + equal('','',''); +} ); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/splitbutton.js b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/splitbutton.js new file mode 100644 index 000000000..bec52c2a5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/_test/ui/splitbutton.js @@ -0,0 +1,68 @@ +/** + * Created by JetBrains PhpStorm. + * User: dongyancen + * Date: 12-5-2 + * Time: 下午2:36 + * To change this template use File | Settings | File Templates. + */ +module( 'ui.splitbutton' ); +test( 'splitbutton', function() { + //打开一个对话框 + + var editor = new baidu.editor.ui.Editor(); + editor.render("editor"); + editor.ready(function(){ + var splitButton = new te.obj[0].SplitButton({popup:new baidu.editor.ui.Popup({ + //传入配置参数 + content: new te.obj[0].SplitButton({editor:editor}), + 'editor':editor + }), editor:editor}); + te.dom[0].innerHTML = splitButton.renderHtml(); + splitButton.postRender(); + splitButton.showPopup(); + equal(splitButton.popup.getDom('body').lastChild,splitButton.popup.getDom('bordereraser'),'检查:addListener:postrender'); + ok(contains(splitButton.getStateDom().className,"edui-state-opened"),'_onPopupShow'); + splitButton.popup.hide(); + equal(splitButton.getStateDom().className,"",'_onPopupHide'); + splitButton.popup.show(); + ok(contains(splitButton.getStateDom().className,"edui-state-opened"),'_onPopupShow'); + var flag = 0; + //有两个baidu.editor.ui.SplitButton,通过popup操作的是第一个 + splitButton.addListener('buttonclick', function(){ + flag = 1; + }); + + ua.click(document.getElementsByClassName('edui-box edui-button-body')[0]); + equal(flag, 1,'_onButtonClick'); + ua.click(document.getElementsByClassName('edui-box edui-arrow')[0]); + ok(contains(splitButton.getStateDom().className,"edui-state-opened"),'_onArrowClick'); + splitButton.popup.hide(); + equal(splitButton.getStateDom().className,"",'_onArrowClick'); + ua.click(document.getElementsByClassName('edui-box edui-arrow')[0]); + ok(contains(splitButton.getStateDom().className,"edui-state-opened"),'_onArrowClick'); + splitButton.popup.hide(); + start(); + }); + stop(); + function contains(string,substr,isIgnoreCase) + { + if(isIgnoreCase) + { + string=string.toLowerCase(); + substr=substr.toLowerCase(); + } + var startChar=substr.substring(0,1); + var strLen=substr.length; + for(var j=0;j 0 Then + aj_in_string = False + aj_in_escape = False + aj_colonfound = False + For aj_i_tmp = 1 To Len(aj_line) + If aj_in_escape Then + aj_in_escape = False + Else + Select Case Mid(aj_line, aj_i_tmp, 1) + Case """" + aj_in_string = Not aj_in_string + Case ":" + If Not aj_in_escape And Not aj_in_string Then + aj_currentkey = Left(aj_line, aj_i_tmp - 1) + aj_currentvalue = Mid(aj_line, aj_i_tmp + 1) + aj_colonfound = True + Exit For + End If + Case "\" + aj_in_escape = True + End Select + End If + Next + if aj_colonfound then + aj_currentkey = aj_Strip(aj_JSONDecode(aj_currentkey), """") + If Not level(aj_currentlevel).exists(aj_currentkey) Then level(aj_currentlevel).Add aj_currentkey, "" + end if + End If + If right(aj_line,1) = "{" Or right(aj_line,1) = "[" Then + If Len(aj_currentkey) = 0 Then aj_currentkey = level(aj_currentlevel).Count + Set level(aj_currentlevel).Item(aj_currentkey) = Collection() + Set level(aj_currentlevel + 1) = level(aj_currentlevel).Item(aj_currentkey) + aj_currentlevel = aj_currentlevel + 1 + aj_currentkey = "" + ElseIf right(aj_line,1) = "}" Or right(aj_line,1) = "]" or right(aj_line,2) = "}," Or right(aj_line,2) = "]," Then + aj_currentlevel = aj_currentlevel - 1 + ElseIf Len(Trim(aj_line)) > 0 Then + if Len(aj_currentvalue) = 0 Then aj_currentvalue = aj_line + aj_currentvalue = getJSONValue(aj_currentvalue) + + If Len(aj_currentkey) = 0 Then aj_currentkey = level(aj_currentlevel).Count + level(aj_currentlevel).Item(aj_currentkey) = aj_currentvalue + End If + Next + End Sub + + Public Function Collection() + set Collection = Server.CreateObject("Scripting.Dictionary") + End Function + + Public Function AddToCollection(dictobj) + if TypeName(dictobj) <> "Dictionary" then Err.Raise 1, "AddToCollection Error", "Not a collection." + aj_newlabel = dictobj.Count + dictobj.Add aj_newlabel, Collection() + set AddToCollection = dictobj.item(aj_newlabel) + end function + + Private Function CleanUpJSONstring(aj_originalstring) + aj_originalstring = Replace(aj_originalstring, Chr(13) & Chr(10), "") + aj_originalstring = Mid(aj_originalstring, 2, Len(aj_originalstring) - 2) + aj_in_string = False : aj_in_escape = False : aj_s_tmp = "" + For aj_i_tmp = 1 To Len(aj_originalstring) + aj_char_tmp = Mid(aj_originalstring, aj_i_tmp, 1) + If aj_in_escape Then + aj_in_escape = False + aj_s_tmp = aj_s_tmp & aj_char_tmp + Else + Select Case aj_char_tmp + Case "\" : aj_s_tmp = aj_s_tmp & aj_char_tmp : aj_in_escape = True + Case """" : aj_s_tmp = aj_s_tmp & aj_char_tmp : aj_in_string = Not aj_in_string + Case "{", "[" + aj_s_tmp = aj_s_tmp & aj_char_tmp & aj_InlineIf(aj_in_string, "", Chr(13) & Chr(10)) + Case "}", "]" + aj_s_tmp = aj_s_tmp & aj_InlineIf(aj_in_string, "", Chr(13) & Chr(10)) & aj_char_tmp + Case "," : aj_s_tmp = aj_s_tmp & aj_char_tmp & aj_InlineIf(aj_in_string, "", Chr(13) & Chr(10)) + Case Else : aj_s_tmp = aj_s_tmp & aj_char_tmp + End Select + End If + Next + + CleanUpJSONstring = "" + aj_s_tmp = split(aj_s_tmp, Chr(13) & Chr(10)) + For Each aj_line_tmp In aj_s_tmp + aj_line_tmp = replace(replace(aj_line_tmp, chr(10), ""), chr(13), "") + CleanUpJSONstring = CleanUpJSONstring & aj_Trim(aj_line_tmp) & Chr(13) & Chr(10) + Next + End Function + + Private Function getJSONValue(ByVal val) + val = Trim(val) + If Left(val,1) = ":" Then val = Mid(val, 2) + If Right(val,1) = "," Then val = Left(val, Len(val) - 1) + val = Trim(val) + + Select Case val + Case "true" : getJSONValue = True + Case "false" : getJSONValue = False + Case "null" : getJSONValue = Null + Case Else + If (Instr(val, """") = 0) Then + If IsNumeric(val) Then + getJSONValue = CDbl(val) + Else + getJSONValue = val + End If + Else + If Left(val,1) = """" Then val = Mid(val, 2) + If Right(val,1) = """" Then val = Left(val, Len(val) - 1) + getJSONValue = aj_JSONDecode(Trim(val)) + End If + End Select + End Function + + Private JSONoutput_level + Public Function JSONoutput() + dim wrap_dicttype, aj_label + JSONoutput_level = 1 + wrap_dicttype = "[]" + For Each aj_label In data + If Not aj_IsInt(aj_label) Then wrap_dicttype = "{}" + Next + JSONoutput = Left(wrap_dicttype, 1) & Chr(13) & Chr(10) & GetDict(data) & Right(wrap_dicttype, 1) + End Function + + Public Function PrintJson + Response.AddHeader "Content-Type", "text/plain" + If IsEmpty(Request.QueryString("callback")) Then + Response.Write JSONoutput() + Else + Response.Write Request.QueryString("callback") & "(" & JSONoutput() & ")" + End If + End Function + + Private Function GetDict(objDict) + dim aj_item, aj_keyvals, aj_label, aj_dicttype + For Each aj_item In objDict + Select Case TypeName(objDict.Item(aj_item)) + Case "Dictionary" + GetDict = GetDict & Space(JSONoutput_level * 4) + + aj_dicttype = "[]" + For Each aj_label In objDict.Item(aj_item).Keys + If Not aj_IsInt(aj_label) Then aj_dicttype = "{}" + Next + If aj_IsInt(aj_item) Then + GetDict = GetDict & (Left(aj_dicttype,1) & Chr(13) & Chr(10)) + Else + GetDict = GetDict & ("""" & aj_JSONEncode(aj_item) & """" & ": " & Left(aj_dicttype,1) & Chr(13) & Chr(10)) + End If + JSONoutput_level = JSONoutput_level + 1 + + aj_keyvals = objDict.Keys + GetDict = GetDict & (GetSubDict(objDict.Item(aj_item)) & Space(JSONoutput_level * 4) & Right(aj_dicttype,1) & aj_InlineIf(aj_item = aj_keyvals(objDict.Count - 1),"" , ",") & Chr(13) & Chr(10)) + Case Else + aj_keyvals = objDict.Keys + GetDict = GetDict & (Space(JSONoutput_level * 4) & aj_InlineIf(aj_IsInt(aj_item), "", """" & aj_JSONEncode(aj_item) & """: ") & WriteValue(objDict.Item(aj_item)) & aj_InlineIf(aj_item = aj_keyvals(objDict.Count - 1),"" , ",") & Chr(13) & Chr(10)) + End Select + Next + End Function + + Private Function aj_IsInt(val) + aj_IsInt = (TypeName(val) = "Integer" Or TypeName(val) = "Long") + End Function + + Private Function GetSubDict(objSubDict) + GetSubDict = GetDict(objSubDict) + JSONoutput_level= JSONoutput_level -1 + End Function + + Private Function WriteValue(ByVal val) + Select Case TypeName(val) + Case "Double", "Integer", "Long": WriteValue = val + Case "Null" : WriteValue = "null" + Case "Boolean" : WriteValue = aj_InlineIf(val, "true", "false") + Case Else : WriteValue = """" & aj_JSONEncode(val) & """" + End Select + End Function + + Private Function aj_JSONEncode(ByVal val) + val = Replace(val, "\", "\\") + val = Replace(val, """", "\""") + 'val = Replace(val, "/", "\/") + val = Replace(val, Chr(8), "\b") + val = Replace(val, Chr(12), "\f") + val = Replace(val, Chr(10), "\n") + val = Replace(val, Chr(13), "\r") + val = Replace(val, Chr(9), "\t") + aj_JSONEncode = Trim(val) + End Function + + Private Function aj_JSONDecode(ByVal val) + val = Replace(val, "\""", """") + val = Replace(val, "\\", "\") + val = Replace(val, "\/", "/") + val = Replace(val, "\b", Chr(8)) + val = Replace(val, "\f", Chr(12)) + val = Replace(val, "\n", Chr(10)) + val = Replace(val, "\r", Chr(13)) + val = Replace(val, "\t", Chr(9)) + aj_JSONDecode = Trim(val) + End Function + + Private Function aj_InlineIf(condition, returntrue, returnfalse) + If condition Then aj_InlineIf = returntrue Else aj_InlineIf = returnfalse + End Function + + Private Function aj_Strip(ByVal val, stripper) + If Left(val, 1) = stripper Then val = Mid(val, 2) + If Right(val, 1) = stripper Then val = Left(val, Len(val) - 1) + aj_Strip = val + End Function + + Private Function aj_MultilineTrim(TextData) + aj_MultilineTrim = aj_RegExp.Replace(TextData, "$1") + End Function + + private function aj_Trim(val) + aj_Trim = Trim(val) + Do While Left(aj_Trim, 1) = Chr(9) : aj_Trim = Mid(aj_Trim, 2) : Loop + Do While Right(aj_Trim, 1) = Chr(9) : aj_Trim = Left(aj_Trim, Len(aj_Trim) - 1) : Loop + aj_Trim = Trim(aj_Trim) + end function +End Class +%> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/asp/MultiformProcessor.class.asp b/nezha-fronted/static/ueditor-1.4.3.3/asp/MultiformProcessor.class.asp new file mode 100644 index 000000000..ec2b4e1e7 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/asp/MultiformProcessor.class.asp @@ -0,0 +1,138 @@ +<% +' Power by Techird +' Processor Usage: +' Set p = new MultiformProcessor +' Set formValues = p.Process() +' filename = formValues.Item("filename") +' Set stream = formValues.Item("file1") // the name of the file input +' stream.SaveToFile "upload/" & filename +' stream.Close +Class MultiformProcessor + Private adTypeBinary + Private adTypeText + Private adModeReadWrite + Private binCtLf + Private binCtLf2 + + + private Sub Class_Initialize() + adTypeBinary = 1 + adTypeText = 2 + adModeReadWrite = 3 + binCtLf = ChrB(13) & ChrB(10) + binCtLf2 = binCtLf & binCtLf + End Sub + + Private Function OpenStream( optype ) + Set stream = Server.CreateObject("ADODB.Stream") + stream.Type = optype + stream.Mode = adModeReadWrite + stream.Open + Set OpenStream = stream + End Function + + Private Function CopyStreamPart( stream, pBgn, pEnd ) + Dim iStream, oStream + Set iStream = stream + Set oStream = OpenStream( adTypeBinary ) + iStream.Position = pBgn + iStream.CopyTo oStream, pEnd - pBgn + Set CopyStreamPart = oStream + End Function + + Private Function GetString( stream, pBgn, pEnd ) + Dim iStream, oStream + Set iStream = stream + Set oStream = OpenStream( adTypeBinary ) + iStream.Position = pBgn + iStream.CopyTo oStream, pEnd - pBgn + oStream.Position = 0 + oStream.Type = adTypeText + oStream.Charset = GetCharset + GetString = oStream.ReadText + oStream.Close + End Function + + Private Function GetCharset() + If Charset = "" Then + GetCharset = "utf-8" + Else + GetCharset = Charset + End If + End Function + + 'See RFC 2388 + 'http://www.ietf.org/rfc/rfc2388.txt + public Function Process() + Dim formBytes, bLen, pBgn, pEnd, header, stream + Dim varPtn, filePtn, formValues, key, field + + formBytes = Request.BinaryRead( Request.TotalBytes ) + + Set stream = OpenStream( adTypeBinary ) + stream.Write formBytes + + Set varPtn = new RegExp + varPtn.Pattern = "(\w+?)=""(.+?)""" + varPtn.Global = True + + Set filePtn = new RegExp + filePtn.Pattern = "filename=" + + Set formValues = Server.CreateObject("Scripting.Dictionary") + + 'Find boundary + bLen = InStrB( 1, formBytes, binCtLf ) - 1 + boundary = LeftB( formBytes, bLen ) + + 'Init begin pointer to byte start + pBgn = 1 + + Do + 'Find begin pointer and end pointer for block header + pBgn = pBgn + bLen + LenB( binCtLf ) - 1 + pEnd = InStrB( pBgn, formBytes, binCtLf2 ) + + 'If next block not found, means all blocks processed + If pEnd = 0 Then + Exit Do 'Load Finished + End If + + 'Decode the headerf + header = GetString( stream, pBgn, pEnd ) + + 'Test if the block is a file block + isFileBlock = filePtn.Test( header ) + + 'Find begin pointer and end pointer for block content + pBgn = pEnd + LenB(binCtLf2) - 1 + pEnd = InStrB(pBgn, formBytes, boundary) - LenB( binCtLf ) - 1 + + 'Extract field values from header, which like key = "filed" + Set matches = varPtn.Execute( header ) + For Each match In matches + key = match.SubMatches(0) + field = match.SubMatches(1) + 'filename as a field + If key = "filename" Then + formValues.Add key, field + 'name specified fields + ElseIf key = "name" Then + If isFileBlock Then + 'Resolve content as stream for fileblock + formValues.Add field, CopyStreamPart(stream, pBgn, pEnd) + Else + 'Resolve content as string for non-fileblock + formValues.Add field, GetString(stream, pBgn, pEnd) + End If + End If + Next + + 'Move over the begin pointer to next block + pBgn = pEnd + LenB( binCtLf ) + 1 + Loop + stream.Close + Set Process = formValues + End Function +End Class +%> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/asp/PathFormatter.class.asp b/nezha-fronted/static/ueditor-1.4.3.3/asp/PathFormatter.class.asp new file mode 100644 index 000000000..b0196a0cd --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/asp/PathFormatter.class.asp @@ -0,0 +1,81 @@ +<% + +Class PathFormatter + Public Function Format( ByVal pathFormat, ByVal filename ) + Dim ext, name + If IsEmpty( format ) Then + format = "{yyyy}{mm}{dd}{hh}{ii}{ss}{rand:6}" + End If + + Set invalidPattern = new RegExp + invalidPattern.Pattern = "[\\\/\:\*\?\<\>\|""]" + invalidPattern.Global = true + filename = invalidPattern.Replace( filename, "" ) + + ext = GetExt( filename ) + name = GetNameWithoutExt( filename ) + + pathFormat = Replace( pathFormat, "{filename}", name ) + pathFormat = Replace( pathFormat, "{time}", TimeStamp() ) + pathFormat = Replace( pathFormat, "{yyyy}", Year(Now) ) + pathFormat = Replace( pathFormat, "{yy}", Year(Now) Mod 100 ) + pathFormat = Replace( pathFormat, "{mm}", LeadZero( Month(Now) ) ) + pathFormat = Replace( pathFormat, "{dd}", LeadZero( Day(Now) ) ) + pathFormat = Replace( pathFormat, "{hh}", LeadZero( Hour(Now) ) ) + pathFormat = Replace( pathFormat, "{ii}", LeadZero( Minute(Now) ) ) + pathFormat = Replace( pathFormat, "{ss}", LeadZero( Second(Now) ) ) + + Set randPattern = new RegExp + randPattern.Pattern = "{rand(\:?)(\d+)}" + Set matches = randPattern.Execute(pathFormat) + If matches.Count Then + Set match = matches(0) + digit = 6 + If match.SubMatches.Count > 1 Then + digit = 0 + match.SubMatches(1) + End If + min = 1 + Do While digit > 0 + min = min * 10 + digit = digit - 1 + Loop + max = min * 10 + pathFormat = randPattern.Replace( pathFormat, Rand( min, max ) ) + End If + Format = pathFormat + ext + End Function + + Private Function GetExt( file ) + GetExt = Right( file, Len(file) - InStrRev(file, ".") + 1 ) + End Function + + Private Function GetNameWithoutExt( file ) + GetNameWithoutExt = Left( file, InStrRev(file, ".") - 1 ) + End Function + + Private Function TimeStamp() + TimeStamp = DateDiff("s", "1970-1-1 8:00:00", Now()) + End Function + + Private Function Rand( min, max ) + Randomize + Rand = Int( (max - min + 1) * Rnd + min ) + End Function + + Private Function GetFormatedDate() + Dim yyyy, mm, dd + yyyy = Year(Date) + mm = LeadZero(Month(Date)) + dd = LeadZero(Day(Date)) + GetFormatedDate = yyyy & mm & dd + End Function + + Private Function LeadZero( number ) + If number < 10 Then + LeadZero = "0" & number + Else + LeadZero = number + End If + End Function +End Class +%> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/asp/README.md b/nezha-fronted/static/ueditor-1.4.3.3/asp/README.md new file mode 100644 index 000000000..bf3a2215f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/asp/README.md @@ -0,0 +1,115 @@ +# UEditor ASP 支持说明 + +应广大用户要求,UEditor 团队在原本支持的 PHP、Java 和 .Net 的后台的基础上,推出了 ASP 后台的支持。 + +## 支持版本 ## +支持 UEditor 1.2.6+ 的版本 + +## 支持功能 ## +支持所有其他后台已支持的功能,包括: + +1. 图片上传 +2. 远程图片转存 +3. 图片管理 +4. 涂鸦上传(包括背景) +5. Word 图片转存 +6. 截图上传 +7. 文件上传 + +## 部署指南 ## +Classic ASP 一般在 IIS 上运行。其它 ASP 服务器不介绍部署方式,请自行研究。 + +### 配置 ### + +对于 v1.4.0 之前的版本,需要修改 `ueditor.config.js`。最简单的方法,就是把文件中的 php 都替换成 asp。要修改的配置包括: + +```javascript +{ + imageUrl:URL+"asp/imageUp.asp" + ,imagePath:URL + "asp/" + ,scrawlUrl:URL+"asp/scrawlUp.asp" + ,scrawlPath:URL+"asp/" + ,fileUrl:URL+"asp/fileUp.asp" + ,filePath:URL + "asp/" + ,catcherUrl:URL +"asp/getRemoteImage.asp" + ,catcherPath:URL + "asp/" + ,imageManagerUrl:URL + "asp/imageManager.asp" + ,imageManagerPath:URL + "asp/" + ,snapscreenServerUrl: URL +"asp/imageUp.asp" + ,snapscreenPath: URL + "asp/" + ,wordImageUrl:URL + "asp/imageUp.asp" + ,wordImagePath:URL + "asp/" + ,getMovieUrl:URL+"asp/getMovie.asp" +} +``` + +UEditor v1.4.0 后进行了后端的统一配置,后端相关的配置文件是 `config.json`,在具体的后台目录下。需要注意以下两个类型的配置: + + +```javascript +{ + "{tpl}UrlPrefix": "/ueditor/asp/", + "{tpl}PathFormat": "upload/{tpl}/{yyyy}{mm}{dd}/{time}{rand:6}" +} +``` + +`{tpl}PathFormat` 是资源(图片、涂鸦、文件等)保存的位置以及文件名格式,这个路径在 ASP 中是相对运行目录的。 + +`{tpl}UrlPrefix` 是资源定位的基本路径,在 ASP 后台中一般设置成 ASP 的目录。 + +比如,IIS 中运行的 UEditor ASP 的目录为 C:\iis_pub\wwwroot\mysite\ueditor\asp,而网站的访问地址为 http://localhost/mysite/,那么你可以这样修改这两类配置项: + +```javascript +{ + "{tpl}UrlPrefix": "/mysite/ueditor/asp/", + "{tpl}PathFormat": "upload/{tpl}/{yyyy}{mm}{dd}/{time}{rand:6}" +} +``` + + +### 在 IIS 6.X 中部署 +IIS 的安装在这里不介绍,请自行查阅相关资料。 + +1. 启用 ASP 拓展 + * 打开 IIS 管理器 + * 展开本地计算机 + * 选中 Web 服务拓展 + * 允许 Active Server Pages 拓展 + +2. 配置网站脚本执行权限(如果使用虚拟路径,请跳过本步骤) + * 在网站上右击,点属性 + * 切换到主目录选项卡,勾选*读取*、*写入*两个权限,并且*执行权限*选择*纯脚本* + * 点确定 + +3. 使用虚拟路径 + * 在网站上右击,点*新建* - *虚拟路径* + * 按照向导填写名称和路径 + * 勾选*读取*、*执行脚本*和*写入*三个权限 + * 完成虚拟目录的创建 + +4. 配置脚本执行身份 + * 在网站或虚拟路径上右击,点属性 + * 选择*目录安全性*选项卡 + * 在*身份验证和访问控制*中点击*编辑* + * 勾选*启用匿名访问*,点击用户名后面的*浏览* + * 输入*administrator*点确定 + * 输入*administrator*账号的密码 + * 点击确定,再确认一次密码 + +5. 设置最大 HTTP 请求大小限制 + * 找到位于 C:\Windows\System32\Inetsrv 中的 metabase.XML,打开,查找ASPMaxRequestEntityAllowed,修改为需要的值(如10240000 即 10M) + > ASP 文件中也有上传文件大小的限制,不过先验证的限制是 IIS 中设置的,所以如果 IIS 中设置最大 256K,那么就算 ASP 中设置了最大 10M,那么超过 256K 的文件也无法上传,而且 ASP 没法给出错误信息。 + +### 在 IIS 7.X 中部署 +IIS7 默认不安装 ASP,需要手动添加进去。添加方法请读者自行查阅。 + +1. 配置脚本执行身份 + * 选中网站或者应用程序 + * 双击 IIS 中的*身份验证* + * 双击匿名身份验证 + * 填写*administrator*的用户名和密码,确定 + +2. 设置最大 HTTP 请求大小限制 + * 打开 IIS 控制台 + * 双击 ASP,展开*限制属性*,修改*醉倒请求实体主体限制*为需要的值(如10240000 即 10M) + > ASP 文件中也有上传文件大小的限制,不过先验证的限制是 IIS 中设置的,所以如果 IIS 中设置最大 256K,那么就算 ASP 中设置了最大 10M,那么超过 256K 的文件也无法上传,而且 ASP 没法给出错误信息。 diff --git a/nezha-fronted/static/ueditor-1.4.3.3/asp/Uploader.Class.asp b/nezha-fronted/static/ueditor-1.4.3.3/asp/Uploader.Class.asp new file mode 100644 index 000000000..5d65ce102 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/asp/Uploader.Class.asp @@ -0,0 +1,264 @@ + + + +<% +' ASP 文件上传类 +' Author: techird +' Email: techird@qq.com + +'配置 +'MAX_SIZE 在这里设定了之后如果出现大上传失败,请执行以下步骤 +'IIS 6 + '找到位于 C:\Windows\System32\Inetsrv 中的 metabase.XML 打开,找到ASPMaxRequestEntityAllowed 把他修改为需要的值(如10240000即10M) +'IIS 7 + '打开IIS控制台,选择 ASP,在限制属性里有一个“最大请求实体主题限制”,设置需要的值 + +CURRENT_ENCODING = "gb2312" + +Class Uploader + + '上传配置 + Private cfgMaxSize + Private cfgAllowType + Private cfgPathFormat + Private cfgFileField + + '上传返回信息 + Private stateString + Private rsOriginalFileName + Private rsFilePath + + Private rsFileName + Private rsFileSize + Private rsState + Private rsFormValues + + Private Sub Class_Initialize + Set stateString = Server.CreateObject("Scripting.Dictionary") + stateString.Add "SIZE_LIMIT_EXCCEED", "File size exceeded!" + stateString.Add "TYPE_NOW_ALLOW", "File type not allowed!" + End Sub + + Public Property Let MaxSize(ByVal size) + cfgMaxSize = size + End Property + + Public Property Let AllowType(ByVal types) + Set cfgAllowType = types + End Property + + Public Property Let PathFormat(ByVal format) + cfgPathFormat = format + End Property + + Public Property Let FileField(ByVal field) + cfgFileField = field + End Property + + Public Property Get OriginalFileName + OriginalFileName = rsOriginalFileName + End Property + + Public Property Get FileName + FileName = rsFileName + End Property + + Public Property Get FilePath + FilePath = rsFilePath + End Property + + Public Property Get FileSize + FileSize = rsFileSize + End Property + + Public Property Get State + State = rsState + End Property + + Public Property Get FormValues + Set FormValues = rsFormValues + End Property + + Public Function UploadForm() + ProcessForm() + SaveFile() + End Function + + Public Function ProcessForm() + Set processor = new MultiformProcessor + Set rsFormValues = processor.Process() + End Function + + Public Function SaveFile() + Dim stream, filename + Set stream = rsFormValues.Item( cfgFileField ) + filename = rsFormValues.Item( "filename" ) + DoUpload stream, filename + End Function + + Public Function UploadBase64( filename ) + Dim stream, content + content = Request.Item ( cfgFileField ) + Set stream = Base64Decode( content ) + + DoUpload stream, filename + End Function + + Private Function RegExpTest(patrn, str) + Dim regEx, Match, Matches + Set regEx = New RegExp + regEx.Pattern = patrn + regEx.IgnoreCase = False + regEx.Global = True + Set Matches = regEx.Execute(str) + For Each Match in Matches + RetStr = RetStr & Match.value &" " + RetStr = RetStr & vbCRLF + Next + RegExpTest = RetStr + End Function + + Private Function IpToNumber( ip ) + arr=split(ip,".") + IpToNumber=256*256*256*clng(arr(0))+256*256*clng(arr(1))+256*clng(arr(2))+clng(arr(3)) + End Function + + Private Function IsPrivateIp( url ) + Dim ip + ip = RegExpTest("\d+\.\d+\.\d+\.\d*", url) + + If ip = "" Then + If RegExpTest("([\w-]+\.)+[\w-]+", url) <> "" Then + IsPrivateIp = False:Exit Function + End If + IsPrivateIp = True:Exit Function + End If + + If instr(ip,"127.")=1 Then + IsPrivateIp = true:Exit Function + End If + ABegin = IpToNumber("10.0.0.0"):AEnd = IpToNumber("10.255.255.255") + BBegin = IpToNumber("172.16.0.0"):BEnd = IpToNumber("172.31.255.255") + CBegin = IpToNumber("192.168.0.0"):CEnd = IpToNumber("192.168.255.255") + IpNum = IpToNumber(ip) + IsPrivateIp = (ABegin <= IpNum and IpNum <= AEnd) or (BBegin <= IpNum and IpNum <= BEnd) or (CBegin <= IpNum and IpNum <= CEnd) + End Function + + Public Function UploadRemote( url ) + Dim stream, filename + + If IsPrivateIp(url) Then + rsState = "Failed":Exit Function + End If + + filename = Right( url, Len(url) - InStrRev(url, "/") ) + + Set stream = CrawlImage( url ) + + If Not IsNull(stream) Then + DoUpload stream, filename + Else + rsState = "Failed" + End If + Set stream = Nothing + End Function + + Private Function DoUpload( stream, filename ) + + rsFileSize = stream.Size + If rsFileSize > cfgMaxSize Then + rsState = stateString.Item( "SIZE_LIMIT_EXCCEED" ) + Exit Function + End If + + rsOriginalFileName = filename + fileType = GetExt(filename) + If CheckExt(fileType) = False Then + rsState = stateString.Item( "TYPE_NOW_ALLOW" ) + Exit Function + End If + + Set formatter = new PathFormatter + rsFilePath = formatter.format( cfgPathFormat, filename ) + + savePath = Server.MapPath(rsFilePath) + CheckOrCreatePath( GetDirectoryName(savePath) ) + + stream.SaveToFile savePath + stream.Close + rsState = "SUCCESS" + End Function + + Private Function GetDirectoryName(path) + GetDirectoryName = Left( path, InStrRev(path, "\") ) + End Function + + Private Function Base64Decode( content ) + dim xml, stream, node + Set xml = Server.CreateObject("MSXML2.DOMDocument") + Set stream = Server.CreateObject("ADODB.Stream") + Set node = xml.CreateElement("tmpNode") + node.dataType = "bin.base64" + node.Text = content + stream.Charset = CURRENT_ENCODING + stream.Type = 1 + stream.Open() + stream.Write( node.nodeTypedValue ) + Set Base64Decode = stream + Set node = Nothing + Set stream = Nothing + Set xml = Nothing + End Function + + Private Function CrawlImage( url ) + Dim http, stream + Set http = Server.CreateObject("Microsoft.XMLHTTP") + http.Open "GET", url, false + http.Send + If http.Status = 200 Then + Set stream = Server.CreateObject("ADODB.Stream") + stream.Type = 1 + stream.Open() + stream.Write http.ResponseBody + Set CrawlImage = stream + Else + Set CrawlImage = null + End If + Set http = Nothing + End Function + + Private Function CheckExt( fileType ) + If IsEmpty (cfgAllowType) Then + CheckExt = true + Exit Function + End If + For Each ext In cfgAllowType + If UCase(fileType) = UCase(cfgAllowType.Item(ext)) Then + CheckExt = true + Exit Function + End If + Next + CheckExt = false + End Function + + Private Function GetExt( file ) + GetExt = Right( file, Len(file) - InStrRev(file, ".") + 1 ) + End Function + + Private Function CheckOrCreatePath( ByVal path ) + Set fs = Server.CreateObject("Scripting.FileSystemObject") + Dim parts + parts = Split( path, "\" ) + path = "" + For Each part in parts + path = path + part + "\" + If fs.FolderExists( path ) = False Then + fs.CreateFolder( path ) + End If + Next + End Function +End Class + + + +%> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/asp/action_config.asp b/nezha-fronted/static/ueditor-1.4.3.3/asp/action_config.asp new file mode 100644 index 000000000..d3726a4ff --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/asp/action_config.asp @@ -0,0 +1,9 @@ + + + +<% + Set json = new ASPJson + Set json.data = config + + json.PrintJson() +%> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/asp/action_crawler.asp b/nezha-fronted/static/ueditor-1.4.3.3/asp/action_crawler.asp new file mode 100644 index 000000000..1235916d5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/asp/action_crawler.asp @@ -0,0 +1,32 @@ + + + +<% + + Set up = new Uploader + up.MaxSize = config.Item("catcherMaxSize") + up.AllowType = config.Item("catcherAllowFiles") + up.PathFormat = config.Item("catcherPathFormat") + + urls = Split(Request.Item("source[]"), ", ") + Set list = new ASPJson.Collection + + For i = 0 To UBound(urls) + up.UploadRemote( urls(i) ) + Dim instance + Set instance = new ASPJson.Collection + instance.Add "state", up.State + instance.Add "url", up.FilePath + instance.Add "source", urls(i) + list.Add i, instance + Next + + Set json = new ASPJson + + With json.data + .Add "state", "SUCCESS" + .Add "list", list + End With + + json.PrintJson() +%> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/asp/action_list.asp b/nezha-fronted/static/ueditor-1.4.3.3/asp/action_list.asp new file mode 100644 index 000000000..74bf8097c --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/asp/action_list.asp @@ -0,0 +1,81 @@ + + + +<% + listTemplateName = Session.Value("ueditor_asp_listTemplateName") + + start = CInt(Request.Item("start")) + size = CInt(Request.Item("size")) + total = 0 + + If size < 0 Then + size = CInt(config.Item( listTemplateName + "ManagerListSize" )) + End If + + path = config.Item( listTemplateName + "ManagerListPath" ) + Set extensions = config.Item( listTemplateName + "ManagerAllowFiles") + + Set list = new ASPJson.Collection + + Set fso = Server.CreateObject("Scripting.FileSystemObject") + If fso.FolderExists(Server.MapPath(path)) = False Then + state = "找不到目录:" + path + Else + Set all = ListAllFilesInFolder( fso, path ) + total = all.Count + index = 0 + For Each file in all + If index >= start And index < start + size Then + Dim fileObject + Set fileObject = new ASPJson.Collection + fileObject.Add "url", file + list.Add index - start, fileObject + End If + index = index + 1 + Next + state = "SUCCESS" + End If + + Set json = new ASPJson + With json.data + .Add "state", state + .Add "list", list + .Add "start", start + .Add "size", size + .Add "total", total + End With + + json.PrintJson() + + Function ListAllFilesInFolder( fso, path ) + Dim list + Set list = Server.CreateObject("Scripting.Dictionary") + Set folder = fso.GetFolder(Server.MapPath(path)) + For Each file In folder.Files + If CheckExt(file.Name) Then + list.Add path & "/" & file.Name, true + End If + Next + For Each subFolder In folder.SubFolders + Set subList = ListAllFilesInFolder( fso, path & "/" & subFolder.Name ) + For Each subListFile In subList + list.Add subListFile, true + Next + Next + Set ListAllFilesInFolder = list + End Function + + Function CheckExt( filename ) + For Each ext In extensions + If UCase(GetExt(filename)) = UCase(extensions.Item(ext)) Then + CheckExt = true + Exit Function + End If + Next + CheckExt = false + End Function + + Function GetExt( file ) + GetExt = Right( file, Len(file) - InStrRev(file, ".") + 1 ) + End Function +%> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/asp/action_upload.asp b/nezha-fronted/static/ueditor-1.4.3.3/asp/action_upload.asp new file mode 100644 index 000000000..19300c122 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/asp/action_upload.asp @@ -0,0 +1,29 @@ + + + +<% + uploadTemplateName = Session.Value("ueditor_asp_uploadTemplateName") + + Set up = new Uploader + up.MaxSize = config.Item( uploadTemplateName & "MaxSize" ) + up.FileField = config.Item( uploadTemplateName & "FieldName" ) + up.PathFormat = config.Item( uploadTemplateName & "PathFormat" ) + + If Not IsEmpty( Session.Value("base64Upload") ) Then + up.UploadBase64( Session.Value("base64Upload") ) + Else + up.AllowType = config.Item( uploadTemplateName & "AllowFiles" ) + up.UploadForm() + End If + + Set json = new ASPJson + + With json.data + .Add "url", up.FilePath + .Add "original", up.OriginalFileName + .Add "state", up.State + .Add "title", up.OriginalFileName + End With + + json.PrintJson() +%> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/asp/config.json b/nezha-fronted/static/ueditor-1.4.3.3/asp/config.json new file mode 100644 index 000000000..9a20cc7c6 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/asp/config.json @@ -0,0 +1,94 @@ +/* 前后端通信相关的配置,注释只允许使用多行方式 */ +{ + /* 上传图片配置项 */ + "imageActionName": "uploadimage", /* 执行上传图片的action名称 */ + "imageFieldName": "upfile", /* 提交的图片表单名称 */ + "imageMaxSize": 2048000, /* 上传大小限制,单位B */ + "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */ + "imageCompressEnable": true, /* 是否压缩图片,默认是true */ + "imageCompressBorder": 1600, /* 图片压缩最长边限制 */ + "imageInsertAlign": "none", /* 插入的图片浮动方式 */ + "imageUrlPrefix": "/ueditor/asp/", /* 图片访问路径前缀 */ + "imagePathFormat": "upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */ + /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */ + /* {time} 会替换成时间戳 */ + /* {yyyy} 会替换成四位年份 */ + /* {yy} 会替换成两位年份 */ + /* {mm} 会替换成两位月份 */ + /* {dd} 会替换成两位日期 */ + /* {hh} 会替换成两位小时 */ + /* {ii} 会替换成两位分钟 */ + /* {ss} 会替换成两位秒 */ + /* 非法字符 \ : * ? " < > | */ + /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */ + + /* 涂鸦图片上传配置项 */ + "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */ + "scrawlFieldName": "upfile", /* 提交的图片表单名称 */ + "scrawlPathFormat": "upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "scrawlMaxSize": 2048000, /* 上传大小限制,单位B */ + "scrawlUrlPrefix": "/ueditor/asp/", /* 图片访问路径前缀 */ + "scrawlInsertAlign": "none", + + /* 截图工具上传 */ + "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */ + "snapscreenPathFormat": "upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "snapscreenUrlPrefix": "/ueditor/asp/", /* 图片访问路径前缀 */ + "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */ + + /* 抓取远程图片配置 */ + "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"], + "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */ + "catcherFieldName": "source", /* 提交的图片列表表单名称 */ + "catcherPathFormat": "upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "catcherUrlPrefix": "/ueditor/asp/", /* 图片访问路径前缀 */ + "catcherMaxSize": 2048000, /* 上传大小限制,单位B */ + "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */ + + /* 上传视频配置 */ + "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */ + "videoFieldName": "upfile", /* 提交的视频表单名称 */ + "videoPathFormat": "upload/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "videoUrlPrefix": "/ueditor/asp/", /* 视频访问路径前缀 */ + "videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */ + "videoAllowFiles": [ + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */ + + /* 上传文件配置 */ + "fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */ + "fileFieldName": "upfile", /* 提交的文件表单名称 */ + "filePathFormat": "upload/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "fileUrlPrefix": "/ueditor/asp/", /* 文件访问路径前缀 */ + "fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */ + "fileAllowFiles": [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ], /* 上传文件格式显示 */ + + /* 列出指定目录下的图片 */ + "imageManagerActionName": "listimage", /* 执行图片管理的action名称 */ + "imageManagerListPath": "upload/image", /* 指定要列出图片的目录 */ + "imageManagerListSize": 20, /* 每次列出文件数量 */ + "imageManagerUrlPrefix": "/ueditor/asp/", /* 图片访问路径前缀 */ + "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */ + "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */ + + /* 列出指定目录下的文件 */ + "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */ + "fileManagerListPath": "upload/file", /* 指定要列出文件的目录 */ + "fileManagerUrlPrefix": "/ueditor/asp/", /* 文件访问路径前缀 */ + "fileManagerListSize": 20, /* 每次列出文件数量 */ + "fileManagerAllowFiles": [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ] /* 列出的文件类型 */ + +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/asp/config_loader.asp b/nezha-fronted/static/ueditor-1.4.3.3/asp/config_loader.asp new file mode 100644 index 000000000..085f79c15 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/asp/config_loader.asp @@ -0,0 +1,21 @@ +<% + Set json = new ASPJson + Set fso = Server.CreateObject("Scripting.FileSystemObject") + + Set stream = Server.CreateObject("ADODB.Stream") + + stream.Open() + stream.Charset = "UTF-8" + stream.LoadFromFile Server.MapPath( "config.json" ) + + content = stream.ReadText() + + Set commentPattern = new RegExp + commentPattern.Multiline = true + commentPattern.Pattern = "/\*[\s\S]+?\*/" + commentPattern.Global = true + content = commentPattern.Replace(content, "") + json.loadJSON( content ) + + Set config = json.data +%> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/asp/controller.asp b/nezha-fronted/static/ueditor-1.4.3.3/asp/controller.asp new file mode 100644 index 000000000..5dd2ff73e --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/asp/controller.asp @@ -0,0 +1,44 @@ +<%@ LANGUAGE="VBSCRIPT" CODEPAGE="65001" %> +<% + action = Request.Item("action") + + Session.Contents.Remove("ueditor_asp_uploadTemplateName") + Session.Contents.Remove("ueditor_asp_base64Upload") + Session.Contents.Remove("ueditor_asp_listTemplateName") + + + Select Case action + + Case "config" + Server.Execute("action_config.asp") + + Case "uploadimage" + Session.Value("ueditor_asp_uploadTemplateName") = "image" + Server.Execute("action_upload.asp") + + Case "uploadscrawl" + Session.Value("ueditor_asp_uploadTemplateName") = "scrawl" + Session.Value("base64Upload") = "scrawl.png" + Server.Execute("action_upload.asp") + + Case "uploadvideo" + Session.Value("ueditor_asp_uploadTemplateName") = "video" + Server.Execute("action_upload.asp") + + Case "uploadfile" + Session.Value("ueditor_asp_uploadTemplateName") = "file" + Server.Execute("action_upload.asp") + + Case "listimage" + Session.Value("ueditor_asp_listTemplateName") = "image" + Server.Execute("action_list.asp") + + Case "listfile" + Session.Value("ueditor_asp_listTemplateName") = "file" + Server.Execute("action_list.asp") + + Case "catchimage" + Server.Execute("action_crawler.asp") + End Select + +%> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/changelog.md b/nezha-fronted/static/ueditor-1.4.3.3/changelog.md new file mode 100644 index 000000000..562eb20d3 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/changelog.md @@ -0,0 +1,432 @@ +#UEditor Change List + +##1.4.3 +###bug修复&优化改进 +1. 修复hasContents接口在非ie下只有空格时判断还为真的问题 +2. 修复在粘贴word内容时,会误命中cm,pt这样的文本内容变成px的问题 +3. 优化删除编辑器再创建编辑器时,编辑器的容器id发生变化的问题 +4. 修复提交jsonp请求时,callback参数的xss漏洞 +5. 新增jsp后台多种服务器配置下的路径定位 +6. 修复ZeroClipboard的flash地址参数名称错误 +7. 修复getActionUrl的bug +8. 整理配置参数,把遗漏在代码中的配置项整理到ueditor.config.js里 +9. 修复图片拉伸工具和编辑拉伸长高器的样式冲突 +10. 修复文字的unicode编码会被错误再次解析问题 +11. 添加消息提示功能,冒泡提示信息 +12. 优化上传功能提示,当后端配置项没正常加载,禁用上传功能 +13. 修复单图上传按钮和jqueryValidate不兼容的问题 +14. 简化了与jqueryValidate的结合操作,具体看_examples/jqueryValidateDemo.html +15. 修复在删除编辑器后,再次创建时丢失原有id的问题 +16. 修复查找替换在一些块节点中会导致替换错误 + +##1.4.2 +###重构前后端交互功能 +1. 前端上传模块统一改用webuploader +2. 整体重构了文件上传的配置方式,改为统一在后端配置,前后端自动打通,[详细文档]() +3. 统一各上传模块的提交地址,各模块通过action参数区分类型,[详细文档]() +4. 提供serverparam命令,可在提交时追加任意参数,[详细文档]() +5. 统一了前端各上传模块的布局样式 +6. 支持了在线附件预览和插入 +7. 统一了后端返回数据格式,[详细文档]() +8. 各在线预览列表模块支持分组加载 +9. 增加点击直接选择文件上传图片插件 +10. 优化了粘贴图片的功能,上传时有loading和出错的提示 +11. 添加jsonp的跨域请求支持 + +###bug修复&优化改进 +1. 修复内容过多时,回到顶部,顶部内容被工具栏遮挡问题 +2. 修复htmlparser解析标签的bug +3. 修复锚点是#开头时还添加http://的bug +4. 修复全屏后,退出全屏高度没有缩回来的问题 +5. 文字选中后按delete删除,无法触发contentchange事件 +6. 修复选择图片时点击8个控制点不拖动,contentchange会误触发的问题 +7. 修复执行命令会触发多次contentchange事件 +8. 修复输入文字,设置高度300,没有滚动条 +9. 修复在不可编辑模式下,链接认可修改的问题 +10. 修复全局css对于ueditor有时展现会出现按钮独占一行的问题 +11. 修复在ie11下上传图片失败的问题 +12. 修复chrome 34版本下报错问题 +13. 修复ie8下插入多张远程图片之后,对话框假死问题 +14. 修复uparse,在页面中多次调用某些模块无效果问题 +15. 修复容器宽度100%时,改变窗口大小,宽度不自适应的问题 +16. 将桥接ui和编辑器的业务代码放到了新建的adapter目录,方便维护 +17. 修复拖拽改变图片大小功能和bootstrap不兼容的问题 +18. 修复在表格水平边框上拖拽,不能改变大小的问题 +19. 修复在表格标题上可以向左向下合并单元格的问题 +20. 修复grunt打包出错的问题 +21. 优化ie11下的兼容问题,主要修复了表格下的诸多问题 +22. 优化插入图片,添加原文件名作为alt属性 + +###新功能添加 +1. 添加了enableContextMenu配置开关,开关右键菜单,默认为true +2. 添加disablePInList配置,指定产出的列表中是否嵌套P标签,默认是false +3. 添加retainOnlyLabelPasted配置,指定粘贴时是否是只保留标签模式,默认是false +4. 优化了添加toolbar上各类ui的方式,方便二次开发 +6. 优化有时产出数据会带有 bookmark标签的脏数据问题 +7. 添加LocalStorage本地存储工具 +8. 优化自动排版功能,选项保存到localStorage或UserData +9. 添加右键菜单的复制粘贴的支持,非ie不提供粘贴功能 + +##1.3.6 + +###bug修复 +1. script/style标签内容,在ie下的编辑状态显示内容问题 +2. 修复预览窗口没有滚动条问题 [出自](http://www.ueditorbbs.com/forum.php?mod=viewthread&tid=28231&extra=page%3D1) +3. 修复在ie67下自动寻址的问题 +4. 修复ff下图片拖拽大小不触发contentchange问题 +5. 修复注释被删除的问题,包括在script中的[出自](http://www.ueditorbbs.com/forum.php?mod=viewthread&tid=12509&extra=page%3D1) +6. 修复在源码模式下不能使用setContent的问题,[出自](http://www.ueditorbbs.com/forum.php?mod=viewthread&tid=26910&extra=page%3D1) +7. 修复在给定宽度为100%时,ie11在拖动窗口大小时,编辑区域不随着变化的问题 +8. 修复在ie67下destroy方法调用报错 +9. 修复在插入代码模式下,ie9+以上的浏览器键盘操作(enter/tab等)错误或者失效的问题 +10. 修复不规则源码在ie下解析成文本的问题 +11. 修复p标签在ie下嵌套的问题 +12. 修复目录大纲更新事件导致失焦点的问题 +13. 针对word粘贴列表到编辑器中自动转换为list标签,由于有误命中情况,所以默认关闭该功能。提供**autoTransWordToList**配置项(默认为false),开发者可酌情配置。 +14. 添加禁止表格嵌套的开关,解决excel中粘贴到编辑器中会有冗余的嵌套表格问题,配置项**disabledTableInTable**(默认是true)。 +15. 过滤掉excel的表格粘贴到ie中时,会有bitmap的冗余占位图片问题 + +###功能更新 +1. 支持视频上传插入,多浏览器自适配播放器 + +#1.3.5 + +###新增功能 +1. asp后台的支持 +2. 添加本地自动保存功能 +3. 增加数据可视化展示功能 +4. 编辑器实例上添加isFocus,blur方法 +5. 新增在chrome下针对图片的拖拽宽高功能 +6. 新增在高端浏览器下,qq截图粘贴上传,拖拽图片到编辑上传 +7. 添加表格插入列标题功能 +8. 添加设置表格可排序功能,支持表格在预览页排序 +9. 添加生成目录功能 + +###已有功能优化 +1. ie8以上版本使用w3cRange +2. 使用grunt作为打包工具 +3. 修复了过滤规则对于script/style的内容的转码 +5. 自动寻址功能重构 +6. 修复下拉菜单高度问题 +7. 针对ie默认带有的autolink功能,添加开启禁用选项,创建时传入autolink:false就可禁用ie的autolink功能 +8. 支持插入动态地图 +9. **API文档更新** +10. 图片上传路径可配置,增加前后端路径验证 +11. 对uparse进行了拆分重构 +12. 随下载包提供各种功能说明文档 +13. 背景颜色功能重构,可以在预览页显示背景 +14. 重写了查找替换插件,解决ff下window.find方法失效的问题 + + +##1.2.6.1 +1. 查找替换支持正则表达式 +2. 修复了ie67下初始化宽高给定百分比 +3. 增加类似word中的快捷菜单,默认关闭 +4. 针对默认过滤回转换div为p标签,提供了配置开关allowDivTransToP,默认为true +5. 修复了在ie下删除分割线后光标定位的问题 +6. 提供了手动加载语言文件,避免ie下有时会因语言文件加载失败导致编辑器加载失败,提示"not import language file"的错误 +7. 优化了编辑器初始化时获得contentWindow可能不存在的情况 +8. 优化了编辑器加载自定义样式的问题,默认initialStyle传入的css样式优先级最高,其次是指定的外部css文件 +9. 工具栏支持指定位置折行,'|'表示分割符,'||'表示折行 +10. 表格操作功能升级,优化了对表格的拖拉及双击操作,并且支持IE6+浏览器。 +11. 修复编辑器在禁用状态下仍然可以拖动表格边框的bug。 +12. 修复了分割线不能删除的问题 +13. 修复了初始化内容过多时,编辑器不自动长高,要点击编辑器才会长高的问题 +14. 优化了添加字符边框的展示效果,避免出现重叠的问题 +15. 修复下拉菜单超出屏幕的bug +16. 修复table属性初始化时table布局错误的bug +17. 优化了选择工具栏上下拉菜单类型的操作命令时,选区会有闪动的问题 +18. 优化了关于swfupload的一个xss漏洞 +19. 优化了对于ie9,10的支持 + + +##1.2.6 +1. 优化了编辑器路径的设置,可以不用手动设置路径,自动识别相关路径,解决路径设置繁琐的问题 +2. 重写了过滤粘贴机制,采用黑白名单,可以书写符合自己需求的过滤规则,可以完全定义标签的属性,甚至是style上的某个属性及其数值 +3. 优化了拖拽机制,处理浮动图片拖拽不能跟指定的某行对齐 +4. 数据同步改为失去焦点就执行,可以不再使用sync方法手动同步数据 +5. 添加了字体边框 +6. 优化了backspace/del键的操作 +7. 重写了插入代码功能,插入代码编写支持tab和回车键 +8. 表格支持排序和隔行显示 +9. 改使用closure的压缩工具 +10. 优化了undo/redo操作 +11. 优化了ui界面 + + +##1.2.5 +###新增功能 +1. table整体重构 +2. table支持插入表头和标题 +3. table支持拷贝 +4. table支持任意调整宽高 +5. table支持任意前插后插行列 +6. table键盘操作仿word用户体验 +7. 添加table平均分布行、列 +8. 添加table单元格对齐方式 +9. 添加table对齐方式 +10. 添加选中部分表格,点击backspace或delete删除功能 +11. 重写表格属性、单元格属性dialog +12. 粘贴支持纯文本,源码,纯标签3个模式选择 +13. 添加计算字数的getContentLength接口 +14. 添加计算字数事件wordcount +15. 图片上传支持参数动态绑定 +16. 重写了list功能,支持一,一),(一),1),(1),——等新的列表标签 +17. 调整了list中tab键的逻辑 +18. 添加了可以限制列表的层级 +19. 全屏快捷键 ALT+Z +20. 添加了uparseplugin.js展示页加载器 + +###优化修复 +1. 优化了插入代码功能 +2. ie下默认禁用源码模式下的代码高亮 +3. 截图功能支持非ie浏览器 +4. 修正了非ie下中文输入时回退不准确的问题 +5. 改进了键盘输入时做回退的操作 + +##1.2.4 +###新增功能 +1. 官网新增API文档 +2. CSS按照UI结构进行了模块化拆分 +3. 新增皮肤切换功能,并提供一套新皮肤(可通过配置项theme来设置) +4. 新增编辑器容器拖动缩放功能,配置项为:scaleEnabled、minFrameWidth、minFrameHeight +5. 新增音乐插件 +6. 增加了源码模式下,全屏按钮可以使用 +7. 添加了UE.getEditor工厂方法 +8. 添加了针对jquery配合使用的demo +9. 添加了针对jqueryValidation配合使用的demo +10. 添加了初始化编辑器宽高配置,配置为项:initialFrameWidth、initialFrameHeight + +###优化修复 +1. 修复涂鸦路径在配置时,添加参数时请求报错 +2. 修复涂鸦opera下缩放不能使用 +3. 修复编辑器全屏功能失效问题 +4. codemirror版本升级到最新版 +5. 对opera/safari的支持进行了进一步的优化 +6. 优化了部分demo页的代码 +7. 修改原来的minFrameHeight为拖动时的最小高度 + +##1.2.3 +###新增功能 +1. 新增国际化支持 +2. 新增涂鸦功能 +3. 新增大小写功能 +4. 新增getAllHtml方法,可以将整个页面的内容打出来,可以在ueditor.configplugin.js里通过配置allHtmlEnabled,来配置在提交时是否使用getAllHtml来得到内容 +5. 新增插入模板的功能 +6. 新增背景功能 +7. 新增UE.instants全局对象,下边挂接了所有实例化的编辑器对象 +8. Editor下新增ready方法,当编辑器ready后执行传入的fn,如果编辑器已经ready好了,就马上执行fn +9. 新增topOffset配置参数,用于设置AutoFloat时工具栏距离顶部的高度 +10. 新增sourceEditorFirst配置参数,用于控制编辑器初始化时是否显示成源码模式,默认为否 +11. 新增在表格内实例化编辑器的demo +12. 新增getDialog(dialogName)接口,可以获取dialog对象。 + +###优化修复 +1. chrome下会出现alt+tab切换时,导致选区位置不对 +2. focus方法添加参数可以指向到内容末尾 +3. 完全支持opera浏览器 +4. 修复了表格中实例化编辑器时工具栏浮动错位问题 +5. 优化了后台处理文件代码,文件夹按照日期自动生成 + + +##1.2.2 +1. 编辑器不可编辑时,可以配置哪些功能可以使用,例如全屏 +2. table的边框为0时,采用虚线显示 +3. 修复firefox下插入大量代码时,代码格式显示不正确的问题 +4. 附件上传成功后显示初始文件名 +5. 自定制下载优化 +6. 当图片上传超时时,增加提示信息 +7. 修复自动排版对H1不生效的问题 +8. 修复插入超链接,超链接地址包含script标签,预览时会执行script语句的问题 + + +##1.2.1 +1. 插入表情时,按住CTRL键可连续插入多个表情 +2. 按住CTRL+Enter提交表单 +3. 增加readonly属性在ueditor.configplugin.js,编辑器实例上增加setEnabled,setDisabled方法,设置编辑区域是否可以编辑 +4. Editor上添加了getPlainTxt方法,得到编辑器的纯文本内容,但会保留段落格式 +5. 修正了initialContent赋值失效的问题,赋值顺序以标签内容为先,如果没有再看initialContent内容。 +6. 为insertHtml命令添加了过滤机制 +7. getContent将“ ”转成空格,连续2个空格则以“  ”表示 +8. 当选区在一个超链接中,就可以在弹出层中直接修改这个超链接中的文本 +9. 与后台交互的路径整体进行了调整 +10. 超链接窗口可以修改超链接显示的文字 +11. 增加插入百度应用的功能 +12. 为每个plugin的在代码中添加了配置项的容错代码,若配置项不存在,不会报错 +13. 提供后台的jsp版本 +14. 重写了ui和和编辑器的交互层,dialog改为显示时创建,整体代码减少22k +15. 修正了代码高亮跟jquery冲突的问题 +16. 改进了多个编辑器实例,使用一个name做为form提交,后台都可以取到 +17. 添加是否删除空的inlineElement节点(包括嵌套的情况)的配置项:autoClearEmptyNode +18. 修正了chrome下粘贴文本带有white-space样式, 导致编辑器内容不能折行的问题 +19. 在配置项中增加isShow设置初始化时是否显示编辑器,在编辑器实例上增加setShow,setHide方法设置编辑器的显示/隐藏 +20. 修正在jquery中实例化编辑器时与UE自带的domready冲突的问题 +21. 修正代码高亮中的行号与代码内容不能对齐的问题 +22. 新增了图片上传对话框中可自定义配置默认Tab的功能 +23. 修正.net源码包中gbk版本的乱码以及demo中使用了php路径的问题 + +##1.2.0 +1. 远程图片抓取 +2. 源码模式下css进行了简写 +3. 增强了表格的编辑功能 +4. 增加了baidu图片搜索功能,搜索图片然后直接插入到编辑器中 +5. 重写了浮动工具栏,支持混乱模式下的工具栏滚动 +6. 服务器图片在线管理 +7. word的本地图片取得寛高 +8. 附件上传 +9. 自动排版 +10. 优化了状态反射的方式,改为编辑器获得焦点才会触发,失去焦点不在触发状态查询 +11. 添加了上来就可以全屏的配置项哦去焦点之前的选区 +13. 优化了查询状态反射的性能 +14. 添加了contentchagne事件 +15. 重写了autoheight插件,去掉setInterval的方式,并且长高时不在跳动 +16. 插入视频,可以预览,并且界面加入了视屏搜索功能,并且可以插入视屏预览图到编辑器中 +17. 单元格属性编辑 +18. ie下的截屏功能 +19. 加强了table的dialog功能 +20. 改进了autolink的效果,例如: dddhttp://www.baidu.com 回车,http://www.baidu.com也可以被匹配到了 +21. 文件上传提供flash源码 +22. 修改了行间距的展示方式 +23. 段间距变为段前距和段后距 +24. 提供了.net的事例代码 +25. 首页提供了功能选择生成下载的新功能 +26. 首页文档进行了改进 +27. 分页符可以删除 + +##1.1.8 +1. 避免了重复加载源码高亮的核心代码 +2. 修复了word粘贴table过滤出错问题 +3. 修复插入地图会出现style="undefined"的问题 +4. 优化了list,多个相邻的属性一直的list会合并 +5. 可以在列表中的一行里产生多行的效果(通过回车再回退操作),类似office的效果 +6. 添加自定义样式功能 +7. 修了在chrome下右键删除td里的图片会把整个td删除的问题 +8. 改进了不同的页面调用一个editor,URL问题 +9. 增加了颜色选择器的颜色 +10. 改进了提供的后台程序的安全性 +11. 代码高亮支持折行 +12. 改进了源码编辑模式下的性能(ie下),并且支持自动换行 +13. 修改了在destroy之后会在ie下报错的问题 +14. 给初始化容器name值,那么在后台取值的键值就是name给定的值,方便多实例在一个form下提交 +15. 支持插入script/style这样的标签 +16. 修复了列表里插入浮动图片,图片不占位问题 +17. 源码模式下,去掉了pre中的  +18. 完善了_example下的demo例子 +19. base64的图片被过滤掉了 + +##1.1.7.3 +1. 支持图片相对路径模式 +2. word粘贴首行缩进问题 +3. 添加了图片边距 +4. 提供了图片等比压缩时基准边选择配置的功能 +5. dialog在某些页面不显示问题 +6. 添加了行内间距的调整 +7. 在editor实例下添加了destroy方法 +8. 全屏按钮位置不对的问题 +9. iframe.css支持相对和绝对路径 +10. 修正了focus方法在ff下失效的问题 +11. 提供了对FF3.6的支持 +12. 添加了Shift+Enter软回车功能 +10. 统一了颜色rgb转成# + +##1.1.7.2 +1. 去掉了iframe.css 改为在ueditor.configplugin.js中配置,避免css文件找不到的问题 +2. 给下拉菜单添加了默认的文字说明 +3. Ueditor.css去掉了对外部页面css的影响 +4. 修正了ie9下,编辑器的高度不随着内容缩短的问题 +5. 修正了粘贴有时会出现粘贴失败的情况 +6. 修正了在ie下点击图片会出现js错误的问题 +7. 修正了在ie下选全部替换,回退,再替换会出现替换失败的问题 +8. 增加表情本地化模式,可在config中配置是否开启本地化 +9. flash的多图片上传 +10. 支持了源码模式的下的代码高亮 +11. 增加插入代码支持的语言,改进了插入代码的展示效果 +12. 增加了字数统计 +13. 增加了对图片的排版操作 +14. 解决ie6和ie7下工具栏浮动时cpu占用过高的bug +15. 优化了文本模式粘贴的效果 +16. 优化了word粘贴的效果 +17. 在word粘贴本地图片时添加引导上传功能 +18. 更好的ie9支持 +19. 优化首行缩进效果 +20. 使用script标签代替textarea标签作为编辑器容器,简化前后端转码的配置。 +21. 优化了路径配置,修正了1.1.7.1中需要修改多处路径的问题 +22. 增加了图片操作浮层的开关配置 +23. 同时支持网络图片和本地图片的等比缩放 +24. 优化了源码模式下的代码格式 + +##1.1.6.1 +1. 去掉了iframe.css 改为在ueditor.configplugin.js中配置,避免css文件找不到的问题 +2. 给下拉菜单添加了默认的文字说明 +3. Ueditor.css去掉了对外部页面css的影响 +4. 修正了ie9下,编辑器的高度不随着内容缩短的问题 +5. 修正了粘贴有时会出现粘贴失败的情况 +6. 修正了在ie下点击图片会出现js错误的问题 +7. 修正了在ie下选全部替换,回退,再替换会出现替换失败的问题 + +##1.1.6 +1. 插入日期按钮现在使用tangram日历控件 +2. table可再编辑 +3. 粘贴excel表格的问题 +4. ff下最大化和切换源码出现光标不能跟着键盘改变和不能切出输入法的问题 +5. tab按键功能 +6. 支持多级列表 +7. 超链接可以在非ie下去除下划线 +8. 字体,字号,在editor-configplugin.js中可配置 + + + +##1.1.5 +1. 右键的策略,只显示选区内可操作的条目 +2. 禁止elementpath还会留下边框问题 +3. 字体改为了px +4. 插入分页符 +5. 整合浮动toolbar为autofloat插件 +6. 初始化的值会在第一次操作前清除,而且不在有延迟感 +7. 配置项都放到了editor-configplugin.js中 +8. 修正了多实例的问题 +9. 插入iframe功能 +10. 粘贴过滤掉内容会有提示,没过滤任何内容不会出现提示 +11. 修正代码高亮的显示效果 +12. list放弃原生改为手动实现,修正一系列原生的bug +13. 初始给个textarea会把内容取出作为初始值 +14. 去掉了源码状态下冗余的table/td/pre的style属性 +15. fixed剪切出去会带start/end +16. fixex源码模式下getContent内容不是新的 +17. table加入了设置背景颜色和边框颜色 + + + +##1.1.4 +1. 锚点 +2. 首行缩进 +3. 行间距 +4. 右键菜单 +5. 插入代码 +6. 文件上传(php版本) +7. 修复一些bug + +##1.1.3 +1. 修复chrome下粘贴的bug +2. 自动转换office粘入的有序列表和无序列表 +3. 插入图片不再等比缩放,显示原始大小 + +##1.1.2 +1. 修正IE9下autoHeight插件会一直长高的问题 +2. 增加对IE6下大写style属性的转换处理(现统一转换成小写) +3. 格式刷 +4. 上下标互斥 +5. form提交的支持 +6. 增加了focus属性,可以初始化时,设置是否编辑器获得焦点 +7. 增加了下滑线,删除线按钮,去掉了原来的下拉框 +8. autolink支持,使非ie在输入链接时能自动加上a标签 +9. google地图支持 +10. 修正了一些bug + +##1.1 +1. 修改了删除链接的机制,允许一次性删除多个超链接 +2. 改变了目录结构,方便部署(大大减少了开发代码过程中需要引入的js数量) +3. 修正部分bug + +##1.0 (2011-7-8) +1. 完成功能的开发 diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/anchor/anchor.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/anchor/anchor.html new file mode 100644 index 000000000..f277847a4 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/anchor/anchor.html @@ -0,0 +1,40 @@ + + + + + + + + +
        + +
        + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/attachment.css b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/attachment.css new file mode 100644 index 000000000..548b4284d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/attachment.css @@ -0,0 +1,681 @@ +@charset "utf-8"; +/* dialog样式 */ +.wrapper { + zoom: 1; + width: 630px; + *width: 626px; + height: 380px; + margin: 0 auto; + padding: 10px; + position: relative; + font-family: sans-serif; +} + +/*tab样式框大小*/ +.tabhead { + float:left; +} +.tabbody { + width: 100%; + height: 346px; + position: relative; + clear: both; +} + +.tabbody .panel { + position: absolute; + width: 0; + height: 0; + background: #fff; + overflow: hidden; + display: none; +} + +.tabbody .panel.focus { + width: 100%; + height: 346px; + display: block; +} + +/* 上传附件 */ +.tabbody #upload.panel { + width: 0; + height: 0; + overflow: hidden; + position: absolute !important; + clip: rect(1px, 1px, 1px, 1px); + background: #fff; + display: block; +} + +.tabbody #upload.panel.focus { + width: 100%; + height: 346px; + display: block; + clip: auto; +} + +#upload .queueList { + margin: 0; + width: 100%; + height: 100%; + position: absolute; + overflow: hidden; +} + +#upload p { + margin: 0; +} + +.element-invisible { + width: 0 !important; + height: 0 !important; + border: 0; + padding: 0; + margin: 0; + overflow: hidden; + position: absolute !important; + clip: rect(1px, 1px, 1px, 1px); +} + +#upload .placeholder { + margin: 10px; + border: 2px dashed #e6e6e6; + *border: 0px dashed #e6e6e6; + height: 172px; + padding-top: 150px; + text-align: center; + background: url(./images/image.png) center 70px no-repeat; + color: #cccccc; + font-size: 18px; + position: relative; + top:0; + *top: 10px; +} + +#upload .placeholder .webuploader-pick { + font-size: 18px; + background: #00b7ee; + border-radius: 3px; + line-height: 44px; + padding: 0 30px; + *width: 120px; + color: #fff; + display: inline-block; + margin: 0 auto 20px auto; + cursor: pointer; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); +} + +#upload .placeholder .webuploader-pick-hover { + background: #00a2d4; +} + + +#filePickerContainer { + text-align: center; +} + +#upload .placeholder .flashTip { + color: #666666; + font-size: 12px; + position: absolute; + width: 100%; + text-align: center; + bottom: 20px; +} + +#upload .placeholder .flashTip a { + color: #0785d1; + text-decoration: none; +} + +#upload .placeholder .flashTip a:hover { + text-decoration: underline; +} + +#upload .placeholder.webuploader-dnd-over { + border-color: #999999; +} + +#upload .filelist { + list-style: none; + margin: 0; + padding: 0; + overflow-x: hidden; + overflow-y: auto; + position: relative; + height: 300px; +} + +#upload .filelist:after { + content: ''; + display: block; + width: 0; + height: 0; + overflow: hidden; + clear: both; +} + +#upload .filelist li { + width: 113px; + height: 113px; + background: url(./images/bg.png); + text-align: center; + margin: 9px 0 0 9px; + *margin: 6px 0 0 6px; + position: relative; + display: block; + float: left; + overflow: hidden; + font-size: 12px; +} + +#upload .filelist li p.log { + position: relative; + top: -45px; +} + +#upload .filelist li p.title { + position: absolute; + top: 0; + left: 0; + width: 100%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + top: 5px; + text-indent: 5px; + text-align: left; +} + +#upload .filelist li p.progress { + position: absolute; + width: 100%; + bottom: 0; + left: 0; + height: 8px; + overflow: hidden; + z-index: 50; + margin: 0; + border-radius: 0; + background: none; + -webkit-box-shadow: 0 0 0; +} + +#upload .filelist li p.progress span { + display: none; + overflow: hidden; + width: 0; + height: 100%; + background: #1483d8 url(./images/progress.png) repeat-x; + + -webit-transition: width 200ms linear; + -moz-transition: width 200ms linear; + -o-transition: width 200ms linear; + -ms-transition: width 200ms linear; + transition: width 200ms linear; + + -webkit-animation: progressmove 2s linear infinite; + -moz-animation: progressmove 2s linear infinite; + -o-animation: progressmove 2s linear infinite; + -ms-animation: progressmove 2s linear infinite; + animation: progressmove 2s linear infinite; + + -webkit-transform: translateZ(0); +} + +@-webkit-keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +@-moz-keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +@keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +#upload .filelist li p.imgWrap { + position: relative; + z-index: 2; + line-height: 113px; + vertical-align: middle; + overflow: hidden; + width: 113px; + height: 113px; + + -webkit-transform-origin: 50% 50%; + -moz-transform-origin: 50% 50%; + -o-transform-origin: 50% 50%; + -ms-transform-origin: 50% 50%; + transform-origin: 50% 50%; + + -webit-transition: 200ms ease-out; + -moz-transition: 200ms ease-out; + -o-transition: 200ms ease-out; + -ms-transition: 200ms ease-out; + transition: 200ms ease-out; +} +#upload .filelist li p.imgWrap.notimage { + margin-top: 0; + width: 111px; + height: 111px; + border: 1px #eeeeee solid; +} +#upload .filelist li p.imgWrap.notimage i.file-preview { + margin-top: 15px; +} + +#upload .filelist li img { + width: 100%; +} + +#upload .filelist li p.error { + background: #f43838; + color: #fff; + position: absolute; + bottom: 0; + left: 0; + height: 28px; + line-height: 28px; + width: 100%; + z-index: 100; + display:none; +} + +#upload .filelist li .success { + display: block; + position: absolute; + left: 0; + bottom: 0; + height: 40px; + width: 100%; + z-index: 200; + background: url(./images/success.png) no-repeat right bottom; + background-image: url(./images/success.gif) \9; +} + +#upload .filelist li.filePickerBlock { + width: 113px; + height: 113px; + background: url(./images/image.png) no-repeat center 12px; + border: 1px solid #eeeeee; + border-radius: 0; +} +#upload .filelist li.filePickerBlock div.webuploader-pick { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + opacity: 0; + background: none; + font-size: 0; +} + +#upload .filelist div.file-panel { + position: absolute; + height: 0; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#80000000', endColorstr='#80000000') \0; + background: rgba(0, 0, 0, 0.5); + width: 100%; + top: 0; + left: 0; + overflow: hidden; + z-index: 300; +} + +#upload .filelist div.file-panel span { + width: 24px; + height: 24px; + display: inline; + float: right; + text-indent: -9999px; + overflow: hidden; + background: url(./images/icons.png) no-repeat; + background: url(./images/icons.gif) no-repeat \9; + margin: 5px 1px 1px; + cursor: pointer; + -webkit-tap-highlight-color: rgba(0,0,0,0); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +#upload .filelist div.file-panel span.rotateLeft { + display:none; + background-position: 0 -24px; +} + +#upload .filelist div.file-panel span.rotateLeft:hover { + background-position: 0 0; +} + +#upload .filelist div.file-panel span.rotateRight { + display:none; + background-position: -24px -24px; +} + +#upload .filelist div.file-panel span.rotateRight:hover { + background-position: -24px 0; +} + +#upload .filelist div.file-panel span.cancel { + background-position: -48px -24px; +} + +#upload .filelist div.file-panel span.cancel:hover { + background-position: -48px 0; +} + +#upload .statusBar { + height: 45px; + border-bottom: 1px solid #dadada; + margin: 0 10px; + padding: 0; + line-height: 45px; + vertical-align: middle; + position: relative; +} + +#upload .statusBar .progress { + border: 1px solid #1483d8; + width: 198px; + background: #fff; + height: 18px; + position: absolute; + top: 12px; + display: none; + text-align: center; + line-height: 18px; + color: #6dbfff; + margin: 0 10px 0 0; +} +#upload .statusBar .progress span.percentage { + width: 0; + height: 100%; + left: 0; + top: 0; + background: #1483d8; + position: absolute; +} +#upload .statusBar .progress span.text { + position: relative; + z-index: 10; +} + +#upload .statusBar .info { + display: inline-block; + font-size: 14px; + color: #666666; +} + +#upload .statusBar .btns { + position: absolute; + top: 7px; + right: 0; + line-height: 30px; +} + +#filePickerBtn { + display: inline-block; + float: left; +} +#upload .statusBar .btns .webuploader-pick, +#upload .statusBar .btns .uploadBtn, +#upload .statusBar .btns .uploadBtn.state-uploading, +#upload .statusBar .btns .uploadBtn.state-paused { + background: #ffffff; + border: 1px solid #cfcfcf; + color: #565656; + padding: 0 18px; + display: inline-block; + border-radius: 3px; + margin-left: 10px; + cursor: pointer; + font-size: 14px; + float: left; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +#upload .statusBar .btns .webuploader-pick-hover, +#upload .statusBar .btns .uploadBtn:hover, +#upload .statusBar .btns .uploadBtn.state-uploading:hover, +#upload .statusBar .btns .uploadBtn.state-paused:hover { + background: #f0f0f0; +} + +#upload .statusBar .btns .uploadBtn, +#upload .statusBar .btns .uploadBtn.state-paused{ + background: #00b7ee; + color: #fff; + border-color: transparent; +} +#upload .statusBar .btns .uploadBtn:hover, +#upload .statusBar .btns .uploadBtn.state-paused:hover{ + background: #00a2d4; +} + +#upload .statusBar .btns .uploadBtn.disabled { + pointer-events: none; + filter:alpha(opacity=60); + -moz-opacity:0.6; + -khtml-opacity: 0.6; + opacity: 0.6; +} + + + +/* 图片管理样式 */ +#online { + width: 100%; + height: 336px; + padding: 10px 0 0 0; +} +#online #fileList{ + width: 100%; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + position: relative; +} +#online ul { + display: block; + list-style: none; + margin: 0; + padding: 0; +} +#online li { + float: left; + display: block; + list-style: none; + padding: 0; + width: 113px; + height: 113px; + margin: 0 0 9px 9px; + *margin: 0 0 6px 6px; + background-color: #eee; + overflow: hidden; + cursor: pointer; + position: relative; +} +#online li.clearFloat { + float: none; + clear: both; + display: block; + width:0; + height:0; + margin: 0; + padding: 0; +} +#online li img { + cursor: pointer; +} +#online li div.file-wrapper { + cursor: pointer; + position: absolute; + display: block; + width: 111px; + height: 111px; + border: 1px solid #eee; + background: url("./images/bg.png") repeat; +} +#online li div span.file-title{ + display: block; + padding: 0 3px; + margin: 3px 0 0 0; + font-size: 12px; + height: 13px; + color: #555555; + text-align: center; + width: 107px; + white-space: nowrap; + word-break: break-all; + overflow: hidden; + text-overflow: ellipsis; +} +#online li .icon { + cursor: pointer; + width: 113px; + height: 113px; + position: absolute; + top: 0; + left: 0; + z-index: 2; + border: 0; + background-repeat: no-repeat; +} +#online li .icon:hover { + width: 107px; + height: 107px; + border: 3px solid #1094fa; +} +#online li.selected .icon { + background-image: url(images/success.png); + background-image: url(images/success.gif) \9; + background-position: 75px 75px; +} +#online li.selected .icon:hover { + width: 107px; + height: 107px; + border: 3px solid #1094fa; + background-position: 72px 72px; +} + + +/* 在线文件的文件预览图标 */ +i.file-preview { + display: block; + margin: 10px auto; + width: 70px; + height: 70px; + background-image: url("./images/file-icons.png"); + background-image: url("./images/file-icons.gif") \9; + background-position: -140px center; + background-repeat: no-repeat; +} +i.file-preview.file-type-dir{ + background-position: 0 center; +} +i.file-preview.file-type-file{ + background-position: -140px center; +} +i.file-preview.file-type-filelist{ + background-position: -210px center; +} +i.file-preview.file-type-zip, +i.file-preview.file-type-rar, +i.file-preview.file-type-7z, +i.file-preview.file-type-tar, +i.file-preview.file-type-gz, +i.file-preview.file-type-bz2{ + background-position: -280px center; +} +i.file-preview.file-type-xls, +i.file-preview.file-type-xlsx{ + background-position: -350px center; +} +i.file-preview.file-type-doc, +i.file-preview.file-type-docx{ + background-position: -420px center; +} +i.file-preview.file-type-ppt, +i.file-preview.file-type-pptx{ + background-position: -490px center; +} +i.file-preview.file-type-vsd{ + background-position: -560px center; +} +i.file-preview.file-type-pdf{ + background-position: -630px center; +} +i.file-preview.file-type-txt, +i.file-preview.file-type-md, +i.file-preview.file-type-json, +i.file-preview.file-type-htm, +i.file-preview.file-type-xml, +i.file-preview.file-type-html, +i.file-preview.file-type-js, +i.file-preview.file-type-css, +i.file-preview.file-type-php, +i.file-preview.file-type-jsp, +i.file-preview.file-type-asp{ + background-position: -700px center; +} +i.file-preview.file-type-apk{ + background-position: -770px center; +} +i.file-preview.file-type-exe{ + background-position: -840px center; +} +i.file-preview.file-type-ipa{ + background-position: -910px center; +} +i.file-preview.file-type-mp4, +i.file-preview.file-type-swf, +i.file-preview.file-type-mkv, +i.file-preview.file-type-avi, +i.file-preview.file-type-flv, +i.file-preview.file-type-mov, +i.file-preview.file-type-mpg, +i.file-preview.file-type-mpeg, +i.file-preview.file-type-ogv, +i.file-preview.file-type-webm, +i.file-preview.file-type-rm, +i.file-preview.file-type-rmvb{ + background-position: -980px center; +} +i.file-preview.file-type-ogg, +i.file-preview.file-type-wav, +i.file-preview.file-type-wmv, +i.file-preview.file-type-mid, +i.file-preview.file-type-mp3{ + background-position: -1050px center; +} +i.file-preview.file-type-jpg, +i.file-preview.file-type-jpeg, +i.file-preview.file-type-gif, +i.file-preview.file-type-bmp, +i.file-preview.file-type-png, +i.file-preview.file-type-psd{ + background-position: -140px center; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/attachment.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/attachment.html new file mode 100644 index 000000000..2ae928202 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/attachment.html @@ -0,0 +1,60 @@ + + + + + ueditor图片对话框 + + + + + + + + + + + + + + +
        +
        + + +
        +
        + +
        +
        +
        +
        + 0% + +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
          +
        • +
        +
        +
        + + +
        +
        +
        + +
        +
        + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/attachment.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/attachment.js new file mode 100644 index 000000000..ce3be633d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/attachment.js @@ -0,0 +1,754 @@ +/** + * User: Jinqn + * Date: 14-04-08 + * Time: 下午16:34 + * 上传图片对话框逻辑代码,包括tab: 远程图片/上传图片/在线图片/搜索图片 + */ + +(function () { + + var uploadFile, + onlineFile; + + window.onload = function () { + initTabs(); + initButtons(); + }; + + /* 初始化tab标签 */ + function initTabs() { + var tabs = $G('tabhead').children; + for (var i = 0; i < tabs.length; i++) { + domUtils.on(tabs[i], "click", function (e) { + var target = e.target || e.srcElement; + setTabFocus(target.getAttribute('data-content-id')); + }); + } + + setTabFocus('upload'); + } + + /* 初始化tabbody */ + function setTabFocus(id) { + if(!id) return; + var i, bodyId, tabs = $G('tabhead').children; + for (i = 0; i < tabs.length; i++) { + bodyId = tabs[i].getAttribute('data-content-id') + if (bodyId == id) { + domUtils.addClass(tabs[i], 'focus'); + domUtils.addClass($G(bodyId), 'focus'); + } else { + domUtils.removeClasses(tabs[i], 'focus'); + domUtils.removeClasses($G(bodyId), 'focus'); + } + } + switch (id) { + case 'upload': + uploadFile = uploadFile || new UploadFile('queueList'); + break; + case 'online': + onlineFile = onlineFile || new OnlineFile('fileList'); + break; + } + } + + /* 初始化onok事件 */ + function initButtons() { + + dialog.onok = function () { + var list = [], id, tabs = $G('tabhead').children; + for (var i = 0; i < tabs.length; i++) { + if (domUtils.hasClass(tabs[i], 'focus')) { + id = tabs[i].getAttribute('data-content-id'); + break; + } + } + + switch (id) { + case 'upload': + list = uploadFile.getInsertList(); + var count = uploadFile.getQueueCount(); + if (count) { + $('.info', '#queueList').html('' + '还有2个未上传文件'.replace(/[\d]/, count) + ''); + return false; + } + break; + case 'online': + list = onlineFile.getInsertList(); + break; + } + + editor.execCommand('insertfile', list); + }; + } + + + /* 上传附件 */ + function UploadFile(target) { + this.$wrap = target.constructor == String ? $('#' + target) : $(target); + this.init(); + } + UploadFile.prototype = { + init: function () { + this.fileList = []; + this.initContainer(); + this.initUploader(); + }, + initContainer: function () { + this.$queue = this.$wrap.find('.filelist'); + }, + /* 初始化容器 */ + initUploader: function () { + var _this = this, + $ = jQuery, // just in case. Make sure it's not an other libaray. + $wrap = _this.$wrap, + // 图片容器 + $queue = $wrap.find('.filelist'), + // 状态栏,包括进度和控制按钮 + $statusBar = $wrap.find('.statusBar'), + // 文件总体选择信息。 + $info = $statusBar.find('.info'), + // 上传按钮 + $upload = $wrap.find('.uploadBtn'), + // 上传按钮 + $filePickerBtn = $wrap.find('.filePickerBtn'), + // 上传按钮 + $filePickerBlock = $wrap.find('.filePickerBlock'), + // 没选择文件之前的内容。 + $placeHolder = $wrap.find('.placeholder'), + // 总体进度条 + $progress = $statusBar.find('.progress').hide(), + // 添加的文件数量 + fileCount = 0, + // 添加的文件总大小 + fileSize = 0, + // 优化retina, 在retina下这个值是2 + ratio = window.devicePixelRatio || 1, + // 缩略图大小 + thumbnailWidth = 113 * ratio, + thumbnailHeight = 113 * ratio, + // 可能有pedding, ready, uploading, confirm, done. + state = '', + // 所有文件的进度信息,key为file id + percentages = {}, + supportTransition = (function () { + var s = document.createElement('p').style, + r = 'transition' in s || + 'WebkitTransition' in s || + 'MozTransition' in s || + 'msTransition' in s || + 'OTransition' in s; + s = null; + return r; + })(), + // WebUploader实例 + uploader, + actionUrl = editor.getActionUrl(editor.getOpt('fileActionName')), + fileMaxSize = editor.getOpt('fileMaxSize'), + acceptExtensions = (editor.getOpt('fileAllowFiles') || []).join('').replace(/\./g, ',').replace(/^[,]/, '');; + + if (!WebUploader.Uploader.support()) { + $('#filePickerReady').after($('
        ').html(lang.errorNotSupport)).hide(); + return; + } else if (!editor.getOpt('fileActionName')) { + $('#filePickerReady').after($('
        ').html(lang.errorLoadConfig)).hide(); + return; + } + + uploader = _this.uploader = WebUploader.create({ + pick: { + id: '#filePickerReady', + label: lang.uploadSelectFile + }, + swf: '../../third-party/webuploader/Uploader.swf', + server: actionUrl, + fileVal: editor.getOpt('fileFieldName'), + duplicate: true, + fileSingleSizeLimit: fileMaxSize, + compress: false + }); + uploader.addButton({ + id: '#filePickerBlock' + }); + uploader.addButton({ + id: '#filePickerBtn', + label: lang.uploadAddFile + }); + + setState('pedding'); + + // 当有文件添加进来时执行,负责view的创建 + function addFile(file) { + var $li = $('
      1. ' + + '

        ' + file.name + '

        ' + + '

        ' + + '

        ' + + '
      2. '), + + $btns = $('
        ' + + '' + lang.uploadDelete + '' + + '' + lang.uploadTurnRight + '' + + '' + lang.uploadTurnLeft + '
        ').appendTo($li), + $prgress = $li.find('p.progress span'), + $wrap = $li.find('p.imgWrap'), + $info = $('

        ').hide().appendTo($li), + + showError = function (code) { + switch (code) { + case 'exceed_size': + text = lang.errorExceedSize; + break; + case 'interrupt': + text = lang.errorInterrupt; + break; + case 'http': + text = lang.errorHttp; + break; + case 'not_allow_type': + text = lang.errorFileType; + break; + default: + text = lang.errorUploadRetry; + break; + } + $info.text(text).show(); + }; + + if (file.getStatus() === 'invalid') { + showError(file.statusText); + } else { + $wrap.text(lang.uploadPreview); + if ('|png|jpg|jpeg|bmp|gif|'.indexOf('|'+file.ext.toLowerCase()+'|') == -1) { + $wrap.empty().addClass('notimage').append('' + + '' + file.name + ''); + } else { + if (browser.ie && browser.version <= 7) { + $wrap.text(lang.uploadNoPreview); + } else { + uploader.makeThumb(file, function (error, src) { + if (error || !src) { + $wrap.text(lang.uploadNoPreview); + } else { + var $img = $(''); + $wrap.empty().append($img); + $img.on('error', function () { + $wrap.text(lang.uploadNoPreview); + }); + } + }, thumbnailWidth, thumbnailHeight); + } + } + percentages[ file.id ] = [ file.size, 0 ]; + file.rotation = 0; + + /* 检查文件格式 */ + if (!file.ext || acceptExtensions.indexOf(file.ext.toLowerCase()) == -1) { + showError('not_allow_type'); + uploader.removeFile(file); + } + } + + file.on('statuschange', function (cur, prev) { + if (prev === 'progress') { + $prgress.hide().width(0); + } else if (prev === 'queued') { + $li.off('mouseenter mouseleave'); + $btns.remove(); + } + // 成功 + if (cur === 'error' || cur === 'invalid') { + showError(file.statusText); + percentages[ file.id ][ 1 ] = 1; + } else if (cur === 'interrupt') { + showError('interrupt'); + } else if (cur === 'queued') { + percentages[ file.id ][ 1 ] = 0; + } else if (cur === 'progress') { + $info.hide(); + $prgress.css('display', 'block'); + } else if (cur === 'complete') { + } + + $li.removeClass('state-' + prev).addClass('state-' + cur); + }); + + $li.on('mouseenter', function () { + $btns.stop().animate({height: 30}); + }); + $li.on('mouseleave', function () { + $btns.stop().animate({height: 0}); + }); + + $btns.on('click', 'span', function () { + var index = $(this).index(), + deg; + + switch (index) { + case 0: + uploader.removeFile(file); + return; + case 1: + file.rotation += 90; + break; + case 2: + file.rotation -= 90; + break; + } + + if (supportTransition) { + deg = 'rotate(' + file.rotation + 'deg)'; + $wrap.css({ + '-webkit-transform': deg, + '-mos-transform': deg, + '-o-transform': deg, + 'transform': deg + }); + } else { + $wrap.css('filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + (~~((file.rotation / 90) % 4 + 4) % 4) + ')'); + } + + }); + + $li.insertBefore($filePickerBlock); + } + + // 负责view的销毁 + function removeFile(file) { + var $li = $('#' + file.id); + delete percentages[ file.id ]; + updateTotalProgress(); + $li.off().find('.file-panel').off().end().remove(); + } + + function updateTotalProgress() { + var loaded = 0, + total = 0, + spans = $progress.children(), + percent; + + $.each(percentages, function (k, v) { + total += v[ 0 ]; + loaded += v[ 0 ] * v[ 1 ]; + }); + + percent = total ? loaded / total : 0; + + spans.eq(0).text(Math.round(percent * 100) + '%'); + spans.eq(1).css('width', Math.round(percent * 100) + '%'); + updateStatus(); + } + + function setState(val, files) { + + if (val != state) { + + var stats = uploader.getStats(); + + $upload.removeClass('state-' + state); + $upload.addClass('state-' + val); + + switch (val) { + + /* 未选择文件 */ + case 'pedding': + $queue.addClass('element-invisible'); + $statusBar.addClass('element-invisible'); + $placeHolder.removeClass('element-invisible'); + $progress.hide(); $info.hide(); + uploader.refresh(); + break; + + /* 可以开始上传 */ + case 'ready': + $placeHolder.addClass('element-invisible'); + $queue.removeClass('element-invisible'); + $statusBar.removeClass('element-invisible'); + $progress.hide(); $info.show(); + $upload.text(lang.uploadStart); + uploader.refresh(); + break; + + /* 上传中 */ + case 'uploading': + $progress.show(); $info.hide(); + $upload.text(lang.uploadPause); + break; + + /* 暂停上传 */ + case 'paused': + $progress.show(); $info.hide(); + $upload.text(lang.uploadContinue); + break; + + case 'confirm': + $progress.show(); $info.hide(); + $upload.text(lang.uploadStart); + + stats = uploader.getStats(); + if (stats.successNum && !stats.uploadFailNum) { + setState('finish'); + return; + } + break; + + case 'finish': + $progress.hide(); $info.show(); + if (stats.uploadFailNum) { + $upload.text(lang.uploadRetry); + } else { + $upload.text(lang.uploadStart); + } + break; + } + + state = val; + updateStatus(); + + } + + if (!_this.getQueueCount()) { + $upload.addClass('disabled') + } else { + $upload.removeClass('disabled') + } + + } + + function updateStatus() { + var text = '', stats; + + if (state === 'ready') { + text = lang.updateStatusReady.replace('_', fileCount).replace('_KB', WebUploader.formatSize(fileSize)); + } else if (state === 'confirm') { + stats = uploader.getStats(); + if (stats.uploadFailNum) { + text = lang.updateStatusConfirm.replace('_', stats.successNum).replace('_', stats.successNum); + } + } else { + stats = uploader.getStats(); + text = lang.updateStatusFinish.replace('_', fileCount). + replace('_KB', WebUploader.formatSize(fileSize)). + replace('_', stats.successNum); + + if (stats.uploadFailNum) { + text += lang.updateStatusError.replace('_', stats.uploadFailNum); + } + } + + $info.html(text); + } + + uploader.on('fileQueued', function (file) { + fileCount++; + fileSize += file.size; + + if (fileCount === 1) { + $placeHolder.addClass('element-invisible'); + $statusBar.show(); + } + + addFile(file); + }); + + uploader.on('fileDequeued', function (file) { + fileCount--; + fileSize -= file.size; + + removeFile(file); + updateTotalProgress(); + }); + + uploader.on('filesQueued', function (file) { + if (!uploader.isInProgress() && (state == 'pedding' || state == 'finish' || state == 'confirm' || state == 'ready')) { + setState('ready'); + } + updateTotalProgress(); + }); + + uploader.on('all', function (type, files) { + switch (type) { + case 'uploadFinished': + setState('confirm', files); + break; + case 'startUpload': + /* 添加额外的GET参数 */ + var params = utils.serializeParam(editor.queryCommandValue('serverparam')) || '', + url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?':'&') + 'encode=utf-8&' + params); + uploader.option('server', url); + setState('uploading', files); + break; + case 'stopUpload': + setState('paused', files); + break; + } + }); + + uploader.on('uploadBeforeSend', function (file, data, header) { + //这里可以通过data对象添加POST参数 + header['X_Requested_With'] = 'XMLHttpRequest'; + }); + + uploader.on('uploadProgress', function (file, percentage) { + var $li = $('#' + file.id), + $percent = $li.find('.progress span'); + + $percent.css('width', percentage * 100 + '%'); + percentages[ file.id ][ 1 ] = percentage; + updateTotalProgress(); + }); + + uploader.on('uploadSuccess', function (file, ret) { + var $file = $('#' + file.id); + try { + var responseText = (ret._raw || ret), + json = utils.str2json(responseText); + if (json.state == 'SUCCESS') { + _this.fileList.push(json); + $file.append(''); + } else { + $file.find('.error').text(json.state).show(); + } + } catch (e) { + $file.find('.error').text(lang.errorServerUpload).show(); + } + }); + + uploader.on('uploadError', function (file, code) { + }); + uploader.on('error', function (code, file) { + if (code == 'Q_TYPE_DENIED' || code == 'F_EXCEED_SIZE') { + addFile(file); + } + }); + uploader.on('uploadComplete', function (file, ret) { + }); + + $upload.on('click', function () { + if ($(this).hasClass('disabled')) { + return false; + } + + if (state === 'ready') { + uploader.upload(); + } else if (state === 'paused') { + uploader.upload(); + } else if (state === 'uploading') { + uploader.stop(); + } + }); + + $upload.addClass('state-' + state); + updateTotalProgress(); + }, + getQueueCount: function () { + var file, i, status, readyFile = 0, files = this.uploader.getFiles(); + for (i = 0; file = files[i++]; ) { + status = file.getStatus(); + if (status == 'queued' || status == 'uploading' || status == 'progress') readyFile++; + } + return readyFile; + }, + getInsertList: function () { + var i, link, data, list = [], + prefix = editor.getOpt('fileUrlPrefix'); + for (i = 0; i < this.fileList.length; i++) { + data = this.fileList[i]; + link = data.url; + list.push({ + title: data.original || link.substr(link.lastIndexOf('/') + 1), + url: prefix + link + }); + } + return list; + } + }; + + + /* 在线附件 */ + function OnlineFile(target) { + this.container = utils.isString(target) ? document.getElementById(target) : target; + this.init(); + } + OnlineFile.prototype = { + init: function () { + this.initContainer(); + this.initEvents(); + this.initData(); + }, + /* 初始化容器 */ + initContainer: function () { + this.container.innerHTML = ''; + this.list = document.createElement('ul'); + this.clearFloat = document.createElement('li'); + + domUtils.addClass(this.list, 'list'); + domUtils.addClass(this.clearFloat, 'clearFloat'); + + this.list.appendChild(this.clearFloat); + this.container.appendChild(this.list); + }, + /* 初始化滚动事件,滚动到地步自动拉取数据 */ + initEvents: function () { + var _this = this; + + /* 滚动拉取图片 */ + domUtils.on($G('fileList'), 'scroll', function(e){ + var panel = this; + if (panel.scrollHeight - (panel.offsetHeight + panel.scrollTop) < 10) { + _this.getFileData(); + } + }); + /* 选中图片 */ + domUtils.on(this.list, 'click', function (e) { + var target = e.target || e.srcElement, + li = target.parentNode; + + if (li.tagName.toLowerCase() == 'li') { + if (domUtils.hasClass(li, 'selected')) { + domUtils.removeClasses(li, 'selected'); + } else { + domUtils.addClass(li, 'selected'); + } + } + }); + }, + /* 初始化第一次的数据 */ + initData: function () { + + /* 拉取数据需要使用的值 */ + this.state = 0; + this.listSize = editor.getOpt('fileManagerListSize'); + this.listIndex = 0; + this.listEnd = false; + + /* 第一次拉取数据 */ + this.getFileData(); + }, + /* 向后台拉取图片列表数据 */ + getFileData: function () { + var _this = this; + + if(!_this.listEnd && !this.isLoadingData) { + this.isLoadingData = true; + ajax.request(editor.getActionUrl(editor.getOpt('fileManagerActionName')), { + timeout: 100000, + data: utils.extend({ + start: this.listIndex, + size: this.listSize + }, editor.queryCommandValue('serverparam')), + method: 'get', + onsuccess: function (r) { + try { + var json = eval('(' + r.responseText + ')'); + if (json.state == 'SUCCESS') { + _this.pushData(json.list); + _this.listIndex = parseInt(json.start) + parseInt(json.list.length); + if(_this.listIndex >= json.total) { + _this.listEnd = true; + } + _this.isLoadingData = false; + } + } catch (e) { + if(r.responseText.indexOf('ue_separate_ue') != -1) { + var list = r.responseText.split(r.responseText); + _this.pushData(list); + _this.listIndex = parseInt(list.length); + _this.listEnd = true; + _this.isLoadingData = false; + } + } + }, + onerror: function () { + _this.isLoadingData = false; + } + }); + } + }, + /* 添加图片到列表界面上 */ + pushData: function (list) { + var i, item, img, filetype, preview, icon, _this = this, + urlPrefix = editor.getOpt('fileManagerUrlPrefix'); + for (i = 0; i < list.length; i++) { + if(list[i] && list[i].url) { + item = document.createElement('li'); + icon = document.createElement('span'); + filetype = list[i].url.substr(list[i].url.lastIndexOf('.') + 1); + + if ( "png|jpg|jpeg|gif|bmp".indexOf(filetype) != -1 ) { + preview = document.createElement('img'); + domUtils.on(preview, 'load', (function(image){ + return function(){ + _this.scale(image, image.parentNode.offsetWidth, image.parentNode.offsetHeight); + }; + })(preview)); + preview.width = 113; + preview.setAttribute('src', urlPrefix + list[i].url + (list[i].url.indexOf('?') == -1 ? '?noCache=':'&noCache=') + (+new Date()).toString(36) ); + } else { + var ic = document.createElement('i'), + textSpan = document.createElement('span'); + textSpan.innerHTML = list[i].url.substr(list[i].url.lastIndexOf('/') + 1); + preview = document.createElement('div'); + preview.appendChild(ic); + preview.appendChild(textSpan); + domUtils.addClass(preview, 'file-wrapper'); + domUtils.addClass(textSpan, 'file-title'); + domUtils.addClass(ic, 'file-type-' + filetype); + domUtils.addClass(ic, 'file-preview'); + } + domUtils.addClass(icon, 'icon'); + item.setAttribute('data-url', urlPrefix + list[i].url); + if (list[i].original) { + item.setAttribute('data-title', list[i].original); + } + + item.appendChild(preview); + item.appendChild(icon); + this.list.insertBefore(item, this.clearFloat); + } + } + }, + /* 改变图片大小 */ + scale: function (img, w, h, type) { + var ow = img.width, + oh = img.height; + + if (type == 'justify') { + if (ow >= oh) { + img.width = w; + img.height = h * oh / ow; + img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px'; + } else { + img.width = w * ow / oh; + img.height = h; + img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px'; + } + } else { + if (ow >= oh) { + img.width = w * ow / oh; + img.height = h; + img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px'; + } else { + img.width = w; + img.height = h * oh / ow; + img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px'; + } + } + }, + getInsertList: function () { + var i, lis = this.list.children, list = []; + for (i = 0; i < lis.length; i++) { + if (domUtils.hasClass(lis[i], 'selected')) { + var url = lis[i].getAttribute('data-url'); + var title = lis[i].getAttribute('data-title') || url.substr(url.lastIndexOf('/') + 1); + list.push({ + title: title, + url: url + }); + } + } + return list; + } + }; + + +})(); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_chm.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_chm.gif new file mode 100644 index 000000000..9ca4fb6a2 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_chm.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_default.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_default.png new file mode 100644 index 000000000..50ac1cb16 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_default.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_doc.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_doc.gif new file mode 100644 index 000000000..206fede4e Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_doc.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_exe.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_exe.gif new file mode 100644 index 000000000..2e3b7a28e Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_exe.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_jpg.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_jpg.gif new file mode 100644 index 000000000..5d5dec026 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_jpg.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_mp3.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_mp3.gif new file mode 100644 index 000000000..b351a1f2a Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_mp3.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_mv.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_mv.gif new file mode 100644 index 000000000..26019b099 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_mv.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_pdf.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_pdf.gif new file mode 100644 index 000000000..bbb65c837 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_pdf.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_ppt.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_ppt.gif new file mode 100644 index 000000000..ccb26fbeb Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_ppt.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_psd.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_psd.gif new file mode 100644 index 000000000..2e8743a27 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_psd.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_rar.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_rar.gif new file mode 100644 index 000000000..5359e46d2 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_rar.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_txt.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_txt.gif new file mode 100644 index 000000000..e7b8dd21d Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_txt.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_xls.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_xls.gif new file mode 100644 index 000000000..e86c1c663 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/fileTypeImages/icon_xls.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/alignicon.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/alignicon.gif new file mode 100644 index 000000000..005a5ac65 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/alignicon.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/alignicon.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/alignicon.png new file mode 100644 index 000000000..4b6c444b7 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/alignicon.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/bg.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/bg.png new file mode 100644 index 000000000..580be0a01 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/bg.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/file-icons.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/file-icons.gif new file mode 100644 index 000000000..d8c02c27e Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/file-icons.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/file-icons.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/file-icons.png new file mode 100644 index 000000000..3ff82c8c4 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/file-icons.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/icons.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/icons.gif new file mode 100644 index 000000000..78459dea7 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/icons.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/icons.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/icons.png new file mode 100644 index 000000000..12e470016 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/icons.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/image.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/image.png new file mode 100644 index 000000000..19699f6a9 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/image.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/progress.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/progress.png new file mode 100644 index 000000000..717c4865c Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/progress.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/success.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/success.gif new file mode 100644 index 000000000..8d4f3112b Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/success.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/success.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/success.png new file mode 100644 index 000000000..94f968dc8 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/attachment/images/success.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/background/background.css b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/background/background.css new file mode 100644 index 000000000..5c41fe9a4 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/background/background.css @@ -0,0 +1,94 @@ +.wrapper{ width: 424px;margin: 10px auto; zoom:1;position: relative} +.tabbody{height:225px;} +.tabbody .panel { position: absolute;width:100%; height:100%;background: #fff; display: none;} +.tabbody .focus { display: block;} + +body{font-size: 12px;color: #888;overflow: hidden;} +input,label{vertical-align:middle} +.clear{clear: both;} +.pl{padding-left: 18px;padding-left: 23px\9;} + +#imageList {width: 420px;height: 215px;margin-top: 10px;overflow: hidden;overflow-y: auto;} +#imageList div {float: left;width: 100px;height: 95px;margin: 5px 10px;} +#imageList img {cursor: pointer;border: 2px solid white;} + +.bgarea{margin: 10px;padding: 5px;height: 84%;border: 1px solid #A8A297;} +.content div{margin: 10px 0 10px 5px;} +.content .iptradio{margin: 0px 5px 5px 0px;} +.txt{width:280px;} + +.wrapcolor{height: 19px;} +div.color{float: left;margin: 0;} +#colorPicker{width: 17px;height: 17px;border: 1px solid #CCC;display: inline-block;border-radius: 3px;box-shadow: 2px 2px 5px #D3D6DA;margin: 0;float: left;} +div.alignment,#custom{margin-left: 23px;margin-left: 28px\9;} +#custom input{height: 15px;min-height: 15px;width:20px;} +#repeatType{width:100px;} + + +/* 图片管理样式 */ +#imgManager { + width: 100%; + height: 225px; +} +#imgManager #imageList{ + width: 100%; + overflow-x: hidden; + overflow-y: auto; +} +#imgManager ul { + display: block; + list-style: none; + margin: 0; + padding: 0; +} +#imgManager li { + float: left; + display: block; + list-style: none; + padding: 0; + width: 113px; + height: 113px; + margin: 9px 0 0 19px; + background-color: #eee; + overflow: hidden; + cursor: pointer; + position: relative; +} +#imgManager li.clearFloat { + float: none; + clear: both; + display: block; + width:0; + height:0; + margin: 0; + padding: 0; +} +#imgManager li img { + cursor: pointer; +} +#imgManager li .icon { + cursor: pointer; + width: 113px; + height: 113px; + position: absolute; + top: 0; + left: 0; + z-index: 2; + border: 0; + background-repeat: no-repeat; +} +#imgManager li .icon:hover { + width: 107px; + height: 107px; + border: 3px solid #1094fa; +} +#imgManager li.selected .icon { + background-image: url(images/success.png); + background-position: 75px 75px; +} +#imgManager li.selected .icon:hover { + width: 107px; + height: 107px; + border: 3px solid #1094fa; + background-position: 72px 72px; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/background/background.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/background/background.html new file mode 100644 index 000000000..3cc2ac1ee --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/background/background.html @@ -0,0 +1,56 @@ + + + + + + + + +
        +
        + + +
        +
        +
        +
        + +
        +
        + + +
        +
        +
        + : +
        +
        +
        +
        +
        + +
        +
        + : +
        +
        + :x:px  y:px +
        +
        +
        + +
        +
        +
        +
        +
        +
        + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/background/background.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/background/background.js new file mode 100644 index 000000000..9a4a1315d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/background/background.js @@ -0,0 +1,376 @@ +(function () { + + var onlineImage, + backupStyle = editor.queryCommandValue('background'); + + window.onload = function () { + initTabs(); + initColorSelector(); + }; + + /* 初始化tab标签 */ + function initTabs(){ + var tabs = $G('tabHeads').children; + for (var i = 0; i < tabs.length; i++) { + domUtils.on(tabs[i], "click", function (e) { + var target = e.target || e.srcElement; + for (var j = 0; j < tabs.length; j++) { + if(tabs[j] == target){ + tabs[j].className = "focus"; + var contentId = tabs[j].getAttribute('data-content-id'); + $G(contentId).style.display = "block"; + if(contentId == 'imgManager') { + initImagePanel(); + } + }else { + tabs[j].className = ""; + $G(tabs[j].getAttribute('data-content-id')).style.display = "none"; + } + } + }); + } + } + + /* 初始化颜色设置 */ + function initColorSelector () { + var obj = editor.queryCommandValue('background'); + if (obj) { + var color = obj['background-color'], + repeat = obj['background-repeat'] || 'repeat', + image = obj['background-image'] || '', + position = obj['background-position'] || 'center center', + pos = position.split(' '), + x = parseInt(pos[0]) || 0, + y = parseInt(pos[1]) || 0; + + if(repeat == 'no-repeat' && (x || y)) repeat = 'self'; + + image = image.match(/url[\s]*\(([^\)]*)\)/); + image = image ? image[1]:''; + updateFormState('colored', color, image, repeat, x, y); + } else { + updateFormState(); + } + + var updateHandler = function () { + updateFormState(); + updateBackground(); + } + domUtils.on($G('nocolorRadio'), 'click', updateBackground); + domUtils.on($G('coloredRadio'), 'click', updateHandler); + domUtils.on($G('url'), 'keyup', function(){ + if($G('url').value && $G('alignment').style.display == "none") { + utils.each($G('repeatType').children, function(item){ + item.selected = ('repeat' == item.getAttribute('value') ? 'selected':false); + }); + } + updateHandler(); + }); + domUtils.on($G('repeatType'), 'change', updateHandler); + domUtils.on($G('x'), 'keyup', updateBackground); + domUtils.on($G('y'), 'keyup', updateBackground); + + initColorPicker(); + } + + /* 初始化颜色选择器 */ + function initColorPicker() { + var me = editor, + cp = $G("colorPicker"); + + /* 生成颜色选择器ui对象 */ + var popup = new UE.ui.Popup({ + content: new UE.ui.ColorPicker({ + noColorText: me.getLang("clearColor"), + editor: me, + onpickcolor: function (t, color) { + updateFormState('colored', color); + updateBackground(); + UE.ui.Popup.postHide(); + }, + onpicknocolor: function (t, color) { + updateFormState('colored', 'transparent'); + updateBackground(); + UE.ui.Popup.postHide(); + } + }), + editor: me, + onhide: function () { + } + }); + + /* 设置颜色选择器 */ + domUtils.on(cp, "click", function () { + popup.showAnchor(this); + }); + domUtils.on(document, 'mousedown', function (evt) { + var el = evt.target || evt.srcElement; + UE.ui.Popup.postHide(el); + }); + domUtils.on(window, 'scroll', function () { + UE.ui.Popup.postHide(); + }); + } + + /* 初始化在线图片列表 */ + function initImagePanel() { + onlineImage = onlineImage || new OnlineImage('imageList'); + } + + /* 更新背景色设置面板 */ + function updateFormState (radio, color, url, align, x, y) { + var nocolorRadio = $G('nocolorRadio'), + coloredRadio = $G('coloredRadio'); + + if(radio) { + nocolorRadio.checked = (radio == 'colored' ? false:'checked'); + coloredRadio.checked = (radio == 'colored' ? 'checked':false); + } + if(color) { + domUtils.setStyle($G("colorPicker"), "background-color", color); + } + + if(url && /^\//.test(url)) { + var a = document.createElement('a'); + a.href = url; + browser.ie && (a.href = a.href); + url = browser.ie ? a.href:(a.protocol + '//' + a.host + a.pathname + a.search + a.hash); + } + + if(url || url === '') { + $G('url').value = url; + } + if(align) { + utils.each($G('repeatType').children, function(item){ + item.selected = (align == item.getAttribute('value') ? 'selected':false); + }); + } + if(x || y) { + $G('x').value = parseInt(x) || 0; + $G('y').value = parseInt(y) || 0; + } + + $G('alignment').style.display = coloredRadio.checked && $G('url').value ? '':'none'; + $G('custom').style.display = coloredRadio.checked && $G('url').value && $G('repeatType').value == 'self' ? '':'none'; + } + + /* 更新背景颜色 */ + function updateBackground () { + if ($G('coloredRadio').checked) { + var color = domUtils.getStyle($G("colorPicker"), "background-color"), + bgimg = $G("url").value, + align = $G("repeatType").value, + backgroundObj = { + "background-repeat": "no-repeat", + "background-position": "center center" + }; + + if (color) backgroundObj["background-color"] = color; + if (bgimg) backgroundObj["background-image"] = 'url(' + bgimg + ')'; + if (align == 'self') { + backgroundObj["background-position"] = $G("x").value + "px " + $G("y").value + "px"; + } else if (align == 'repeat-x' || align == 'repeat-y' || align == 'repeat') { + backgroundObj["background-repeat"] = align; + } + + editor.execCommand('background', backgroundObj); + } else { + editor.execCommand('background', null); + } + } + + + /* 在线图片 */ + function OnlineImage(target) { + this.container = utils.isString(target) ? document.getElementById(target) : target; + this.init(); + } + OnlineImage.prototype = { + init: function () { + this.reset(); + this.initEvents(); + }, + /* 初始化容器 */ + initContainer: function () { + this.container.innerHTML = ''; + this.list = document.createElement('ul'); + this.clearFloat = document.createElement('li'); + + domUtils.addClass(this.list, 'list'); + domUtils.addClass(this.clearFloat, 'clearFloat'); + + this.list.id = 'imageListUl'; + this.list.appendChild(this.clearFloat); + this.container.appendChild(this.list); + }, + /* 初始化滚动事件,滚动到地步自动拉取数据 */ + initEvents: function () { + var _this = this; + + /* 滚动拉取图片 */ + domUtils.on($G('imageList'), 'scroll', function(e){ + var panel = this; + if (panel.scrollHeight - (panel.offsetHeight + panel.scrollTop) < 10) { + _this.getImageData(); + } + }); + /* 选中图片 */ + domUtils.on(this.container, 'click', function (e) { + var target = e.target || e.srcElement, + li = target.parentNode, + nodes = $G('imageListUl').childNodes; + + if (li.tagName.toLowerCase() == 'li') { + updateFormState('nocolor', null, ''); + for (var i = 0, node; node = nodes[i++];) { + if (node == li && !domUtils.hasClass(node, 'selected')) { + domUtils.addClass(node, 'selected'); + updateFormState('colored', null, li.firstChild.getAttribute("_src"), 'repeat'); + } else { + domUtils.removeClasses(node, 'selected'); + } + } + updateBackground(); + } + }); + }, + /* 初始化第一次的数据 */ + initData: function () { + + /* 拉取数据需要使用的值 */ + this.state = 0; + this.listSize = editor.getOpt('imageManagerListSize'); + this.listIndex = 0; + this.listEnd = false; + + /* 第一次拉取数据 */ + this.getImageData(); + }, + /* 重置界面 */ + reset: function() { + this.initContainer(); + this.initData(); + }, + /* 向后台拉取图片列表数据 */ + getImageData: function () { + var _this = this; + + if(!_this.listEnd && !this.isLoadingData) { + this.isLoadingData = true; + var url = editor.getActionUrl(editor.getOpt('imageManagerActionName')), + isJsonp = utils.isCrossDomainUrl(url); + ajax.request(url, { + 'timeout': 100000, + 'dataType': isJsonp ? 'jsonp':'', + 'data': utils.extend({ + start: this.listIndex, + size: this.listSize + }, editor.queryCommandValue('serverparam')), + 'method': 'get', + 'onsuccess': function (r) { + try { + var json = isJsonp ? r:eval('(' + r.responseText + ')'); + if (json.state == 'SUCCESS') { + _this.pushData(json.list); + _this.listIndex = parseInt(json.start) + parseInt(json.list.length); + if(_this.listIndex >= json.total) { + _this.listEnd = true; + } + _this.isLoadingData = false; + } + } catch (e) { + if(r.responseText.indexOf('ue_separate_ue') != -1) { + var list = r.responseText.split(r.responseText); + _this.pushData(list); + _this.listIndex = parseInt(list.length); + _this.listEnd = true; + _this.isLoadingData = false; + } + } + }, + 'onerror': function () { + _this.isLoadingData = false; + } + }); + } + }, + /* 添加图片到列表界面上 */ + pushData: function (list) { + var i, item, img, icon, _this = this, + urlPrefix = editor.getOpt('imageManagerUrlPrefix'); + for (i = 0; i < list.length; i++) { + if(list[i] && list[i].url) { + item = document.createElement('li'); + img = document.createElement('img'); + icon = document.createElement('span'); + + domUtils.on(img, 'load', (function(image){ + return function(){ + _this.scale(image, image.parentNode.offsetWidth, image.parentNode.offsetHeight); + } + })(img)); + img.width = 113; + img.setAttribute('src', urlPrefix + list[i].url + (list[i].url.indexOf('?') == -1 ? '?noCache=':'&noCache=') + (+new Date()).toString(36) ); + img.setAttribute('_src', urlPrefix + list[i].url); + domUtils.addClass(icon, 'icon'); + + item.appendChild(img); + item.appendChild(icon); + this.list.insertBefore(item, this.clearFloat); + } + } + }, + /* 改变图片大小 */ + scale: function (img, w, h, type) { + var ow = img.width, + oh = img.height; + + if (type == 'justify') { + if (ow >= oh) { + img.width = w; + img.height = h * oh / ow; + img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px'; + } else { + img.width = w * ow / oh; + img.height = h; + img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px'; + } + } else { + if (ow >= oh) { + img.width = w * ow / oh; + img.height = h; + img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px'; + } else { + img.width = w; + img.height = h * oh / ow; + img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px'; + } + } + }, + getInsertList: function () { + var i, lis = this.list.children, list = [], align = getAlign(); + for (i = 0; i < lis.length; i++) { + if (domUtils.hasClass(lis[i], 'selected')) { + var img = lis[i].firstChild, + src = img.getAttribute('_src'); + list.push({ + src: src, + _src: src, + floatStyle: align + }); + } + + } + return list; + } + }; + + dialog.onok = function () { + updateBackground(); + editor.fireEvent('saveScene'); + }; + dialog.oncancel = function () { + editor.execCommand('background', backupStyle); + }; + +})(); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/background/images/bg.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/background/images/bg.png new file mode 100644 index 000000000..580be0a01 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/background/images/bg.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/background/images/success.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/background/images/success.png new file mode 100644 index 000000000..94f968dc8 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/background/images/success.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/chart.config.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/chart.config.js new file mode 100644 index 000000000..678b00deb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/chart.config.js @@ -0,0 +1,65 @@ +/* + * 图表配置文件 + * */ + + +//不同类型的配置 +var typeConfig = [ + { + chart: { + type: 'line' + }, + plotOptions: { + line: { + dataLabels: { + enabled: false + }, + enableMouseTracking: true + } + } + }, { + chart: { + type: 'line' + }, + plotOptions: { + line: { + dataLabels: { + enabled: true + }, + enableMouseTracking: false + } + } + }, { + chart: { + type: 'area' + } + }, { + chart: { + type: 'bar' + } + }, { + chart: { + type: 'column' + } + }, { + chart: { + plotBackgroundColor: null, + plotBorderWidth: null, + plotShadow: false + }, + plotOptions: { + pie: { + allowPointSelect: true, + cursor: 'pointer', + dataLabels: { + enabled: true, + color: '#000000', + connectorColor: '#000000', + formatter: function() { + return ''+ this.point.name +': '+ ( Math.round( this.point.percentage*100 ) / 100 ) +' %'; + } + } + } + } + } +]; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/charts.css b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/charts.css new file mode 100644 index 000000000..ac3c76458 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/charts.css @@ -0,0 +1,165 @@ +html, body { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + overflow-x: hidden; +} + +.main { + width: 100%; + overflow: hidden; +} + +.table-view { + height: 100%; + float: left; + margin: 20px; + width: 40%; +} + +.table-view .table-container { + width: 100%; + margin-bottom: 50px; + overflow: scroll; +} + +.table-view th { + padding: 5px 10px; + background-color: #F7F7F7; +} + +.table-view td { + width: 50px; + text-align: center; + padding:0; +} + +.table-container input { + width: 40px; + padding: 5px; + border: none; + outline: none; +} + +.table-view caption { + font-size: 18px; + text-align: left; +} + +.charts-view { + /*margin-left: 49%!important;*/ + width: 50%; + margin-left: 49%; + height: 400px; +} + +.charts-container { + border-left: 1px solid #c3c3c3; +} + +.charts-format fieldset { + padding-left: 20px; + margin-bottom: 50px; +} + +.charts-format legend { + padding-left: 10px; + padding-right: 10px; +} + +.format-item-container { + padding: 20px; +} + +.format-item-container label { + display: block; + margin: 10px 0; +} + +.charts-format .data-item { + border: 1px solid black; + outline: none; + padding: 2px 3px; +} + +/* 图表类型 */ + +.charts-type { + margin-top: 50px; + height: 300px; +} + +.scroll-view { + border: 1px solid #c3c3c3; + border-left: none; + border-right: none; + overflow: hidden; +} + +.scroll-container { + margin: 20px; + width: 100%; + overflow: hidden; +} + +.scroll-bed { + width: 10000px; + _margin-top: 20px; + -webkit-transition: margin-left .5s ease; + -moz-transition: margin-left .5s ease; + transition: margin-left .5s ease; +} + +.view-box { + display: inline-block; + *display: inline; + *zoom: 1; + margin-right: 20px; + border: 2px solid white; + line-height: 0; + overflow: hidden; + cursor: pointer; +} + +.view-box img { + border: 1px solid #cecece; +} + +.view-box.selected { + border-color: #7274A7; +} + +.button-container { + margin-bottom: 20px; + text-align: center; +} + +.button-container a { + display: inline-block; + width: 100px; + height: 25px; + line-height: 25px; + border: 1px solid #c2ccd1; + margin-right: 30px; + text-decoration: none; + color: black; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; +} + +.button-container a:HOVER { + background: #fcfcfc; +} + +.button-container a:ACTIVE { + border-top-color: #c2ccd1; + box-shadow:inset 0 5px 4px -4px rgba(49, 49, 64, 0.1); +} + +.edui-charts-not-data { + height: 100px; + line-height: 100px; + text-align: center; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/charts.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/charts.html new file mode 100644 index 000000000..70e23149f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/charts.html @@ -0,0 +1,89 @@ + + + + chart + + + + + +
        +
        +

        +
        +

        +
        +
        +
        + +
        + + +
        +
        +
        +
        + +
        + + + + +
        +
        +
        + +
        + +

        +
        +
        +
        + +
        + +

        +
        +
        +
        +
        +
        +
        +
        +
        +

        +
        +
        +
        +
        +
        + + +
        +
        +
        +
        +
        + + + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/charts.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/charts.js new file mode 100644 index 000000000..37344fd12 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/charts.js @@ -0,0 +1,519 @@ +/* + * 图片转换对话框脚本 + **/ + +var tableData = [], + //编辑器页面table + editorTable = null, + chartsConfig = window.typeConfig, + resizeTimer = null, + //初始默认图表类型 + currentChartType = 0; + +window.onload = function () { + + editorTable = domUtils.findParentByTagName( editor.selection.getRange().startContainer, 'table', true); + + //未找到表格, 显示错误页面 + if ( !editorTable ) { + document.body.innerHTML = "
        未找到数据
        "; + return; + } + + //初始化图表类型选择 + initChartsTypeView(); + renderTable( editorTable ); + initEvent(); + initUserConfig( editorTable.getAttribute( "data-chart" ) ); + $( "#scrollBed .view-box:eq("+ currentChartType +")" ).trigger( "click" ); + updateViewType( currentChartType ); + + dialog.addListener( "resize", function () { + + if ( resizeTimer != null ) { + window.clearTimeout( resizeTimer ); + } + + resizeTimer = window.setTimeout( function () { + + resizeTimer = null; + + renderCharts(); + + }, 500 ); + + } ); + +}; + +function initChartsTypeView () { + + var contents = []; + + for ( var i = 0, len = chartsConfig.length; i' ); + + } + + $( "#scrollBed" ).html( contents.join( "" ) ); + +} + +//渲染table, 以便用户修改数据 +function renderTable ( table ) { + + var tableHtml = []; + + //构造数据 + for ( var i = 0, row; row = table.rows[ i ]; i++ ) { + + tableData[ i ] = []; + tableHtml[ i ] = []; + + for ( var j = 0, cell; cell = row.cells[ j ]; j++ ) { + + var value = getCellValue( cell ); + + if ( i > 0 && j > 0 ) { + value = +value; + } + + if ( i === 0 || j === 0 ) { + tableHtml[ i ].push( ''+ value +'' ); + } else { + tableHtml[ i ].push( '' ); + } + + tableData[ i ][ j ] = value; + + } + + tableHtml[ i ] = tableHtml[ i ].join( "" ); + + } + + //draw 表格 + $( "#tableContainer" ).html( ''+ tableHtml.join( "" ) +'
        ' ); + +} + +/* + * 根据表格已有的图表属性初始化当前图表属性 + */ +function initUserConfig ( config ) { + + var parsedConfig = {}; + + if ( !config ) { + return; + } + + config = config.split( ";" ); + + $.each( config, function ( index, item ) { + + item = item.split( ":" ); + parsedConfig[ item[ 0 ] ] = item[ 1 ]; + + } ); + + setUserConfig( parsedConfig ); + +} + +function initEvent () { + + var cacheValue = null, + //图表类型数 + typeViewCount = chartsConfig.length- 1, + $chartsTypeViewBox = $( '#scrollBed .view-box' ); + + $( ".charts-format" ).delegate( ".format-ctrl", "change", function () { + + renderCharts(); + + } ) + + $( ".table-view" ).delegate( ".data-item", "focus", function () { + + cacheValue = this.value; + + } ).delegate( ".data-item", "blur", function () { + + if ( this.value !== cacheValue ) { + renderCharts(); + } + + cacheValue = null; + + } ); + + $( "#buttonContainer" ).delegate( "a", "click", function (e) { + + e.preventDefault(); + + if ( this.getAttribute( "data-title" ) === 'prev' ) { + + if ( currentChartType > 0 ) { + currentChartType--; + updateViewType( currentChartType ); + } + + } else { + + if ( currentChartType < typeViewCount ) { + currentChartType++; + updateViewType( currentChartType ); + } + + } + + } ); + + //图表类型变化 + $( '#scrollBed' ).delegate( ".view-box", "click", function (e) { + + var index = $( this ).attr( "data-chart-type" ); + $chartsTypeViewBox.removeClass( "selected" ); + $( $chartsTypeViewBox[ index ] ).addClass( "selected" ); + + currentChartType = index | 0; + + //饼图, 禁用部分配置 + if ( currentChartType === chartsConfig.length - 1 ) { + + disableNotPieConfig(); + + //启用完整配置 + } else { + + enableNotPieConfig(); + + } + + renderCharts(); + + } ); + +} + +function renderCharts () { + + var data = collectData(); + + $('#chartsContainer').highcharts( $.extend( {}, chartsConfig[ currentChartType ], { + + credits: { + enabled: false + }, + exporting: { + enabled: false + }, + title: { + text: data.title, + x: -20 //center + }, + subtitle: { + text: data.subTitle, + x: -20 + }, + xAxis: { + title: { + text: data.xTitle + }, + categories: data.categories + }, + yAxis: { + title: { + text: data.yTitle + }, + plotLines: [{ + value: 0, + width: 1, + color: '#808080' + }] + }, + tooltip: { + enabled: true, + valueSuffix: data.suffix + }, + legend: { + layout: 'vertical', + align: 'right', + verticalAlign: 'middle', + borderWidth: 1 + }, + series: data.series + + } )); + +} + +function updateViewType ( index ) { + + $( "#scrollBed" ).css( 'marginLeft', -index*324+'px' ); + +} + +function collectData () { + + var form = document.forms[ 'data-form' ], + data = null; + + if ( currentChartType !== chartsConfig.length - 1 ) { + + data = getSeriesAndCategories(); + $.extend( data, getUserConfig() ); + + //饼图数据格式 + } else { + data = getSeriesForPieChart(); + data.title = form[ 'title' ].value; + data.suffix = form[ 'unit' ].value; + } + + return data; + +} + +/** + * 获取用户配置信息 + */ +function getUserConfig () { + + var form = document.forms[ 'data-form' ], + info = { + title: form[ 'title' ].value, + subTitle: form[ 'sub-title' ].value, + xTitle: form[ 'x-title' ].value, + yTitle: form[ 'y-title' ].value, + suffix: form[ 'unit' ].value, + //数据对齐方式 + tableDataFormat: getTableDataFormat (), + //饼图提示文字 + tip: $( "#tipInput" ).val() + }; + + return info; + +} + +function setUserConfig ( config ) { + + var form = document.forms[ 'data-form' ]; + + config.title && ( form[ 'title' ].value = config.title ); + config.subTitle && ( form[ 'sub-title' ].value = config.subTitle ); + config.xTitle && ( form[ 'x-title' ].value = config.xTitle ); + config.yTitle && ( form[ 'y-title' ].value = config.yTitle ); + config.suffix && ( form[ 'unit' ].value = config.suffix ); + config.dataFormat == "-1" && ( form[ 'charts-format' ][ 1 ].checked = true ); + config.tip && ( form[ 'tip' ].value = config.tip ); + currentChartType = config.chartType || 0; + +} + +function getSeriesAndCategories () { + + var form = document.forms[ 'data-form' ], + series = [], + categories = [], + tmp = [], + tableData = getTableData(); + + //反转数据 + if ( getTableDataFormat() === "-1" ) { + + for ( var i = 0, len = tableData.length; i < len; i++ ) { + + for ( var j = 0, jlen = tableData[ i ].length; j < jlen; j++ ) { + + if ( !tmp[ j ] ) { + tmp[ j ] = []; + } + + tmp[ j ][ i ] = tableData[ i ][ j ]; + + } + + } + + tableData = tmp; + + } + + categories = tableData[0].slice( 1 ); + + for ( var i = 1, data; data = tableData[ i ]; i++ ) { + + series.push( { + name: data[ 0 ], + data: data.slice( 1 ) + } ); + + } + + return { + series: series, + categories: categories + }; + +} + +/* + * 获取数据源数据对齐方式 + */ +function getTableDataFormat () { + + var form = document.forms[ 'data-form' ], + items = form['charts-format']; + + return items[ 0 ].checked ? items[ 0 ].value : items[ 1 ].value; + +} + +/* + * 禁用非饼图类型的配置项 + */ +function disableNotPieConfig() { + + updateConfigItem( 'disable' ); + +} + +/* + * 启用非饼图类型的配置项 + */ +function enableNotPieConfig() { + + updateConfigItem( 'enable' ); + +} + +function updateConfigItem ( value ) { + + var table = $( "#showTable" )[ 0 ], + isDisable = value === 'disable' ? true : false; + + //table中的input处理 + for ( var i = 2 , row; row = table.rows[ i ]; i++ ) { + + for ( var j = 1, cell; cell = row.cells[ j ]; j++ ) { + + $( "input", cell ).attr( "disabled", isDisable ); + + } + + } + + //其他项处理 + $( "input.not-pie-item" ).attr( "disabled", isDisable ); + $( "#tipInput" ).attr( "disabled", !isDisable ) + +} + +/* + * 获取饼图数据 + * 饼图的数据只取第一行的 + **/ +function getSeriesForPieChart () { + + var series = { + type: 'pie', + name: $("#tipInput").val(), + data: [] + }, + tableData = getTableData(); + + + for ( var j = 1, jlen = tableData[ 0 ].length; j < jlen; j++ ) { + + var title = tableData[ 0 ][ j ], + val = tableData[ 1 ][ j ]; + + series.data.push( [ title, val ] ); + + } + + return { + series: [ series ] + }; + +} + +function getTableData () { + + var table = document.getElementById( "showTable" ), + xCount = table.rows[0].cells.length - 1, + values = getTableInputValue(); + + for ( var i = 0, value; value = values[ i ]; i++ ) { + + tableData[ Math.floor( i / xCount ) + 1 ][ i % xCount + 1 ] = values[ i ]; + + } + + return tableData; + +} + +function getTableInputValue () { + + var table = document.getElementById( "showTable" ), + inputs = table.getElementsByTagName( "input" ), + values = []; + + for ( var i = 0, input; input = inputs[ i ]; i++ ) { + values.push( input.value | 0 ); + } + + return values; + +} + +function getCellValue ( cell ) { + + var value = utils.trim( ( cell.innerText || cell.textContent || '' ) ); + + return value.replace( new RegExp( UE.dom.domUtils.fillChar, 'g' ), '' ).replace( /^\s+|\s+$/g, '' ); + +} + + +//dialog确认事件 +dialog.onok = function () { + + //收集信息 + var form = document.forms[ 'data-form' ], + info = getUserConfig(); + + //添加图表类型 + info.chartType = currentChartType; + + //同步表格数据到编辑器 + syncTableData(); + + //执行图表命令 + editor.execCommand( 'charts', info ); + +}; + +/* + * 同步图表编辑视图的表格数据到编辑器里的原始表格 + */ +function syncTableData () { + + var tableData = getTableData(); + + for ( var i = 1, row; row = editorTable.rows[ i ]; i++ ) { + + for ( var j = 1, cell; cell = row.cells[ j ]; j++ ) { + + cell.innerHTML = tableData[ i ] [ j ]; + + } + + } + +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts0.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts0.png new file mode 100644 index 000000000..9485e5ed8 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts0.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts1.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts1.png new file mode 100644 index 000000000..b5a003928 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts1.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts2.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts2.png new file mode 100644 index 000000000..7c91a39ff Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts2.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts3.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts3.png new file mode 100644 index 000000000..a6bc29bfc Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts3.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts4.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts4.png new file mode 100644 index 000000000..742006adc Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts4.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts5.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts5.png new file mode 100644 index 000000000..c49a29609 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/charts/images/charts5.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/emotion.css b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/emotion.css new file mode 100644 index 000000000..f801105ad --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/emotion.css @@ -0,0 +1,43 @@ +.jd img{ + background:transparent url(images/jxface2.gif?v=1.1) no-repeat scroll left top; + cursor:pointer;width:35px;height:35px;display:block; +} +.pp img{ + background:transparent url(images/fface.gif?v=1.1) no-repeat scroll left top; + cursor:pointer;width:25px;height:25px;display:block; +} +.ldw img{ + background:transparent url(images/wface.gif?v=1.1) no-repeat scroll left top; + cursor:pointer;width:35px;height:35px;display:block; +} +.tsj img{ + background:transparent url(images/tface.gif?v=1.1) no-repeat scroll left top; + cursor:pointer;width:35px;height:35px;display:block; +} +.cat img{ + background:transparent url(images/cface.gif?v=1.1) no-repeat scroll left top; + cursor:pointer;width:35px;height:35px;display:block; +} +.bb img{ + background:transparent url(images/bface.gif?v=1.1) no-repeat scroll left top; + cursor:pointer;width:35px;height:35px;display:block; +} +.youa img{ + background:transparent url(images/yface.gif?v=1.1) no-repeat scroll left top; + cursor:pointer;width:35px;height:35px;display:block; +} + +.smileytable td {height: 37px;} +#tabPanel{margin-left:5px;overflow: hidden;} +#tabContent {float:left;background:#FFFFFF;} +#tabContent div{display: none;width:480px;overflow:hidden;} +#tabIconReview.show{left:17px;display:block;} +.menuFocus{background:#ACCD3C;} +.menuDefault{background:#FFFFFF;} +#tabIconReview{position:absolute;left:406px;left:398px \9;top:41px;z-index:65533;width:90px;height:76px;} +img.review{width:90px;height:76px;border:2px solid #9cb945;background:#FFFFFF;background-position:center;background-repeat:no-repeat;} + +.wrapper .tabbody{position:relative;float:left;clear:both;padding:10px;width: 95%;} +.tabbody table{width: 100%;} +.tabbody td{border:1px solid #BAC498;} +.tabbody td span{display: block;zoom:1;padding:0 4px;} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/emotion.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/emotion.html new file mode 100644 index 000000000..fca08509a --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/emotion.html @@ -0,0 +1,54 @@ + + + + + + + + + + +
        +
        + + + + + + + +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        + +
        + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/emotion.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/emotion.js new file mode 100644 index 000000000..6e158a913 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/emotion.js @@ -0,0 +1,186 @@ +window.onload = function () { + editor.setOpt({ + emotionLocalization:false + }); + + emotion.SmileyPath = editor.options.emotionLocalization === true ? 'images/' : "http://img.baidu.com/hi/"; + emotion.SmileyBox = createTabList( emotion.tabNum ); + emotion.tabExist = createArr( emotion.tabNum ); + + initImgName(); + initEvtHandler( "tabHeads" ); +}; + +function initImgName() { + for ( var pro in emotion.SmilmgName ) { + var tempName = emotion.SmilmgName[pro], + tempBox = emotion.SmileyBox[pro], + tempStr = ""; + + if ( tempBox.length ) return; + for ( var i = 1; i <= tempName[1]; i++ ) { + tempStr = tempName[0]; + if ( i < 10 ) tempStr = tempStr + '0'; + tempStr = tempStr + i + '.gif'; + tempBox.push( tempStr ); + } + } +} + +function initEvtHandler( conId ) { + var tabHeads = $G( conId ); + for ( var i = 0, j = 0; i < tabHeads.childNodes.length; i++ ) { + var tabObj = tabHeads.childNodes[i]; + if ( tabObj.nodeType == 1 ) { + domUtils.on( tabObj, "click", (function ( index ) { + return function () { + switchTab( index ); + }; + })( j ) ); + j++; + } + } + switchTab( 0 ); + $G( "tabIconReview" ).style.display = 'none'; +} + +function InsertSmiley( url, evt ) { + var obj = { + src:editor.options.emotionLocalization ? editor.options.UEDITOR_HOME_URL + "dialogs/emotion/" + url : url + }; + obj._src = obj.src; + editor.execCommand( 'insertimage', obj ); + if ( !evt.ctrlKey ) { + dialog.popup.hide(); + } +} + +function switchTab( index ) { + + autoHeight( index ); + if ( emotion.tabExist[index] == 0 ) { + emotion.tabExist[index] = 1; + createTab( 'tab' + index ); + } + //获取呈现元素句柄数组 + var tabHeads = $G( "tabHeads" ).getElementsByTagName( "span" ), + tabBodys = $G( "tabBodys" ).getElementsByTagName( "div" ), + i = 0, L = tabHeads.length; + //隐藏所有呈现元素 + for ( ; i < L; i++ ) { + tabHeads[i].className = ""; + tabBodys[i].style.display = "none"; + } + //显示对应呈现元素 + tabHeads[index].className = "focus"; + tabBodys[index].style.display = "block"; +} + +function autoHeight( index ) { + var iframe = dialog.getDom( "iframe" ), + parent = iframe.parentNode.parentNode; + switch ( index ) { + case 0: + iframe.style.height = "380px"; + parent.style.height = "392px"; + break; + case 1: + iframe.style.height = "220px"; + parent.style.height = "232px"; + break; + case 2: + iframe.style.height = "260px"; + parent.style.height = "272px"; + break; + case 3: + iframe.style.height = "300px"; + parent.style.height = "312px"; + break; + case 4: + iframe.style.height = "140px"; + parent.style.height = "152px"; + break; + case 5: + iframe.style.height = "260px"; + parent.style.height = "272px"; + break; + case 6: + iframe.style.height = "230px"; + parent.style.height = "242px"; + break; + default: + + } +} + + +function createTab( tabName ) { + var faceVersion = "?v=1.1", //版本号 + tab = $G( tabName ), //获取将要生成的Div句柄 + imagePath = emotion.SmileyPath + emotion.imageFolders[tabName], //获取显示表情和预览表情的路径 + positionLine = 11 / 2, //中间数 + iWidth = iHeight = 35, //图片长宽 + iColWidth = 3, //表格剩余空间的显示比例 + tableCss = emotion.imageCss[tabName], + cssOffset = emotion.imageCssOffset[tabName], + textHTML = [''], + i = 0, imgNum = emotion.SmileyBox[tabName].length, imgColNum = 11, faceImage, + sUrl, realUrl, posflag, offset, infor; + + for ( ; i < imgNum; ) { + textHTML.push( '' ); + for ( var j = 0; j < imgColNum; j++, i++ ) { + faceImage = emotion.SmileyBox[tabName][i]; + if ( faceImage ) { + sUrl = imagePath + faceImage + faceVersion; + realUrl = imagePath + faceImage; + posflag = j < positionLine ? 0 : 1; + offset = cssOffset * i * (-1) - 1; + infor = emotion.SmileyInfor[tabName][i]; + + textHTML.push( '' ); + } + textHTML.push( '' ); + } + textHTML.push( '
        ' ); + textHTML.push( '' ); + textHTML.push( '' ); + textHTML.push( '' ); + } else { + textHTML.push( '' ); + } + textHTML.push( '
        ' ); + textHTML = textHTML.join( "" ); + tab.innerHTML = textHTML; +} + +function over( td, srcPath, posFlag ) { + td.style.backgroundColor = "#ACCD3C"; + $G( 'faceReview' ).style.backgroundImage = "url(" + srcPath + ")"; + if ( posFlag == 1 ) $G( "tabIconReview" ).className = "show"; + $G( "tabIconReview" ).style.display = 'block'; +} + +function out( td ) { + td.style.backgroundColor = "transparent"; + var tabIconRevew = $G( "tabIconReview" ); + tabIconRevew.className = ""; + tabIconRevew.style.display = 'none'; +} + +function createTabList( tabNum ) { + var obj = {}; + for ( var i = 0; i < tabNum; i++ ) { + obj["tab" + i] = []; + } + return obj; +} + +function createArr( tabNum ) { + var arr = []; + for ( var i = 0; i < tabNum; i++ ) { + arr[i] = 0; + } + return arr; +} + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/0.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/0.gif new file mode 100644 index 000000000..6964168b9 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/0.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/bface.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/bface.gif new file mode 100644 index 000000000..14fe618ab Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/bface.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/cface.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/cface.gif new file mode 100644 index 000000000..bff947f52 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/cface.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/fface.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/fface.gif new file mode 100644 index 000000000..0d8a6afeb Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/fface.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/jxface2.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/jxface2.gif new file mode 100644 index 000000000..a959c90f7 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/jxface2.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/neweditor-tab-bg.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/neweditor-tab-bg.png new file mode 100644 index 000000000..8f398b095 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/neweditor-tab-bg.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/tface.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/tface.gif new file mode 100644 index 000000000..1354f54b9 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/tface.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/wface.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/wface.gif new file mode 100644 index 000000000..5667160d8 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/wface.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/yface.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/yface.gif new file mode 100644 index 000000000..51608be0e Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/emotion/images/yface.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/gmap/gmap.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/gmap/gmap.html new file mode 100644 index 000000000..c4cbfe69c --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/gmap/gmap.html @@ -0,0 +1,89 @@ + + + + + + + + + + +
        + + + + + + +
        +
        +
        + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/help/help.css b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/help/help.css new file mode 100644 index 000000000..4478475fd --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/help/help.css @@ -0,0 +1,7 @@ +.wrapper{width: 370px;margin: 10px auto;zoom: 1;} +.tabbody{height: 360px;} +.tabbody .panel{width:100%;height: 360px;position: absolute;background: #fff;} +.tabbody .panel h1{font-size:26px;margin: 5px 0 0 5px;} +.tabbody .panel p{font-size:12px;margin: 5px 0 0 5px;} +.tabbody table{width:90%;line-height: 20px;margin: 5px 0 0 5px;;} +.tabbody table thead{font-weight: bold;line-height: 25px;} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/help/help.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/help/help.html new file mode 100644 index 000000000..9e50060e7 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/help/help.html @@ -0,0 +1,82 @@ + + + + 帮助 + + + + + +
        +
        + + +
        +
        +
        +

        UEditor

        +

        +

        +
        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        ctrl+b
        ctrl+c
        ctrl+x
        ctrl+v
        ctrl+y
        ctrl+z
        ctrl+i
        ctrl+u
        ctrl+a
        shift+enter
        alt+z
        +
        +
        +
        + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/help/help.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/help/help.js new file mode 100644 index 000000000..9a2272e38 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/help/help.js @@ -0,0 +1,56 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 12-9-26 + * Time: 下午1:06 + * To change this template use File | Settings | File Templates. + */ +/** + * tab点击处理事件 + * @param tabHeads + * @param tabBodys + * @param obj + */ +function clickHandler( tabHeads,tabBodys,obj ) { + //head样式更改 + for ( var k = 0, len = tabHeads.length; k < len; k++ ) { + tabHeads[k].className = ""; + } + obj.className = "focus"; + //body显隐 + var tabSrc = obj.getAttribute( "tabSrc" ); + for ( var j = 0, length = tabBodys.length; j < length; j++ ) { + var body = tabBodys[j], + id = body.getAttribute( "id" ); + body.onclick = function(){ + this.style.zoom = 1; + }; + if ( id != tabSrc ) { + body.style.zIndex = 1; + } else { + body.style.zIndex = 200; + } + } + +} + +/** + * TAB切换 + * @param tabParentId tab的父节点ID或者对象本身 + */ +function switchTab( tabParentId ) { + var tabElements = $G( tabParentId ).children, + tabHeads = tabElements[0].children, + tabBodys = tabElements[1].children; + + for ( var i = 0, length = tabHeads.length; i < length; i++ ) { + var head = tabHeads[i]; + if ( head.className === "focus" )clickHandler(tabHeads,tabBodys, head ); + head.onclick = function () { + clickHandler(tabHeads,tabBodys,this); + } + } +} +switchTab("helptab"); + +document.getElementById('version').innerHTML = parent.UE.version; \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/image.css b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/image.css new file mode 100644 index 000000000..52c2295ef --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/image.css @@ -0,0 +1,894 @@ +@charset "utf-8"; +/* dialog样式 */ +.wrapper { + zoom: 1; + width: 630px; + *width: 626px; + height: 380px; + margin: 0 auto; + padding: 10px; + position: relative; + font-family: sans-serif; +} + +/*tab样式框大小*/ +.tabhead { + float:left; +} +.tabbody { + width: 100%; + height: 346px; + position: relative; + clear: both; +} + +.tabbody .panel { + position: absolute; + width: 0; + height: 0; + background: #fff; + overflow: hidden; + display: none; +} + +.tabbody .panel.focus { + width: 100%; + height: 346px; + display: block; +} + +/* 图片对齐方式 */ +.alignBar{ + float:right; + margin-top: 5px; + position: relative; +} + +.alignBar .algnLabel{ + float:left; + height: 20px; + line-height: 20px; +} + +.alignBar #alignIcon{ + zoom:1; + _display: inline; + display: inline-block; + position: relative; +} +.alignBar #alignIcon span{ + float: left; + cursor: pointer; + display: block; + width: 19px; + height: 17px; + margin-right: 3px; + margin-left: 3px; + background-image: url(./images/alignicon.jpg); +} +.alignBar #alignIcon .none-align{ + background-position: 0 -18px; +} +.alignBar #alignIcon .left-align{ + background-position: -20px -18px; +} +.alignBar #alignIcon .right-align{ + background-position: -40px -18px; +} +.alignBar #alignIcon .center-align{ + background-position: -60px -18px; +} +.alignBar #alignIcon .none-align.focus{ + background-position: 0 0; +} +.alignBar #alignIcon .left-align.focus{ + background-position: -20px 0; +} +.alignBar #alignIcon .right-align.focus{ + background-position: -40px 0; +} +.alignBar #alignIcon .center-align.focus{ + background-position: -60px 0; +} + + + + +/* 远程图片样式 */ +#remote { + z-index: 200; +} + +#remote .top{ + width: 100%; + margin-top: 25px; +} +#remote .left{ + display: block; + float: left; + width: 300px; + height:10px; +} +#remote .right{ + display: block; + float: right; + width: 300px; + height:10px; +} +#remote .row{ + margin-left: 20px; + clear: both; + height: 40px; +} + +#remote .row label{ + text-align: center; + width: 50px; + zoom:1; + _display: inline; + display:inline-block; + vertical-align: middle; +} +#remote .row label.algnLabel{ + float: left; + +} + +#remote input.text{ + width: 150px; + padding: 3px 6px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +#remote input.text:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6); +} +#remote #url{ + width: 500px; + margin-bottom: 2px; +} +#remote #width, +#remote #height{ + width: 20px; + margin-left: 2px; + margin-right: 2px; +} +#remote #border, +#remote #vhSpace, +#remote #title{ + width: 180px; + margin-right: 5px; +} +#remote #lock{ +} +#remote #lockicon{ + zoom: 1; + _display:inline; + display: inline-block; + width: 20px; + height: 20px; + background: url("../../themes/default/images/lock.gif") -13px -13px no-repeat; + vertical-align: middle; +} +#remote #preview{ + clear: both; + width: 260px; + height: 240px; + z-index: 9999; + margin-top: 10px; + background-color: #eee; + overflow: hidden; +} + +/* 上传图片 */ +.tabbody #upload.panel { + width: 0; + height: 0; + overflow: hidden; + position: absolute !important; + clip: rect(1px, 1px, 1px, 1px); + background: #fff; + display: block; +} + +.tabbody #upload.panel.focus { + width: 100%; + height: 346px; + display: block; + clip: auto; +} + +#upload .queueList { + margin: 0; + width: 100%; + height: 100%; + position: absolute; + overflow: hidden; +} + +#upload p { + margin: 0; +} + +.element-invisible { + width: 0 !important; + height: 0 !important; + border: 0; + padding: 0; + margin: 0; + overflow: hidden; + position: absolute !important; + clip: rect(1px, 1px, 1px, 1px); +} + +#upload .placeholder { + margin: 10px; + border: 2px dashed #e6e6e6; + *border: 0px dashed #e6e6e6; + height: 172px; + padding-top: 150px; + text-align: center; + background: url(./images/image.png) center 70px no-repeat; + color: #cccccc; + font-size: 18px; + position: relative; + top:0; + *top: 10px; +} + +#upload .placeholder .webuploader-pick { + font-size: 18px; + background: #00b7ee; + border-radius: 3px; + line-height: 44px; + padding: 0 30px; + *width: 120px; + color: #fff; + display: inline-block; + margin: 0 auto 20px auto; + cursor: pointer; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); +} + +#upload .placeholder .webuploader-pick-hover { + background: #00a2d4; +} + + +#filePickerContainer { + text-align: center; +} + +#upload .placeholder .flashTip { + color: #666666; + font-size: 12px; + position: absolute; + width: 100%; + text-align: center; + bottom: 20px; +} + +#upload .placeholder .flashTip a { + color: #0785d1; + text-decoration: none; +} + +#upload .placeholder .flashTip a:hover { + text-decoration: underline; +} + +#upload .placeholder.webuploader-dnd-over { + border-color: #999999; +} + +#upload .filelist { + list-style: none; + margin: 0; + padding: 0; + overflow-x: hidden; + overflow-y: auto; + position: relative; + height: 300px; +} + +#upload .filelist:after { + content: ''; + display: block; + width: 0; + height: 0; + overflow: hidden; + clear: both; + position: relative; +} + +#upload .filelist li { + width: 113px; + height: 113px; + background: url(./images/bg.png); + text-align: center; + margin: 9px 0 0 9px; + *margin: 6px 0 0 6px; + position: relative; + display: block; + float: left; + overflow: hidden; + font-size: 12px; +} + +#upload .filelist li p.log { + position: relative; + top: -45px; +} + +#upload .filelist li p.title { + position: absolute; + top: 0; + left: 0; + width: 100%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + top: 5px; + text-indent: 5px; + text-align: left; +} + +#upload .filelist li p.progress { + position: absolute; + width: 100%; + bottom: 0; + left: 0; + height: 8px; + overflow: hidden; + z-index: 50; + margin: 0; + border-radius: 0; + background: none; + -webkit-box-shadow: 0 0 0; +} + +#upload .filelist li p.progress span { + display: none; + overflow: hidden; + width: 0; + height: 100%; + background: #1483d8 url(./images/progress.png) repeat-x; + + -webit-transition: width 200ms linear; + -moz-transition: width 200ms linear; + -o-transition: width 200ms linear; + -ms-transition: width 200ms linear; + transition: width 200ms linear; + + -webkit-animation: progressmove 2s linear infinite; + -moz-animation: progressmove 2s linear infinite; + -o-animation: progressmove 2s linear infinite; + -ms-animation: progressmove 2s linear infinite; + animation: progressmove 2s linear infinite; + + -webkit-transform: translateZ(0); +} + +@-webkit-keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +@-moz-keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +@keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +#upload .filelist li p.imgWrap { + position: relative; + z-index: 2; + line-height: 113px; + vertical-align: middle; + overflow: hidden; + width: 113px; + height: 113px; + + -webkit-transform-origin: 50% 50%; + -moz-transform-origin: 50% 50%; + -o-transform-origin: 50% 50%; + -ms-transform-origin: 50% 50%; + transform-origin: 50% 50%; + + -webit-transition: 200ms ease-out; + -moz-transition: 200ms ease-out; + -o-transition: 200ms ease-out; + -ms-transition: 200ms ease-out; + transition: 200ms ease-out; +} + +#upload .filelist li img { + width: 100%; +} + +#upload .filelist li p.error { + background: #f43838; + color: #fff; + position: absolute; + bottom: 0; + left: 0; + height: 28px; + line-height: 28px; + width: 100%; + z-index: 100; + display:none; +} + +#upload .filelist li .success { + display: block; + position: absolute; + left: 0; + bottom: 0; + height: 40px; + width: 100%; + z-index: 200; + background: url(./images/success.png) no-repeat right bottom; + background: url(./images/success.gif) no-repeat right bottom \9; +} + +#upload .filelist li.filePickerBlock { + width: 113px; + height: 113px; + background: url(./images/image.png) no-repeat center 12px; + border: 1px solid #eeeeee; + border-radius: 0; +} +#upload .filelist li.filePickerBlock div.webuploader-pick { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + opacity: 0; + background: none; + font-size: 0; +} + +#upload .filelist div.file-panel { + position: absolute; + height: 0; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#80000000', endColorstr='#80000000') \0; + background: rgba(0, 0, 0, 0.5); + width: 100%; + top: 0; + left: 0; + overflow: hidden; + z-index: 300; +} + +#upload .filelist div.file-panel span { + width: 24px; + height: 24px; + display: inline; + float: right; + text-indent: -9999px; + overflow: hidden; + background: url(./images/icons.png) no-repeat; + background: url(./images/icons.gif) no-repeat \9; + margin: 5px 1px 1px; + cursor: pointer; + -webkit-tap-highlight-color: rgba(0,0,0,0); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +#upload .filelist div.file-panel span.rotateLeft { + display:none; + background-position: 0 -24px; +} + +#upload .filelist div.file-panel span.rotateLeft:hover { + background-position: 0 0; +} + +#upload .filelist div.file-panel span.rotateRight { + display:none; + background-position: -24px -24px; +} + +#upload .filelist div.file-panel span.rotateRight:hover { + background-position: -24px 0; +} + +#upload .filelist div.file-panel span.cancel { + background-position: -48px -24px; +} + +#upload .filelist div.file-panel span.cancel:hover { + background-position: -48px 0; +} + +#upload .statusBar { + height: 45px; + border-bottom: 1px solid #dadada; + margin: 0 10px; + padding: 0; + line-height: 45px; + vertical-align: middle; + position: relative; +} + +#upload .statusBar .progress { + border: 1px solid #1483d8; + width: 198px; + background: #fff; + height: 18px; + position: absolute; + top: 12px; + display: none; + text-align: center; + line-height: 18px; + color: #6dbfff; + margin: 0 10px 0 0; +} +#upload .statusBar .progress span.percentage { + width: 0; + height: 100%; + left: 0; + top: 0; + background: #1483d8; + position: absolute; +} +#upload .statusBar .progress span.text { + position: relative; + z-index: 10; +} + +#upload .statusBar .info { + display: inline-block; + font-size: 14px; + color: #666666; +} + +#upload .statusBar .btns { + position: absolute; + top: 7px; + right: 0; + line-height: 30px; +} + +#filePickerBtn { + display: inline-block; + float: left; +} +#upload .statusBar .btns .webuploader-pick, +#upload .statusBar .btns .uploadBtn, +#upload .statusBar .btns .uploadBtn.state-uploading, +#upload .statusBar .btns .uploadBtn.state-paused { + background: #ffffff; + border: 1px solid #cfcfcf; + color: #565656; + padding: 0 18px; + display: inline-block; + border-radius: 3px; + margin-left: 10px; + cursor: pointer; + font-size: 14px; + float: left; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +#upload .statusBar .btns .webuploader-pick-hover, +#upload .statusBar .btns .uploadBtn:hover, +#upload .statusBar .btns .uploadBtn.state-uploading:hover, +#upload .statusBar .btns .uploadBtn.state-paused:hover { + background: #f0f0f0; +} + +#upload .statusBar .btns .uploadBtn, +#upload .statusBar .btns .uploadBtn.state-paused{ + background: #00b7ee; + color: #fff; + border-color: transparent; +} +#upload .statusBar .btns .uploadBtn:hover, +#upload .statusBar .btns .uploadBtn.state-paused:hover{ + background: #00a2d4; +} + +#upload .statusBar .btns .uploadBtn.disabled { + pointer-events: none; + filter:alpha(opacity=60); + -moz-opacity:0.6; + -khtml-opacity: 0.6; + opacity: 0.6; +} + + + +/* 图片管理样式 */ +#online { + width: 100%; + height: 336px; + padding: 10px 0 0 0; +} +#online #imageList{ + width: 100%; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + position: relative; +} +#online ul { + display: block; + list-style: none; + margin: 0; + padding: 0; +} +#online li { + float: left; + display: block; + list-style: none; + padding: 0; + width: 113px; + height: 113px; + margin: 0 0 9px 9px; + *margin: 0 0 6px 6px; + background-color: #eee; + overflow: hidden; + cursor: pointer; + position: relative; +} +#online li.clearFloat { + float: none; + clear: both; + display: block; + width:0; + height:0; + margin: 0; + padding: 0; +} +#online li img { + cursor: pointer; +} +#online li .icon { + cursor: pointer; + width: 113px; + height: 113px; + position: absolute; + top: 0; + left: 0; + z-index: 2; + border: 0; + background-repeat: no-repeat; +} +#online li .icon:hover { + width: 107px; + height: 107px; + border: 3px solid #1094fa; +} +#online li.selected .icon { + background-image: url(images/success.png); + background-image: url(images/success.gif)\9; + background-position: 75px 75px; +} +#online li.selected .icon:hover { + width: 107px; + height: 107px; + border: 3px solid #1094fa; + background-position: 72px 72px; +} + + +/* 图片搜索样式 */ +#search .searchBar { + width: 100%; + height: 30px; + margin: 10px 0 5px 0; + padding: 0; +} + +#search input.text{ + width: 150px; + padding: 3px 6px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +#search input.text:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6); +} +#search input.searchTxt { + margin-left:5px; + padding-left: 5px; + background: #FFF; + width: 300px; + *width: 260px; + height: 21px; + line-height: 21px; + float: left; + dislay: block; +} + +#search .searchType { + width: 65px; + height: 28px; + padding:0; + line-height: 28px; + border: 1px solid #d7d7d7; + border-radius: 0; + vertical-align: top; + margin-left: 5px; + float: left; + dislay: block; +} + +#search #searchBtn, +#search #searchReset { + display: inline-block; + margin-bottom: 0; + margin-right: 5px; + padding: 4px 10px; + font-weight: 400; + text-align: center; + vertical-align: middle; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + font-size: 14px; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + vertical-align: top; + float: right; +} + +#search #searchBtn { + color: white; + border-color: #285e8e; + background-color: #3b97d7; +} +#search #searchReset { + color: #333; + border-color: #ccc; + background-color: #fff; +} +#search #searchBtn:hover { + background-color: #3276b1; +} +#search #searchReset:hover { + background-color: #eee; +} + +#search .msg { + margin-left: 5px; +} + +#search .searchList{ + width: 100%; + height: 300px; + overflow: hidden; + clear: both; +} +#search .searchList ul{ + margin:0; + padding:0; + list-style:none; + clear: both; + width: 100%; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + zoom: 1; + position: relative; +} + +#search .searchList li { + list-style:none; + float: left; + display: block; + width: 115px; + margin: 5px 10px 5px 20px; + *margin: 5px 10px 5px 15px; + padding:0; + font-size: 12px; + box-shadow: 0 1px 3px rgba(0, 0, 0, .3); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, .3); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, .3); + position: relative; + vertical-align: top; + text-align: center; + overflow: hidden; + cursor: pointer; + filter: alpha(Opacity=100); + -moz-opacity: 1; + opacity: 1; + border: 2px solid #eee; +} + +#search .searchList li.selected { + filter: alpha(Opacity=40); + -moz-opacity: 0.4; + opacity: 0.4; + border: 2px solid #00a0e9; +} + +#search .searchList li p { + background-color: #eee; + margin: 0; + padding: 0; + position: relative; + width:100%; + height:115px; + overflow: hidden; +} + +#search .searchList li p img { + cursor: pointer; + border: 0; +} + +#search .searchList li a { + color: #999; + border-top: 1px solid #F2F2F2; + background: #FAFAFA; + text-align: center; + display: block; + padding: 0 5px; + width: 105px; + height:32px; + line-height:32px; + white-space:nowrap; + text-overflow:ellipsis; + text-decoration: none; + overflow: hidden; + word-break: break-all; +} + +#search .searchList a:hover { + text-decoration: underline; + color: #333; +} +#search .searchList .clearFloat{ + clear: both; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/image.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/image.html new file mode 100644 index 000000000..08ca022dd --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/image.html @@ -0,0 +1,120 @@ + + + + + ueditor图片对话框 + + + + + + + + + + + + + + +
        +
        + + + + +
        +
        + + + + + + + + +
        +
        + + +
        +
        +
        + + +
        +
        +
        +
        + +   px +   px + +
        +
        + + px +
        +
        + + px +
        +
        + + +
        +
        +
        +
        + + +
        +
        +
        +
        + 0% + +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
          +
        • +
        +
        +
        + + +
        +
        +
        + + + + +
        +
        + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/image.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/image.js new file mode 100644 index 000000000..dee16bb80 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/image.js @@ -0,0 +1,1142 @@ +/** + * User: Jinqn + * Date: 14-04-08 + * Time: 下午16:34 + * 上传图片对话框逻辑代码,包括tab: 远程图片/上传图片/在线图片/搜索图片 + */ + +(function () { + + var remoteImage, + uploadImage, + onlineImage, + searchImage; + + window.onload = function () { + initTabs(); + initAlign(); + initButtons(); + }; + + /* 初始化tab标签 */ + function initTabs() { + var tabs = $G('tabhead').children; + for (var i = 0; i < tabs.length; i++) { + domUtils.on(tabs[i], "click", function (e) { + var target = e.target || e.srcElement; + setTabFocus(target.getAttribute('data-content-id')); + }); + } + + var img = editor.selection.getRange().getClosedNode(); + if (img && img.tagName && img.tagName.toLowerCase() == 'img') { + setTabFocus('remote'); + } else { + setTabFocus('upload'); + } + } + + /* 初始化tabbody */ + function setTabFocus(id) { + if(!id) return; + var i, bodyId, tabs = $G('tabhead').children; + for (i = 0; i < tabs.length; i++) { + bodyId = tabs[i].getAttribute('data-content-id'); + if (bodyId == id) { + domUtils.addClass(tabs[i], 'focus'); + domUtils.addClass($G(bodyId), 'focus'); + } else { + domUtils.removeClasses(tabs[i], 'focus'); + domUtils.removeClasses($G(bodyId), 'focus'); + } + } + switch (id) { + case 'remote': + remoteImage = remoteImage || new RemoteImage(); + break; + case 'upload': + setAlign(editor.getOpt('imageInsertAlign')); + uploadImage = uploadImage || new UploadImage('queueList'); + break; + case 'online': + setAlign(editor.getOpt('imageManagerInsertAlign')); + onlineImage = onlineImage || new OnlineImage('imageList'); + onlineImage.reset(); + break; + case 'search': + setAlign(editor.getOpt('imageManagerInsertAlign')); + searchImage = searchImage || new SearchImage(); + break; + } + } + + /* 初始化onok事件 */ + function initButtons() { + + dialog.onok = function () { + var remote = false, list = [], id, tabs = $G('tabhead').children; + for (var i = 0; i < tabs.length; i++) { + if (domUtils.hasClass(tabs[i], 'focus')) { + id = tabs[i].getAttribute('data-content-id'); + break; + } + } + + switch (id) { + case 'remote': + list = remoteImage.getInsertList(); + break; + case 'upload': + list = uploadImage.getInsertList(); + var count = uploadImage.getQueueCount(); + if (count) { + $('.info', '#queueList').html('' + '还有2个未上传文件'.replace(/[\d]/, count) + ''); + return false; + } + break; + case 'online': + list = onlineImage.getInsertList(); + break; + case 'search': + list = searchImage.getInsertList(); + remote = true; + break; + } + + if(list) { + editor.execCommand('insertimage', list); + remote && editor.fireEvent("catchRemoteImage"); + } + }; + } + + + /* 初始化对其方式的点击事件 */ + function initAlign(){ + /* 点击align图标 */ + domUtils.on($G("alignIcon"), 'click', function(e){ + var target = e.target || e.srcElement; + if(target.className && target.className.indexOf('-align') != -1) { + setAlign(target.getAttribute('data-align')); + } + }); + } + + /* 设置对齐方式 */ + function setAlign(align){ + align = align || 'none'; + var aligns = $G("alignIcon").children; + for(i = 0; i < aligns.length; i++){ + if(aligns[i].getAttribute('data-align') == align) { + domUtils.addClass(aligns[i], 'focus'); + $G("align").value = aligns[i].getAttribute('data-align'); + } else { + domUtils.removeClasses(aligns[i], 'focus'); + } + } + } + /* 获取对齐方式 */ + function getAlign(){ + var align = $G("align").value || 'none'; + return align == 'none' ? '':align; + } + + + /* 在线图片 */ + function RemoteImage(target) { + this.container = utils.isString(target) ? document.getElementById(target) : target; + this.init(); + } + RemoteImage.prototype = { + init: function () { + this.initContainer(); + this.initEvents(); + }, + initContainer: function () { + this.dom = { + 'url': $G('url'), + 'width': $G('width'), + 'height': $G('height'), + 'border': $G('border'), + 'vhSpace': $G('vhSpace'), + 'title': $G('title'), + 'align': $G('align') + }; + var img = editor.selection.getRange().getClosedNode(); + if (img) { + this.setImage(img); + } + }, + initEvents: function () { + var _this = this, + locker = $G('lock'); + + /* 改变url */ + domUtils.on($G("url"), 'keyup', updatePreview); + domUtils.on($G("border"), 'keyup', updatePreview); + domUtils.on($G("title"), 'keyup', updatePreview); + + domUtils.on($G("width"), 'keyup', function(){ + updatePreview(); + if(locker.checked) { + var proportion =locker.getAttribute('data-proportion'); + $G('height').value = Math.round(this.value / proportion); + } else { + _this.updateLocker(); + } + }); + domUtils.on($G("height"), 'keyup', function(){ + updatePreview(); + if(locker.checked) { + var proportion =locker.getAttribute('data-proportion'); + $G('width').value = Math.round(this.value * proportion); + } else { + _this.updateLocker(); + } + }); + domUtils.on($G("lock"), 'change', function(){ + var proportion = parseInt($G("width").value) /parseInt($G("height").value); + locker.setAttribute('data-proportion', proportion); + }); + + function updatePreview(){ + _this.setPreview(); + } + }, + updateLocker: function(){ + var width = $G('width').value, + height = $G('height').value, + locker = $G('lock'); + if(width && height && width == parseInt(width) && height == parseInt(height)) { + locker.disabled = false; + locker.title = ''; + } else { + locker.checked = false; + locker.disabled = 'disabled'; + locker.title = lang.remoteLockError; + } + }, + setImage: function(img){ + /* 不是正常的图片 */ + if (!img.tagName || img.tagName.toLowerCase() != 'img' && !img.getAttribute("src") || !img.src) return; + + var wordImgFlag = img.getAttribute("word_img"), + src = wordImgFlag ? wordImgFlag.replace("&", "&") : (img.getAttribute('_src') || img.getAttribute("src", 2).replace("&", "&")), + align = editor.queryCommandValue("imageFloat"); + + /* 防止onchange事件循环调用 */ + if (src !== $G("url").value) $G("url").value = src; + if(src) { + /* 设置表单内容 */ + $G("width").value = img.width || ''; + $G("height").value = img.height || ''; + $G("border").value = img.getAttribute("border") || '0'; + $G("vhSpace").value = img.getAttribute("vspace") || '0'; + $G("title").value = img.title || img.alt || ''; + setAlign(align); + this.setPreview(); + this.updateLocker(); + } + }, + getData: function(){ + var data = {}; + for(var k in this.dom){ + data[k] = this.dom[k].value; + } + return data; + }, + setPreview: function(){ + var url = $G('url').value, + ow = parseInt($G('width').value, 10) || 0, + oh = parseInt($G('height').value, 10) || 0, + border = parseInt($G('border').value, 10) || 0, + title = $G('title').value, + preview = $G('preview'), + width, + height; + + url = utils.unhtmlForUrl(url); + title = utils.unhtml(title); + + width = ((!ow || !oh) ? preview.offsetWidth:Math.min(ow, preview.offsetWidth)); + width = width+(border*2) > preview.offsetWidth ? width:(preview.offsetWidth - (border*2)); + height = (!ow || !oh) ? '':width*oh/ow; + + if(url) { + preview.innerHTML = ''; + } + }, + getInsertList: function () { + var data = this.getData(); + if(data['url']) { + return [{ + src: data['url'], + _src: data['url'], + width: data['width'] || '', + height: data['height'] || '', + border: data['border'] || '', + floatStyle: data['align'] || '', + vspace: data['vhSpace'] || '', + title: data['title'] || '', + alt: data['title'] || '', + style: "width:" + data['width'] + "px;height:" + data['height'] + "px;" + }]; + } else { + return []; + } + } + }; + + + + /* 上传图片 */ + function UploadImage(target) { + this.$wrap = target.constructor == String ? $('#' + target) : $(target); + this.init(); + } + UploadImage.prototype = { + init: function () { + this.imageList = []; + this.initContainer(); + this.initUploader(); + }, + initContainer: function () { + this.$queue = this.$wrap.find('.filelist'); + }, + /* 初始化容器 */ + initUploader: function () { + var _this = this, + $ = jQuery, // just in case. Make sure it's not an other libaray. + $wrap = _this.$wrap, + // 图片容器 + $queue = $wrap.find('.filelist'), + // 状态栏,包括进度和控制按钮 + $statusBar = $wrap.find('.statusBar'), + // 文件总体选择信息。 + $info = $statusBar.find('.info'), + // 上传按钮 + $upload = $wrap.find('.uploadBtn'), + // 上传按钮 + $filePickerBtn = $wrap.find('.filePickerBtn'), + // 上传按钮 + $filePickerBlock = $wrap.find('.filePickerBlock'), + // 没选择文件之前的内容。 + $placeHolder = $wrap.find('.placeholder'), + // 总体进度条 + $progress = $statusBar.find('.progress').hide(), + // 添加的文件数量 + fileCount = 0, + // 添加的文件总大小 + fileSize = 0, + // 优化retina, 在retina下这个值是2 + ratio = window.devicePixelRatio || 1, + // 缩略图大小 + thumbnailWidth = 113 * ratio, + thumbnailHeight = 113 * ratio, + // 可能有pedding, ready, uploading, confirm, done. + state = '', + // 所有文件的进度信息,key为file id + percentages = {}, + supportTransition = (function () { + var s = document.createElement('p').style, + r = 'transition' in s || + 'WebkitTransition' in s || + 'MozTransition' in s || + 'msTransition' in s || + 'OTransition' in s; + s = null; + return r; + })(), + // WebUploader实例 + uploader, + actionUrl = editor.getActionUrl(editor.getOpt('imageActionName')), + acceptExtensions = (editor.getOpt('imageAllowFiles') || []).join('').replace(/\./g, ',').replace(/^[,]/, ''), + imageMaxSize = editor.getOpt('imageMaxSize'), + imageCompressBorder = editor.getOpt('imageCompressBorder'); + + if (!WebUploader.Uploader.support()) { + $('#filePickerReady').after($('
        ').html(lang.errorNotSupport)).hide(); + return; + } else if (!editor.getOpt('imageActionName')) { + $('#filePickerReady').after($('
        ').html(lang.errorLoadConfig)).hide(); + return; + } + + uploader = _this.uploader = WebUploader.create({ + pick: { + id: '#filePickerReady', + label: lang.uploadSelectFile + }, + accept: { + title: 'Images', + extensions: acceptExtensions, + mimeTypes: 'image/*' + }, + swf: '../../third-party/webuploader/Uploader.swf', + server: actionUrl, + fileVal: editor.getOpt('imageFieldName'), + duplicate: true, + fileSingleSizeLimit: imageMaxSize, // 默认 2 M + compress: editor.getOpt('imageCompressEnable') ? { + width: imageCompressBorder, + height: imageCompressBorder, + // 图片质量,只有type为`image/jpeg`的时候才有效。 + quality: 90, + // 是否允许放大,如果想要生成小图的时候不失真,此选项应该设置为false. + allowMagnify: false, + // 是否允许裁剪。 + crop: false, + // 是否保留头部meta信息。 + preserveHeaders: true + }:false + }); + uploader.addButton({ + id: '#filePickerBlock' + }); + uploader.addButton({ + id: '#filePickerBtn', + label: lang.uploadAddFile + }); + + setState('pedding'); + + // 当有文件添加进来时执行,负责view的创建 + function addFile(file) { + var $li = $('
      3. ' + + '

        ' + file.name + '

        ' + + '

        ' + + '

        ' + + '
      4. '), + + $btns = $('
        ' + + '' + lang.uploadDelete + '' + + '' + lang.uploadTurnRight + '' + + '' + lang.uploadTurnLeft + '
        ').appendTo($li), + $prgress = $li.find('p.progress span'), + $wrap = $li.find('p.imgWrap'), + $info = $('

        ').hide().appendTo($li), + + showError = function (code) { + switch (code) { + case 'exceed_size': + text = lang.errorExceedSize; + break; + case 'interrupt': + text = lang.errorInterrupt; + break; + case 'http': + text = lang.errorHttp; + break; + case 'not_allow_type': + text = lang.errorFileType; + break; + default: + text = lang.errorUploadRetry; + break; + } + $info.text(text).show(); + }; + + if (file.getStatus() === 'invalid') { + showError(file.statusText); + } else { + $wrap.text(lang.uploadPreview); + if (browser.ie && browser.version <= 7) { + $wrap.text(lang.uploadNoPreview); + } else { + uploader.makeThumb(file, function (error, src) { + if (error || !src) { + $wrap.text(lang.uploadNoPreview); + } else { + var $img = $(''); + $wrap.empty().append($img); + $img.on('error', function () { + $wrap.text(lang.uploadNoPreview); + }); + } + }, thumbnailWidth, thumbnailHeight); + } + percentages[ file.id ] = [ file.size, 0 ]; + file.rotation = 0; + + /* 检查文件格式 */ + if (!file.ext || acceptExtensions.indexOf(file.ext.toLowerCase()) == -1) { + showError('not_allow_type'); + uploader.removeFile(file); + } + } + + file.on('statuschange', function (cur, prev) { + if (prev === 'progress') { + $prgress.hide().width(0); + } else if (prev === 'queued') { + $li.off('mouseenter mouseleave'); + $btns.remove(); + } + // 成功 + if (cur === 'error' || cur === 'invalid') { + showError(file.statusText); + percentages[ file.id ][ 1 ] = 1; + } else if (cur === 'interrupt') { + showError('interrupt'); + } else if (cur === 'queued') { + percentages[ file.id ][ 1 ] = 0; + } else if (cur === 'progress') { + $info.hide(); + $prgress.css('display', 'block'); + } else if (cur === 'complete') { + } + + $li.removeClass('state-' + prev).addClass('state-' + cur); + }); + + $li.on('mouseenter', function () { + $btns.stop().animate({height: 30}); + }); + $li.on('mouseleave', function () { + $btns.stop().animate({height: 0}); + }); + + $btns.on('click', 'span', function () { + var index = $(this).index(), + deg; + + switch (index) { + case 0: + uploader.removeFile(file); + return; + case 1: + file.rotation += 90; + break; + case 2: + file.rotation -= 90; + break; + } + + if (supportTransition) { + deg = 'rotate(' + file.rotation + 'deg)'; + $wrap.css({ + '-webkit-transform': deg, + '-mos-transform': deg, + '-o-transform': deg, + 'transform': deg + }); + } else { + $wrap.css('filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + (~~((file.rotation / 90) % 4 + 4) % 4) + ')'); + } + + }); + + $li.insertBefore($filePickerBlock); + } + + // 负责view的销毁 + function removeFile(file) { + var $li = $('#' + file.id); + delete percentages[ file.id ]; + updateTotalProgress(); + $li.off().find('.file-panel').off().end().remove(); + } + + function updateTotalProgress() { + var loaded = 0, + total = 0, + spans = $progress.children(), + percent; + + $.each(percentages, function (k, v) { + total += v[ 0 ]; + loaded += v[ 0 ] * v[ 1 ]; + }); + + percent = total ? loaded / total : 0; + + spans.eq(0).text(Math.round(percent * 100) + '%'); + spans.eq(1).css('width', Math.round(percent * 100) + '%'); + updateStatus(); + } + + function setState(val, files) { + + if (val != state) { + + var stats = uploader.getStats(); + + $upload.removeClass('state-' + state); + $upload.addClass('state-' + val); + + switch (val) { + + /* 未选择文件 */ + case 'pedding': + $queue.addClass('element-invisible'); + $statusBar.addClass('element-invisible'); + $placeHolder.removeClass('element-invisible'); + $progress.hide(); $info.hide(); + uploader.refresh(); + break; + + /* 可以开始上传 */ + case 'ready': + $placeHolder.addClass('element-invisible'); + $queue.removeClass('element-invisible'); + $statusBar.removeClass('element-invisible'); + $progress.hide(); $info.show(); + $upload.text(lang.uploadStart); + uploader.refresh(); + break; + + /* 上传中 */ + case 'uploading': + $progress.show(); $info.hide(); + $upload.text(lang.uploadPause); + break; + + /* 暂停上传 */ + case 'paused': + $progress.show(); $info.hide(); + $upload.text(lang.uploadContinue); + break; + + case 'confirm': + $progress.show(); $info.hide(); + $upload.text(lang.uploadStart); + + stats = uploader.getStats(); + if (stats.successNum && !stats.uploadFailNum) { + setState('finish'); + return; + } + break; + + case 'finish': + $progress.hide(); $info.show(); + if (stats.uploadFailNum) { + $upload.text(lang.uploadRetry); + } else { + $upload.text(lang.uploadStart); + } + break; + } + + state = val; + updateStatus(); + + } + + if (!_this.getQueueCount()) { + $upload.addClass('disabled') + } else { + $upload.removeClass('disabled') + } + + } + + function updateStatus() { + var text = '', stats; + + if (state === 'ready') { + text = lang.updateStatusReady.replace('_', fileCount).replace('_KB', WebUploader.formatSize(fileSize)); + } else if (state === 'confirm') { + stats = uploader.getStats(); + if (stats.uploadFailNum) { + text = lang.updateStatusConfirm.replace('_', stats.successNum).replace('_', stats.successNum); + } + } else { + stats = uploader.getStats(); + text = lang.updateStatusFinish.replace('_', fileCount). + replace('_KB', WebUploader.formatSize(fileSize)). + replace('_', stats.successNum); + + if (stats.uploadFailNum) { + text += lang.updateStatusError.replace('_', stats.uploadFailNum); + } + } + + $info.html(text); + } + + uploader.on('fileQueued', function (file) { + fileCount++; + fileSize += file.size; + + if (fileCount === 1) { + $placeHolder.addClass('element-invisible'); + $statusBar.show(); + } + + addFile(file); + }); + + uploader.on('fileDequeued', function (file) { + fileCount--; + fileSize -= file.size; + + removeFile(file); + updateTotalProgress(); + }); + + uploader.on('filesQueued', function (file) { + if (!uploader.isInProgress() && (state == 'pedding' || state == 'finish' || state == 'confirm' || state == 'ready')) { + setState('ready'); + } + updateTotalProgress(); + }); + + uploader.on('all', function (type, files) { + switch (type) { + case 'uploadFinished': + setState('confirm', files); + break; + case 'startUpload': + /* 添加额外的GET参数 */ + var params = utils.serializeParam(editor.queryCommandValue('serverparam')) || '', + url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?':'&') + 'encode=utf-8&' + params); + uploader.option('server', url); + setState('uploading', files); + break; + case 'stopUpload': + setState('paused', files); + break; + } + }); + + uploader.on('uploadBeforeSend', function (file, data, header) { + //这里可以通过data对象添加POST参数 + header['X_Requested_With'] = 'XMLHttpRequest'; + }); + + uploader.on('uploadProgress', function (file, percentage) { + var $li = $('#' + file.id), + $percent = $li.find('.progress span'); + + $percent.css('width', percentage * 100 + '%'); + percentages[ file.id ][ 1 ] = percentage; + updateTotalProgress(); + }); + + uploader.on('uploadSuccess', function (file, ret) { + var $file = $('#' + file.id); + try { + var responseText = (ret._raw || ret), + json = utils.str2json(responseText); + if (json.state == 'SUCCESS') { + _this.imageList.push(json); + $file.append(''); + } else { + $file.find('.error').text(json.state).show(); + } + } catch (e) { + $file.find('.error').text(lang.errorServerUpload).show(); + } + }); + + uploader.on('uploadError', function (file, code) { + }); + uploader.on('error', function (code, file) { + if (code == 'Q_TYPE_DENIED' || code == 'F_EXCEED_SIZE') { + addFile(file); + } + }); + uploader.on('uploadComplete', function (file, ret) { + }); + + $upload.on('click', function () { + if ($(this).hasClass('disabled')) { + return false; + } + + if (state === 'ready') { + uploader.upload(); + } else if (state === 'paused') { + uploader.upload(); + } else if (state === 'uploading') { + uploader.stop(); + } + }); + + $upload.addClass('state-' + state); + updateTotalProgress(); + }, + getQueueCount: function () { + var file, i, status, readyFile = 0, files = this.uploader.getFiles(); + for (i = 0; file = files[i++]; ) { + status = file.getStatus(); + if (status == 'queued' || status == 'uploading' || status == 'progress') readyFile++; + } + return readyFile; + }, + destroy: function () { + this.$wrap.remove(); + }, + getInsertList: function () { + var i, data, list = [], + align = getAlign(), + prefix = editor.getOpt('imageUrlPrefix'); + for (i = 0; i < this.imageList.length; i++) { + data = this.imageList[i]; + list.push({ + src: prefix + data.url, + _src: prefix + data.url, + title: data.title, + alt: data.original, + floatStyle: align + }); + } + return list; + } + }; + + + /* 在线图片 */ + function OnlineImage(target) { + this.container = utils.isString(target) ? document.getElementById(target) : target; + this.init(); + } + OnlineImage.prototype = { + init: function () { + this.reset(); + this.initEvents(); + }, + /* 初始化容器 */ + initContainer: function () { + this.container.innerHTML = ''; + this.list = document.createElement('ul'); + this.clearFloat = document.createElement('li'); + + domUtils.addClass(this.list, 'list'); + domUtils.addClass(this.clearFloat, 'clearFloat'); + + this.list.appendChild(this.clearFloat); + this.container.appendChild(this.list); + }, + /* 初始化滚动事件,滚动到地步自动拉取数据 */ + initEvents: function () { + var _this = this; + + /* 滚动拉取图片 */ + domUtils.on($G('imageList'), 'scroll', function(e){ + var panel = this; + if (panel.scrollHeight - (panel.offsetHeight + panel.scrollTop) < 10) { + _this.getImageData(); + } + }); + /* 选中图片 */ + domUtils.on(this.container, 'click', function (e) { + var target = e.target || e.srcElement, + li = target.parentNode; + + if (li.tagName.toLowerCase() == 'li') { + if (domUtils.hasClass(li, 'selected')) { + domUtils.removeClasses(li, 'selected'); + } else { + domUtils.addClass(li, 'selected'); + } + } + }); + }, + /* 初始化第一次的数据 */ + initData: function () { + + /* 拉取数据需要使用的值 */ + this.state = 0; + this.listSize = editor.getOpt('imageManagerListSize'); + this.listIndex = 0; + this.listEnd = false; + + /* 第一次拉取数据 */ + this.getImageData(); + }, + /* 重置界面 */ + reset: function() { + this.initContainer(); + this.initData(); + }, + /* 向后台拉取图片列表数据 */ + getImageData: function () { + var _this = this; + + if(!_this.listEnd && !this.isLoadingData) { + this.isLoadingData = true; + var url = editor.getActionUrl(editor.getOpt('imageManagerActionName')), + isJsonp = utils.isCrossDomainUrl(url); + ajax.request(url, { + 'timeout': 100000, + 'dataType': isJsonp ? 'jsonp':'', + 'data': utils.extend({ + start: this.listIndex, + size: this.listSize + }, editor.queryCommandValue('serverparam')), + 'method': 'get', + 'onsuccess': function (r) { + try { + var json = isJsonp ? r:eval('(' + r.responseText + ')'); + if (json.state == 'SUCCESS') { + _this.pushData(json.list); + _this.listIndex = parseInt(json.start) + parseInt(json.list.length); + if(_this.listIndex >= json.total) { + _this.listEnd = true; + } + _this.isLoadingData = false; + } + } catch (e) { + if(r.responseText.indexOf('ue_separate_ue') != -1) { + var list = r.responseText.split(r.responseText); + _this.pushData(list); + _this.listIndex = parseInt(list.length); + _this.listEnd = true; + _this.isLoadingData = false; + } + } + }, + 'onerror': function () { + _this.isLoadingData = false; + } + }); + } + }, + /* 添加图片到列表界面上 */ + pushData: function (list) { + var i, item, img, icon, _this = this, + urlPrefix = editor.getOpt('imageManagerUrlPrefix'); + for (i = 0; i < list.length; i++) { + if(list[i] && list[i].url) { + item = document.createElement('li'); + img = document.createElement('img'); + icon = document.createElement('span'); + + domUtils.on(img, 'load', (function(image){ + return function(){ + _this.scale(image, image.parentNode.offsetWidth, image.parentNode.offsetHeight); + } + })(img)); + img.width = 113; + img.setAttribute('src', urlPrefix + list[i].url + (list[i].url.indexOf('?') == -1 ? '?noCache=':'&noCache=') + (+new Date()).toString(36) ); + img.setAttribute('_src', urlPrefix + list[i].url); + domUtils.addClass(icon, 'icon'); + + item.appendChild(img); + item.appendChild(icon); + this.list.insertBefore(item, this.clearFloat); + } + } + }, + /* 改变图片大小 */ + scale: function (img, w, h, type) { + var ow = img.width, + oh = img.height; + + if (type == 'justify') { + if (ow >= oh) { + img.width = w; + img.height = h * oh / ow; + img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px'; + } else { + img.width = w * ow / oh; + img.height = h; + img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px'; + } + } else { + if (ow >= oh) { + img.width = w * ow / oh; + img.height = h; + img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px'; + } else { + img.width = w; + img.height = h * oh / ow; + img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px'; + } + } + }, + getInsertList: function () { + var i, lis = this.list.children, list = [], align = getAlign(); + for (i = 0; i < lis.length; i++) { + if (domUtils.hasClass(lis[i], 'selected')) { + var img = lis[i].firstChild, + src = img.getAttribute('_src'); + list.push({ + src: src, + _src: src, + alt: src.substr(src.lastIndexOf('/') + 1), + floatStyle: align + }); + } + + } + return list; + } + }; + + /*搜索图片 */ + function SearchImage() { + this.init(); + } + SearchImage.prototype = { + init: function () { + this.initEvents(); + }, + initEvents: function(){ + var _this = this; + + /* 点击搜索按钮 */ + domUtils.on($G('searchBtn'), 'click', function(){ + var key = $G('searchTxt').value; + if(key && key != lang.searchRemind) { + _this.getImageData(); + } + }); + /* 点击清除妞 */ + domUtils.on($G('searchReset'), 'click', function(){ + $G('searchTxt').value = lang.searchRemind; + $G('searchListUl').innerHTML = ''; + $G('searchType').selectedIndex = 0; + }); + /* 搜索框聚焦 */ + domUtils.on($G('searchTxt'), 'focus', function(){ + var key = $G('searchTxt').value; + if(key && key == lang.searchRemind) { + $G('searchTxt').value = ''; + } + }); + /* 搜索框回车键搜索 */ + domUtils.on($G('searchTxt'), 'keydown', function(e){ + var keyCode = e.keyCode || e.which; + if (keyCode == 13) { + $G('searchBtn').click(); + } + }); + + /* 选中图片 */ + domUtils.on($G('searchList'), 'click', function(e){ + var target = e.target || e.srcElement, + li = target.parentNode.parentNode; + + if (li.tagName.toLowerCase() == 'li') { + if (domUtils.hasClass(li, 'selected')) { + domUtils.removeClasses(li, 'selected'); + } else { + domUtils.addClass(li, 'selected'); + } + } + }); + }, + encodeToGb2312:function (str){ + if(!str) return ''; + var strOut = "", + z = 'D2BBB6A18140C6DF814181428143CDF2D5C9C8FDC9CFCFC2D8A2B2BBD3EB8144D8A4B3F38145D7A8C7D2D8A7CAC08146C7F0B1FBD2B5B4D4B6ABCBBFD8A9814781488149B6AA814AC1BDD1CF814BC9A5D8AD814CB8F6D1BEE3DCD6D0814D814EB7E1814FB4AE8150C1D98151D8BC8152CDE8B5A4CEAAD6F78153C0F6BED9D8AF815481558156C4CB8157BEC38158D8B1C3B4D2E58159D6AECEDAD5A7BAF5B7A6C0D6815AC6B9C5D2C7C7815BB9D4815CB3CBD2D2815D815ED8BFBEC5C6F2D2B2CFB0CFE7815F816081618162CAE981638164D8C081658166816781688169816AC2F2C2D2816BC8E9816C816D816E816F817081718172817381748175C7AC8176817781788179817A817B817CC1CB817DD3E8D5F9817ECAC2B6FED8A1D3DABFF78180D4C6BBA5D8C1CEE5BEAE81818182D8A88183D1C7D0A9818481858186D8BDD9EFCDF6BFBA8187BDBBBAA5D2E0B2FABAE0C4B68188CFEDBEA9CDA4C1C18189818A818BC7D7D9F1818CD9F4818D818E818F8190C8CBD8E9819181928193D2DACAB2C8CAD8ECD8EAD8C6BDF6C6CDB3F08194D8EBBDF1BDE98195C8D4B4D381968197C2D88198B2D6D7D0CACBCBFBD5CCB8B6CFC98199819A819BD9DAD8F0C7AA819CD8EE819DB4FAC1EED2D4819E819FD8ED81A0D2C7D8EFC3C781A181A281A3D1F681A4D6D9D8F281A5D8F5BCFEBCDB81A681A781A8C8CE81A9B7DD81AAB7C281ABC6F381AC81AD81AE81AF81B081B181B2D8F8D2C181B381B4CEE9BCBFB7FCB7A5D0DD81B581B681B781B881B9D6DAD3C5BBEFBBE1D8F181BA81BBC9A1CEB0B4AB81BCD8F381BDC9CBD8F6C2D7D8F781BE81BFCEB1D8F981C081C181C2B2AEB9C081C3D9A381C4B0E981C5C1E681C6C9EC81C7CBC581C8CBC6D9A481C981CA81CB81CC81CDB5E881CE81CFB5AB81D081D181D281D381D481D5CEBBB5CDD7A1D7F4D3D381D6CCE581D7BACE81D8D9A2D9DCD3E0D8FDB7F0D7F7D8FED8FAD9A1C4E381D981DAD3B6D8F4D9DD81DBD8FB81DCC5E581DD81DEC0D081DF81E0D1F0B0DB81E181E2BCD1D9A681E3D9A581E481E581E681E7D9ACD9AE81E8D9ABCAB981E981EA81EBD9A9D6B681EC81ED81EEB3DED9A881EFC0FD81F0CACC81F1D9AA81F2D9A781F381F4D9B081F581F6B6B181F781F881F9B9A981FAD2C081FB81FCCFC081FD81FEC2C28240BDC4D5ECB2E0C7C8BFEBD9AD8241D9AF8242CEEABAEE82438244824582468247C7D682488249824A824B824C824D824E824F8250B1E3825182528253B4D9B6EDD9B48254825582568257BFA182588259825AD9DEC7CEC0FED9B8825B825C825D825E825FCBD7B7FD8260D9B58261D9B7B1A3D3E1D9B98262D0C58263D9B682648265D9B18266D9B2C1A9D9B382678268BCF3D0DEB8A98269BEE3826AD9BD826B826C826D826ED9BA826FB0B3827082718272D9C28273827482758276827782788279827A827B827C827D827E8280D9C4B1B68281D9BF82828283B5B98284BEF3828582868287CCC8BAF2D2D08288D9C38289828ABDE8828BB3AB828C828D828ED9C5BEEB828FD9C6D9BBC4DF8290D9BED9C1D9C0829182928293829482958296829782988299829A829BD5AE829CD6B5829DC7E3829E829F82A082A1D9C882A282A382A4BCD9D9CA82A582A682A7D9BC82A8D9CBC6AB82A982AA82AB82AC82ADD9C982AE82AF82B082B1D7F682B2CDA382B382B482B582B682B782B882B982BABDA182BB82BC82BD82BE82BF82C0D9CC82C182C282C382C482C582C682C782C882C9C5BCCDB582CA82CB82CCD9CD82CD82CED9C7B3A5BFFE82CF82D082D182D2B8B582D382D4C0FC82D582D682D782D8B0F882D982DA82DB82DC82DD82DE82DF82E082E182E282E382E482E582E682E782E882E982EA82EB82EC82EDB4F682EED9CE82EFD9CFB4A2D9D082F082F1B4DF82F282F382F482F582F6B0C182F782F882F982FA82FB82FC82FDD9D1C9B582FE8340834183428343834483458346834783488349834A834B834C834D834E834F83508351CFF1835283538354835583568357D9D283588359835AC1C5835B835C835D835E835F836083618362836383648365D9D6C9AE8366836783688369D9D5D9D4D9D7836A836B836C836DCBDB836EBDA9836F8370837183728373C6A7837483758376837783788379837A837B837C837DD9D3D9D8837E83808381D9D9838283838384838583868387C8E583888389838A838B838C838D838E838F839083918392839383948395C0DC8396839783988399839A839B839C839D839E839F83A083A183A283A383A483A583A683A783A883A983AA83AB83AC83AD83AE83AF83B083B183B2B6F9D8A3D4CA83B3D4AAD0D6B3E4D5D783B4CFC8B9E283B5BFCB83B6C3E283B783B883B9B6D283BA83BBCDC3D9EED9F083BC83BD83BEB5B383BFB6B583C083C183C283C383C4BEA483C583C6C8EB83C783C8C8AB83C983CAB0CBB9ABC1F9D9E283CBC0BCB9B283CCB9D8D0CBB1F8C6E4BEDFB5E4D7C883CDD1F8BCE6CADE83CE83CFBCBDD9E6D8E783D083D1C4DA83D283D3B8D4C8BD83D483D5B2E1D4D983D683D783D883D9C3B083DA83DBC3E1DAA2C8DF83DCD0B483DDBEFCC5A983DE83DF83E0B9DA83E1DAA383E2D4A9DAA483E383E483E583E683E7D9FBB6AC83E883E9B7EBB1F9D9FCB3E5BEF683EABFF6D2B1C0E483EB83EC83EDB6B3D9FED9FD83EE83EFBEBB83F083F183F2C6E083F3D7BCDAA183F4C1B983F5B5F2C1E883F683F7BCF583F8B4D583F983FA83FB83FC83FD83FE844084418442C1DD8443C4FD84448445BCB8B7B284468447B7EF84488449844A844B844C844DD9EC844EC6BE844FBFADBBCB84508451B5CA8452DBC9D0D78453CDB9B0BCB3F6BBF7DBCABAAF8454D4E4B5B6B5F3D8D6C8D084558456B7D6C7D0D8D78457BFAF84588459DBBBD8D8845A845BD0CCBBAE845C845D845EEBBEC1D0C1F5D4F2B8D5B4B4845FB3F584608461C9BE846284638464C5D0846584668467C5D9C0FB8468B1F08469D8D9B9CE846AB5BD846B846CD8DA846D846ED6C6CBA2C8AFC9B2B4CCBFCC846FB9F48470D8DBD8DCB6E7BCC1CCEA847184728473847484758476CFF78477D8DDC7B084788479B9D0BDA3847A847BCCDE847CC6CA847D847E848084818482D8E08483D8DE84848485D8DF848684878488B0FE8489BEE7848ACAA3BCF4848B848C848D848EB8B1848F8490B8EE849184928493849484958496849784988499849AD8E2849BBDCB849CD8E4D8E3849D849E849F84A084A1C5FC84A284A384A484A584A684A784A8D8E584A984AAD8E684AB84AC84AD84AE84AF84B084B1C1A684B2C8B0B0ECB9A6BCD3CEF1DBBDC1D384B384B484B584B6B6AFD6FAC5ACBDD9DBBEDBBF84B784B884B9C0F8BEA2C0CD84BA84BB84BC84BD84BE84BF84C084C184C284C3DBC0CAC684C484C584C6B2AA84C784C884C9D3C284CAC3E384CBD1AB84CC84CD84CE84CFDBC284D0C0D584D184D284D3DBC384D4BFB184D584D684D784D884D984DAC4BC84DB84DC84DD84DEC7DA84DF84E084E184E284E384E484E584E684E784E884E9DBC484EA84EB84EC84ED84EE84EF84F084F1D9E8C9D784F284F384F4B9B4CEF0D4C884F584F684F784F8B0FCB4D284F9D0D984FA84FB84FC84FDD9E984FEDECBD9EB8540854185428543D8B0BBAFB1B18544B3D7D8CE85458546D4D185478548BDB3BFEF8549CFBB854A854BD8D0854C854D854EB7CB854F85508551D8D185528553855485558556855785588559855A855BC6A5C7F8D2BD855C855DD8D2C4E4855ECAAE855FC7A78560D8A68561C9FDCEE7BBDCB0EB856285638564BBAAD0AD8565B1B0D7E4D7BF8566B5A5C2F4C4CF85678568B2A98569B2B7856AB1E5DFB2D5BCBFA8C2ACD8D5C2B1856BD8D4CED4856CDAE0856DCEC0856E856FD8B4C3AED3A1CEA38570BCB4C8B4C2D18571BEEDD0B68572DAE18573857485758576C7E485778578B3A78579B6F2CCFCC0FA857A857BC0F7857CD1B9D1E1D8C7857D857E85808581858285838584B2DE85858586C0E58587BAF185888589D8C8858AD4AD858B858CCFE1D8C9858DD8CACFC3858EB3F8BEC7858F859085918592D8CB8593859485958596859785988599DBCC859A859B859C859DC8A5859E859F85A0CFD885A1C8FEB2CE85A285A385A485A585A6D3D6B2E6BCB0D3D1CBABB7B485A785A885A9B7A285AA85ABCAE585ACC8A1CADCB1E4D0F085ADC5D185AE85AF85B0DBC5B5FE85B185B2BFDAB9C5BEE4C1ED85B3DFB6DFB5D6BBBDD0D5D9B0C8B6A3BFC9CCA8DFB3CAB7D3D285B4D8CFD2B6BAC5CBBECCBE85B5DFB7B5F0DFB485B685B785B8D3F585B9B3D4B8F785BADFBA85BBBACFBCAAB5F585BCCDACC3FBBAF3C0F4CDC2CFF2DFB8CFC585BDC2C0DFB9C2F085BE85BF85C0BEFD85C1C1DFCDCCD2F7B7CDDFC185C2DFC485C385C4B7F1B0C9B6D6B7D485C5BAACCCFDBFD4CBB1C6F485C6D6A8DFC585C7CEE2B3B385C885C9CEFCB4B585CACEC7BAF085CBCEE185CCD1BD85CD85CEDFC085CF85D0B4F485D1B3CA85D2B8E6DFBB85D385D485D585D6C4C585D7DFBCDFBDDFBEC5BBDFBFDFC2D4B1DFC385D8C7BACED885D985DA85DB85DC85DDC4D885DEDFCA85DFDFCF85E0D6DC85E185E285E385E485E585E685E785E8DFC9DFDACEB685E9BAC7DFCEDFC8C5DE85EA85EBC9EBBAF4C3FC85EC85EDBED785EEDFC685EFDFCD85F0C5D885F185F285F385F4D5A6BACD85F5BECCD3BDB8C085F6D6E485F7DFC7B9BEBFA785F885F9C1FCDFCBDFCC85FADFD085FB85FC85FD85FE8640DFDBDFE58641DFD7DFD6D7C9DFE3DFE4E5EBD2A7DFD28642BFA98643D4DB8644BFC8DFD4864586468647CFCC86488649DFDD864AD1CA864BDFDEB0A7C6B7DFD3864CBAE5864DB6DFCDDBB9FED4D5864E864FDFDFCFECB0A5DFE7DFD1D1C6DFD5DFD8DFD9DFDC8650BBA98651DFE0DFE18652DFE2DFE6DFE8D3B486538654865586568657B8E7C5B6DFEAC9DAC1A8C4C486588659BFDECFF8865A865B865CD5DCDFEE865D865E865F866086618662B2B88663BADFDFEC8664DBC18665D1E48666866786688669CBF4B4BD866AB0A6866B866C866D866E866FDFF1CCC6DFF286708671DFED867286738674867586768677DFE986788679867A867BDFEB867CDFEFDFF0BBBD867D867EDFF386808681DFF48682BBA38683CADBCEA8E0A7B3AA8684E0A6868586868687E0A186888689868A868BDFFE868CCDD9DFFC868DDFFA868EBFD0D7C4868FC9CC86908691DFF8B0A186928693869486958696DFFD869786988699869ADFFBE0A2869B869C869D869E869FE0A886A086A186A286A3B7C886A486A5C6A1C9B6C0B2DFF586A686A7C5BE86A8D8C4DFF9C4F686A986AA86AB86AC86AD86AEE0A3E0A4E0A5D0A586AF86B0E0B4CCE486B1E0B186B2BFA6E0AFCEB9E0ABC9C686B386B4C0AEE0AEBAEDBAB0E0A986B586B686B7DFF686B8E0B386B986BAE0B886BB86BC86BDB4ADE0B986BE86BFCFB2BAC886C0E0B086C186C286C386C486C586C686C7D0FA86C886C986CA86CB86CC86CD86CE86CF86D0E0AC86D1D4FB86D2DFF786D3C5E786D4E0AD86D5D3F786D6E0B6E0B786D786D886D986DA86DBE0C4D0E186DC86DD86DEE0BC86DF86E0E0C9E0CA86E186E286E3E0BEE0AAC9A4E0C186E4E0B286E586E686E786E886E9CAC8E0C386EAE0B586EBCECB86ECCBC3E0CDE0C6E0C286EDE0CB86EEE0BAE0BFE0C086EF86F0E0C586F186F2E0C7E0C886F3E0CC86F4E0BB86F586F686F786F886F9CBD4E0D586FAE0D6E0D286FB86FC86FD86FE87408741E0D0BCCE87428743E0D18744B8C2D8C587458746874787488749874A874B874CD0EA874D874EC2EF874F8750E0CFE0BD875187528753E0D4E0D387548755E0D78756875787588759E0DCE0D8875A875B875CD6F6B3B0875DD7EC875ECBBB875F8760E0DA8761CEFB876287638764BAD987658766876787688769876A876B876C876D876E876F8770E0E1E0DDD2AD87718772877387748775E0E287768777E0DBE0D9E0DF87788779E0E0877A877B877C877D877EE0DE8780E0E4878187828783C6F7D8ACD4EBE0E6CAC98784878587868787E0E587888789878A878BB8C1878C878D878E878FE0E7E0E887908791879287938794879587968797E0E9E0E387988799879A879B879C879D879EBABFCCE7879F87A087A1E0EA87A287A387A487A587A687A787A887A987AA87AB87AC87AD87AE87AF87B0CFF987B187B287B387B487B587B687B787B887B987BA87BBE0EB87BC87BD87BE87BF87C087C187C2C8C287C387C487C587C6BDC087C787C887C987CA87CB87CC87CD87CE87CF87D087D187D287D3C4D287D487D587D687D787D887D987DA87DB87DCE0EC87DD87DEE0ED87DF87E0C7F4CBC487E1E0EEBBD8D8B6D2F2E0EFCDC587E2B6DA87E387E487E587E687E787E8E0F187E9D4B087EA87EBC0A7B4D187EC87EDCEA7E0F087EE87EF87F0E0F2B9CC87F187F2B9FACDBCE0F387F387F487F5C6D4E0F487F6D4B287F7C8A6E0F6E0F587F887F987FA87FB87FC87FD87FE8840884188428843884488458846884788488849E0F7884A884BCDC1884C884D884ECAA5884F885088518852D4DADBD7DBD98853DBD8B9E7DBDCDBDDB5D888548855DBDA8856885788588859885ADBDBB3A1DBDF885B885CBBF8885DD6B7885EDBE0885F886088618862BEF988638864B7BB8865DBD0CCAEBFB2BBB5D7F8BFD38866886788688869886ABFE9886B886CBCE1CCB3DBDEB0D3CEEBB7D8D7B9C6C2886D886EC0A4886FCCB98870DBE7DBE1C6BADBE38871DBE88872C5F7887388748875DBEA88768877DBE9BFC088788879887ADBE6DBE5887B887C887D887E8880B4B9C0ACC2A2DBE2DBE48881888288838884D0CDDBED88858886888788888889C0DDDBF2888A888B888C888D888E888F8890B6E28891889288938894DBF3DBD2B9B8D4ABDBEC8895BFD1DBF08896DBD18897B5E68898DBEBBFE58899889A889BDBEE889CDBF1889D889E889FDBF988A088A188A288A388A488A588A688A788A8B9A1B0A388A988AA88AB88AC88AD88AE88AFC2F188B088B1B3C7DBEF88B288B3DBF888B4C6D2DBF488B588B6DBF5DBF7DBF688B788B8DBFE88B9D3F2B2BA88BA88BB88BCDBFD88BD88BE88BF88C088C188C288C388C4DCA488C5DBFB88C688C788C888C9DBFA88CA88CB88CCDBFCC5E0BBF988CD88CEDCA388CF88D0DCA588D1CCC388D288D388D4B6D1DDC088D588D688D7DCA188D8DCA288D988DA88DBC7B588DC88DD88DEB6E988DF88E088E1DCA788E288E388E488E5DCA688E6DCA9B1A488E788E8B5CC88E988EA88EB88EC88EDBFB088EE88EF88F088F188F2D1DF88F388F488F588F6B6C288F788F888F988FA88FB88FC88FD88FE894089418942894389448945DCA88946894789488949894A894B894CCBFAEBF3894D894E894FCBDC89508951CBFE895289538954CCC189558956895789588959C8FB895A895B895C895D895E895FDCAA89608961896289638964CCEEDCAB89658966896789688969896A896B896C896D896E896F897089718972897389748975DBD38976DCAFDCAC8977BEB38978CAFB8979897A897BDCAD897C897D897E89808981898289838984C9CAC4B989858986898789888989C7BDDCAE898A898B898CD4F6D0E6898D898E898F89908991899289938994C4ABB6D589958996899789988999899A899B899C899D899E899F89A089A189A289A389A489A589A6DBD489A789A889A989AAB1DA89AB89AC89ADDBD589AE89AF89B089B189B289B389B489B589B689B789B8DBD689B989BA89BBBABE89BC89BD89BE89BF89C089C189C289C389C489C589C689C789C889C9C8C089CA89CB89CC89CD89CE89CFCABFC8C989D0D7B389D1C9F989D289D3BFC789D489D5BAF889D689D7D2BC89D889D989DA89DB89DC89DD89DE89DFE2BA89E0B4A689E189E2B1B889E389E489E589E689E7B8B489E8CFC489E989EA89EB89ECD9E7CFA6CDE289ED89EED9EDB6E089EFD2B989F089F1B9BB89F289F389F489F5E2B9E2B789F6B4F389F7CCECCCABB7F289F8D8B2D1EBBABB89F9CAA789FA89FBCDB789FC89FDD2C4BFE4BCD0B6E189FEDEC58A408A418A428A43DEC6DBBC8A44D1D98A458A46C6E6C4CEB7EE8A47B7DC8A488A49BFFCD7E08A4AC6F58A4B8A4CB1BCDEC8BDB1CCD7DECA8A4DDEC98A4E8A4F8A508A518A52B5EC8A53C9DD8A548A55B0C28A568A578A588A598A5A8A5B8A5C8A5D8A5E8A5F8A608A618A62C5AEC5AB8A63C4CC8A64BCE9CBFD8A658A668A67BAC38A688A698A6AE5F9C8E7E5FACDFD8A6BD7B1B8BEC2E88A6CC8D18A6D8A6EE5FB8A6F8A708A718A72B6CABCCB8A738A74D1FDE6A18A75C3EE8A768A778A788A79E6A48A7A8A7B8A7C8A7DE5FEE6A5CDD78A7E8A80B7C1E5FCE5FDE6A38A818A82C4DDE6A88A838A84E6A78A858A868A878A888A898A8AC3C38A8BC6DE8A8C8A8DE6AA8A8E8A8F8A908A918A928A938A94C4B78A958A968A97E6A2CABC8A988A998A9A8A9BBDE3B9C3E6A6D0D5CEAF8A9C8A9DE6A9E6B08A9ED2A68A9FBDAAE6AD8AA08AA18AA28AA38AA4E6AF8AA5C0D18AA68AA7D2CC8AA88AA98AAABCA78AAB8AAC8AAD8AAE8AAF8AB08AB18AB28AB38AB48AB58AB6E6B18AB7D2F68AB88AB98ABAD7CB8ABBCDFE8ABCCDDEC2A6E6ABE6ACBDBFE6AEE6B38ABD8ABEE6B28ABF8AC08AC18AC2E6B68AC3E6B88AC48AC58AC68AC7C4EF8AC88AC98ACAC4C88ACB8ACCBEEAC9EF8ACD8ACEE6B78ACFB6F08AD08AD18AD2C3E48AD38AD48AD58AD68AD78AD88AD9D3E9E6B48ADAE6B58ADBC8A28ADC8ADD8ADE8ADF8AE0E6BD8AE18AE28AE3E6B98AE48AE58AE68AE78AE8C6C58AE98AEACDF1E6BB8AEB8AEC8AED8AEE8AEF8AF08AF18AF28AF38AF4E6BC8AF58AF68AF78AF8BBE98AF98AFA8AFB8AFC8AFD8AFE8B40E6BE8B418B428B438B44E6BA8B458B46C0B78B478B488B498B4A8B4B8B4C8B4D8B4E8B4FD3A4E6BFC9F4E6C38B508B51E6C48B528B538B548B55D0F68B568B578B588B598B5A8B5B8B5C8B5D8B5E8B5F8B608B618B628B638B648B658B668B67C3BD8B688B698B6A8B6B8B6C8B6D8B6EC3C4E6C28B6F8B708B718B728B738B748B758B768B778B788B798B7A8B7B8B7CE6C18B7D8B7E8B808B818B828B838B84E6C7CFB18B85EBF48B868B87E6CA8B888B898B8A8B8B8B8CE6C58B8D8B8EBCDEC9A98B8F8B908B918B928B938B94BCB58B958B96CFD38B978B988B998B9A8B9BE6C88B9CE6C98B9DE6CE8B9EE6D08B9F8BA08BA1E6D18BA28BA38BA4E6CBB5D58BA5E6CC8BA68BA7E6CF8BA88BA9C4DB8BAAE6C68BAB8BAC8BAD8BAE8BAFE6CD8BB08BB18BB28BB38BB48BB58BB68BB78BB88BB98BBA8BBB8BBC8BBD8BBE8BBF8BC08BC18BC28BC38BC48BC58BC6E6D28BC78BC88BC98BCA8BCB8BCC8BCD8BCE8BCF8BD08BD18BD2E6D4E6D38BD38BD48BD58BD68BD78BD88BD98BDA8BDB8BDC8BDD8BDE8BDF8BE08BE18BE28BE38BE48BE58BE68BE78BE88BE98BEA8BEB8BECE6D58BEDD9F88BEE8BEFE6D68BF08BF18BF28BF38BF48BF58BF68BF7E6D78BF88BF98BFA8BFB8BFC8BFD8BFE8C408C418C428C438C448C458C468C47D7D3E6DD8C48E6DEBFD7D4D08C49D7D6B4E6CBEFE6DAD8C3D7CED0A28C4AC3CF8C4B8C4CE6DFBCBEB9C2E6DBD1A78C4D8C4EBAA2C2CF8C4FD8AB8C508C518C52CAEBE5EE8C53E6DC8C54B7F58C558C568C578C58C8E68C598C5AC4F58C5B8C5CE5B2C4FE8C5DCBFCE5B3D5AC8C5ED3EECAD8B0B28C5FCBCECDEA8C608C61BAEA8C628C638C64E5B58C65E5B48C66D7DAB9D9D6E6B6A8CDF0D2CBB1A6CAB58C67B3E8C9F3BFCDD0FBCAD2E5B6BBC28C688C698C6ACFDCB9AC8C6B8C6C8C6D8C6ED4D78C6F8C70BAA6D1E7CFFCBCD28C71E5B7C8DD8C728C738C74BFEDB1F6CBDE8C758C76BCC58C77BCC4D2FAC3DCBFDC8C788C798C7A8C7BB8BB8C7C8C7D8C7EC3C28C80BAAED4A28C818C828C838C848C858C868C878C888C89C7DEC4AFB2EC8C8AB9D18C8B8C8CE5BBC1C88C8D8C8ED5AF8C8F8C908C918C928C93E5BC8C94E5BE8C958C968C978C988C998C9A8C9BB4E7B6D4CBC2D1B0B5BC8C9C8C9DCAD98C9EB7E28C9F8CA0C9E48CA1BDAB8CA28CA3CEBED7F08CA48CA58CA68CA7D0A18CA8C9D98CA98CAAB6FBE6D8BCE28CABB3BE8CACC9D08CADE6D9B3A28CAE8CAF8CB08CB1DECC8CB2D3C8DECD8CB3D2A28CB48CB58CB68CB7DECE8CB88CB98CBA8CBBBECD8CBC8CBDDECF8CBE8CBF8CC0CAACD2FCB3DFE5EAC4E1BEA1CEB2C4F2BED6C6A8B2E38CC18CC2BED38CC38CC4C7FCCCEBBDECCEDD8CC58CC6CABAC6C1E5ECD0BC8CC78CC88CC9D5B98CCA8CCB8CCCE5ED8CCD8CCE8CCF8CD0CAF48CD1CDC0C2C58CD2E5EF8CD3C2C4E5F08CD48CD58CD68CD78CD88CD98CDAE5F8CDCD8CDBC9BD8CDC8CDD8CDE8CDF8CE08CE18CE2D2D9E1A88CE38CE48CE58CE6D3EC8CE7CBEAC6F18CE88CE98CEA8CEB8CECE1AC8CED8CEE8CEFE1A7E1A98CF08CF1E1AAE1AF8CF28CF3B2ED8CF4E1ABB8DAE1ADE1AEE1B0B5BAE1B18CF58CF68CF78CF88CF9E1B3E1B88CFA8CFB8CFC8CFD8CFED1D28D40E1B6E1B5C1EB8D418D428D43E1B78D44D4C08D45E1B28D46E1BAB0B68D478D488D498D4AE1B48D4BBFF98D4CE1B98D4D8D4EE1BB8D4F8D508D518D528D538D54E1BE8D558D568D578D588D598D5AE1BC8D5B8D5C8D5D8D5E8D5F8D60D6C58D618D628D638D648D658D668D67CFBF8D688D69E1BDE1BFC2CD8D6AB6EB8D6BD3F88D6C8D6DC7CD8D6E8D6FB7E58D708D718D728D738D748D758D768D778D788D79BEFE8D7A8D7B8D7C8D7D8D7E8D80E1C0E1C18D818D82E1C7B3E78D838D848D858D868D878D88C6E98D898D8A8D8B8D8C8D8DB4DE8D8ED1C28D8F8D908D918D92E1C88D938D94E1C68D958D968D978D988D99E1C58D9AE1C3E1C28D9BB1C08D9C8D9D8D9ED5B8E1C48D9F8DA08DA18DA28DA3E1CB8DA48DA58DA68DA78DA88DA98DAA8DABE1CCE1CA8DAC8DAD8DAE8DAF8DB08DB18DB28DB3EFFA8DB48DB5E1D3E1D2C7B68DB68DB78DB88DB98DBA8DBB8DBC8DBD8DBE8DBF8DC0E1C98DC18DC2E1CE8DC3E1D08DC48DC58DC68DC78DC88DC98DCA8DCB8DCC8DCD8DCEE1D48DCFE1D1E1CD8DD08DD1E1CF8DD28DD38DD48DD5E1D58DD68DD78DD88DD98DDA8DDB8DDC8DDD8DDE8DDF8DE08DE18DE2E1D68DE38DE48DE58DE68DE78DE88DE98DEA8DEB8DEC8DED8DEE8DEF8DF08DF18DF28DF38DF48DF58DF68DF78DF8E1D78DF98DFA8DFBE1D88DFC8DFD8DFE8E408E418E428E438E448E458E468E478E488E498E4A8E4B8E4C8E4D8E4E8E4F8E508E518E528E538E548E55E1DA8E568E578E588E598E5A8E5B8E5C8E5D8E5E8E5F8E608E618E62E1DB8E638E648E658E668E678E688E69CEA18E6A8E6B8E6C8E6D8E6E8E6F8E708E718E728E738E748E758E76E7DD8E77B4A8D6DD8E788E79D1B2B3B28E7A8E7BB9A4D7F3C7C9BEDEB9AE8E7CCED78E7D8E7EB2EEDBCF8E80BCBAD2D1CBC8B0CD8E818E82CFEF8E838E848E858E868E87D9E3BDED8E888E89B1D2CAD0B2BC8E8ACBA7B7AB8E8BCAA68E8C8E8D8E8ECFA38E8F8E90E0F8D5CAE0FB8E918E92E0FAC5C1CCFB8E93C1B1E0F9D6E3B2AFD6C4B5DB8E948E958E968E978E988E998E9A8E9BB4F8D6A18E9C8E9D8E9E8E9F8EA0CFAFB0EF8EA18EA2E0FC8EA38EA48EA58EA68EA7E1A1B3A38EA88EA9E0FDE0FEC3B18EAA8EAB8EAC8EADC3DD8EAEE1A2B7F98EAF8EB08EB18EB28EB38EB4BBCF8EB58EB68EB78EB88EB98EBA8EBBE1A3C4BB8EBC8EBD8EBE8EBF8EC0E1A48EC18EC2E1A58EC38EC4E1A6B4B18EC58EC68EC78EC88EC98ECA8ECB8ECC8ECD8ECE8ECF8ED08ED18ED28ED3B8C9C6BDC4EA8ED4B2A28ED5D0D28ED6E7DBBBC3D3D7D3C48ED7B9E3E2CF8ED88ED98EDAD7AF8EDBC7ECB1D38EDC8EDDB4B2E2D18EDE8EDF8EE0D0F2C2AEE2D08EE1BFE2D3A6B5D7E2D2B5EA8EE2C3EDB8FD8EE3B8AE8EE4C5D3B7CFE2D48EE58EE68EE78EE8E2D3B6C8D7F98EE98EEA8EEB8EEC8EEDCDA58EEE8EEF8EF08EF18EF2E2D88EF3E2D6CAFCBFB5D3B9E2D58EF48EF58EF68EF7E2D78EF88EF98EFA8EFB8EFC8EFD8EFE8F408F418F42C1AEC0C88F438F448F458F468F478F48E2DBE2DAC0AA8F498F4AC1CE8F4B8F4C8F4D8F4EE2DC8F4F8F508F518F528F538F548F558F568F578F588F598F5AE2DD8F5BE2DE8F5C8F5D8F5E8F5F8F608F618F628F638F64DBC88F65D1D3CDA28F668F67BDA88F688F698F6ADEC3D8A5BFAADBCDD2ECC6FAC5AA8F6B8F6C8F6DDEC48F6EB1D7DFAE8F6F8F708F71CABD8F72DFB18F73B9AD8F74D2FD8F75B8A5BAEB8F768F77B3DA8F788F798F7AB5DCD5C58F7B8F7C8F7D8F7EC3D6CFD2BBA18F80E5F3E5F28F818F82E5F48F83CDE48F84C8F58F858F868F878F888F898F8A8F8BB5AFC7BF8F8CE5F68F8D8F8E8F8FECB08F908F918F928F938F948F958F968F978F988F998F9A8F9B8F9C8F9D8F9EE5E68F9FB9E9B5B18FA0C2BCE5E8E5E7E5E98FA18FA28FA38FA4D2CD8FA58FA68FA7E1EAD0CE8FA8CDAE8FA9D1E58FAA8FABB2CAB1EB8FACB1F2C5ED8FAD8FAED5C3D3B08FAFE1DC8FB08FB18FB2E1DD8FB3D2DB8FB4B3B9B1CB8FB58FB68FB7CDF9D5F7E1DE8FB8BEB6B4FD8FB9E1DFBADCE1E0BBB2C2C9E1E18FBA8FBB8FBCD0EC8FBDCDBD8FBE8FBFE1E28FC0B5C3C5C7E1E38FC18FC2E1E48FC38FC48FC58FC6D3F98FC78FC88FC98FCA8FCB8FCCE1E58FCDD1AD8FCE8FCFE1E6CEA28FD08FD18FD28FD38FD48FD5E1E78FD6B5C28FD78FD88FD98FDAE1E8BBD58FDB8FDC8FDD8FDE8FDFD0C4E2E0B1D8D2E48FE08FE1E2E18FE28FE3BCC9C8CC8FE4E2E3ECFEECFDDFAF8FE58FE68FE7E2E2D6BECDFCC3A68FE88FE98FEAE3C38FEB8FECD6D2E2E78FED8FEEE2E88FEF8FF0D3C78FF18FF2E2ECBFEC8FF3E2EDE2E58FF48FF5B3C08FF68FF78FF8C4EE8FF98FFAE2EE8FFB8FFCD0C38FFDBAF6E2E9B7DEBBB3CCACCBCBE2E4E2E6E2EAE2EB8FFE90409041E2F790429043E2F4D4F5E2F390449045C5AD9046D5FAC5C2B2C090479048E2EF9049E2F2C1AFCBBC904A904BB5A1E2F9904C904D904EBCB1E2F1D0D4D4B9E2F5B9D6E2F6904F90509051C7D390529053905490559056E2F0905790589059905A905BD7DCEDA1905C905DE2F8905EEDA5E2FECAD1905F906090619062906390649065C1B59066BBD090679068BFD69069BAE3906A906BCBA1906C906D906EEDA6EDA3906F9070EDA29071907290739074BBD6EDA7D0F490759076EDA4BADEB6F7E3A1B6B2CCF1B9A79077CFA2C7A190789079BFD2907A907BB6F1907CE2FAE2FBE2FDE2FCC4D5E3A2907DD3C1907E90809081E3A7C7C49082908390849085CFA490869087E3A9BAB790889089908A908BE3A8908CBBDA908DE3A3908E908F9090E3A4E3AA9091E3A69092CEF2D3C690939094BBBC90959096D4C39097C4FA90989099EDA8D0FCE3A5909AC3F5909BE3ADB1AF909CE3B2909D909E909FBCC290A090A1E3ACB5BF90A290A390A490A590A690A790A890A9C7E9E3B090AA90AB90ACBEAACDEF90AD90AE90AF90B090B1BBF390B290B390B4CCE890B590B6E3AF90B7E3B190B8CFA7E3AE90B9CEA9BBDD90BA90BB90BC90BD90BEB5EBBEE5B2D2B3CD90BFB1B9E3ABB2D1B5ACB9DFB6E890C090C1CFEBE3B790C2BBCC90C390C4C8C7D0CA90C590C690C790C890C9E3B8B3EE90CA90CB90CC90CDEDA990CED3FAD3E490CF90D090D1EDAAE3B9D2E290D290D390D490D590D6E3B590D790D890D990DAD3DE90DB90DC90DD90DEB8D0E3B390DF90E0E3B6B7DF90E1E3B4C0A290E290E390E4E3BA90E590E690E790E890E990EA90EB90EC90ED90EE90EF90F090F190F290F390F490F590F690F7D4B890F890F990FA90FB90FC90FD90FE9140B4C89141E3BB9142BBC59143C9F791449145C9E5914691479148C4BD9149914A914B914C914D914E914FEDAB9150915191529153C2FD9154915591569157BBDBBFAE91589159915A915B915C915D915ECEBF915F916091619162E3BC9163BFB6916491659166916791689169916A916B916C916D916E916F9170917191729173917491759176B1EF91779178D4F79179917A917B917C917DE3BE917E9180918191829183918491859186EDAD918791889189918A918B918C918D918E918FE3BFBAA9EDAC91909191E3BD91929193919491959196919791989199919A919BE3C0919C919D919E919F91A091A1BAB691A291A391A4B6AE91A591A691A791A891A9D0B891AAB0C3EDAE91AB91AC91AD91AE91AFEDAFC0C191B0E3C191B191B291B391B491B591B691B791B891B991BA91BB91BC91BD91BE91BF91C091C1C5B391C291C391C491C591C691C791C891C991CA91CB91CC91CD91CE91CFE3C291D091D191D291D391D491D591D691D791D8DCB291D991DA91DB91DC91DD91DEEDB091DFB8EA91E0CEECEAA7D0E7CAF9C8D6CFB7B3C9CED2BDE491E191E2E3DEBBF2EAA8D5BD91E3C6DDEAA991E491E591E6EAAA91E7EAACEAAB91E8EAAEEAAD91E991EA91EB91ECBDD891EDEAAF91EEC2BE91EF91F091F191F2B4C1B4F791F391F4BBA791F591F691F791F891F9ECE6ECE5B7BFCBF9B1E291FAECE791FB91FC91FDC9C8ECE8ECE991FECAD6DED0B2C5D4FA92409241C6CBB0C7B4F2C8D3924292439244CDD092459246BFB8924792489249924A924B924C924DBFDB924E924FC7A4D6B49250C0A9DED1C9A8D1EFC5A4B0E7B3B6C8C592519252B0E292539254B7F692559256C5FA92579258B6F39259D5D2B3D0BCBC925A925B925CB3AD925D925E925F9260BEF1B0D1926192629263926492659266D2D6CAE3D7A59267CDB6B6B6BFB9D5DB9268B8A7C5D79269926A926BDED2BFD9C2D5C7C0926CBBA4B1A8926D926EC5EA926F9270C5FBCCA79271927292739274B1A7927592769277B5D692789279927AC4A8927BDED3D1BAB3E9927CC3F2927D927EB7F79280D6F4B5A3B2F0C4B4C4E9C0ADDED49281B0E8C5C4C1E09282B9D59283BEDCCDD8B0CE9284CDCFDED6BED0D7BEDED5D5D0B0DD92859286C4E292879288C2A3BCF09289D3B5C0B9C5A1B2A6D4F1928A928BC0A8CAC3DED7D5FC928CB9B0928DC8ADCBA9928EDED9BFBD928F929092919292C6B4D7A7CAB0C4C39293B3D6B9D29294929592969297D6B8EAFCB0B492989299929A929BBFE6929C929DCCF4929E929F92A092A1CDDA92A292A392A4D6BFC2CE92A5CECECCA2D0AEC4D3B5B2DED8D5F5BCB7BBD392A692A7B0A492A8C5B2B4EC92A992AA92ABD5F192AC92ADEAFD92AE92AF92B092B192B292B3DEDACDA692B492B5CDEC92B692B792B892B9CEE6DEDC92BACDB1C0A692BB92BCD7BD92BDDEDBB0C6BAB4C9D3C4F3BEE892BE92BF92C092C1B2B692C292C392C492C592C692C792C892C9C0CCCBF092CABCF1BBBBB5B792CB92CC92CDC5F592CEDEE692CF92D092D1DEE3BEDD92D292D3DEDF92D492D592D692D7B4B7BDDD92D892D9DEE0C4ED92DA92DB92DC92DDCFC692DEB5E092DF92E092E192E2B6DECADAB5F4DEE592E3D5C692E4DEE1CCCDC6FE92E5C5C592E692E792E8D2B492E9BEF292EA92EB92EC92ED92EE92EF92F0C2D392F1CCBDB3B892F2BDD392F3BFD8CDC6D1DAB4EB92F4DEE4DEDDDEE792F5EAFE92F692F7C2B0DEE292F892F9D6C0B5A792FAB2F492FBDEE892FCDEF292FD92FE934093419342DEED9343DEF193449345C8E0934693479348D7E1DEEFC3E8CCE19349B2E5934A934B934CD2BE934D934E934F9350935193529353DEEE9354DEEBCED59355B4A79356935793589359935ABFABBEBE935B935CBDD2935D935E935F9360DEE99361D4AE9362DEDE9363DEEA9364936593669367C0BF9368DEECB2F3B8E9C2A79369936ABDC1936B936C936D936E936FDEF5DEF893709371B2ABB4A493729373B4EAC9A6937493759376937793789379DEF6CBD1937AB8E3937BDEF7DEFA937C937D937E9380DEF9938193829383CCC29384B0E1B4EE93859386938793889389938AE5BA938B938C938D938E938FD0AF93909391B2EB9392EBA19393DEF493949395C9E3DEF3B0DAD2A1B1F79396CCAF939793989399939A939B939C939DDEF0939ECBA4939F93A093A1D5AA93A293A393A493A593A6DEFB93A793A893A993AA93AB93AC93AD93AEB4DD93AFC4A693B093B193B2DEFD93B393B493B593B693B793B893B993BA93BB93BCC3FEC4A1DFA193BD93BE93BF93C093C193C293C3C1CC93C4DEFCBEEF93C5C6B293C693C793C893C993CA93CB93CC93CD93CEB3C5C8F693CF93D0CBBADEFE93D193D2DFA493D393D493D593D6D7B293D793D893D993DA93DBB3B793DC93DD93DE93DFC1C393E093E1C7CBB2A5B4E993E2D7AB93E393E493E593E6C4EC93E7DFA2DFA393E8DFA593E9BAB393EA93EB93ECDFA693EDC0DE93EE93EFC9C393F093F193F293F393F493F593F6B2D9C7E693F7DFA793F8C7DC93F993FA93FB93FCDFA8EBA293FD93FE944094419442CBD3944394449445DFAA9446DFA99447B2C194489449944A944B944C944D944E944F9450945194529453945494559456945794589459945A945B945C945D945E945F9460C5CA94619462946394649465946694679468DFAB9469946A946B946C946D946E946F9470D4DC94719472947394749475C8C19476947794789479947A947B947C947D947E948094819482DFAC94839484948594869487BEF094889489DFADD6A7948A948B948C948DEAB7EBB6CAD5948ED8FCB8C4948FB9A594909491B7C5D5FE94929493949494959496B9CA94979498D0A7F4CD9499949AB5D0949B949CC3F4949DBEC8949E949F94A0EBB7B0BD94A194A2BDCC94A3C1B294A4B1D6B3A894A594A694A7B8D2C9A294A894A9B6D894AA94AB94AC94ADEBB8BEB494AE94AF94B0CAFD94B1C7C394B2D5FB94B394B4B7F394B594B694B794B894B994BA94BB94BC94BD94BE94BF94C094C194C294C3CEC494C494C594C6D5ABB1F394C794C894C9ECB3B0DF94CAECB594CB94CC94CDB6B794CEC1CF94CFF5FAD0B194D094D1D5E594D2CED394D394D4BDEFB3E294D5B8AB94D6D5B694D7EDBD94D8B6CF94D9CBB9D0C294DA94DB94DC94DD94DE94DF94E094E1B7BD94E294E3ECB6CAA994E494E594E6C5D494E7ECB9ECB8C2C3ECB794E894E994EA94EBD0FDECBA94ECECBBD7E594ED94EEECBC94EF94F094F1ECBDC6EC94F294F394F494F594F694F794F894F9CEDE94FABCC894FB94FCC8D5B5A9BEC9D6BCD4E794FD94FED1AED0F1EAB8EAB9EABABAB59540954195429543CAB1BFF595449545CDFA9546954795489549954AEAC0954BB0BAEABE954C954DC0A5954E954F9550EABB9551B2FD9552C3F7BBE8955395549555D2D7CEF4EABF955695579558EABC9559955A955BEAC3955CD0C7D3B3955D955E955F9560B4BA9561C3C1D7F29562956395649565D5D19566CAC79567EAC595689569EAC4EAC7EAC6956A956B956C956D956ED6E7956FCFD495709571EACB9572BBCE9573957495759576957795789579BDFAC9CE957A957BEACC957C957DC9B9CFFEEACAD4CEEACDEACF957E9580CDED9581958295839584EAC99585EACE95869587CEEE9588BBDE9589B3BF958A958B958C958D958EC6D5BEB0CEFA958F95909591C7E79592BEA7EAD095939594D6C7959595969597C1C095989599959AD4DD959BEAD1959C959DCFBE959E959F95A095A1EAD295A295A395A495A5CAEE95A695A795A895A9C5AFB0B595AA95AB95AC95AD95AEEAD495AF95B095B195B295B395B495B595B695B7EAD3F4DF95B895B995BA95BB95BCC4BA95BD95BE95BF95C095C1B1A995C295C395C495C5E5DF95C695C795C895C9EAD595CA95CB95CC95CD95CE95CF95D095D195D295D395D495D595D695D795D895D995DA95DB95DC95DD95DE95DF95E095E195E295E3CAEF95E4EAD6EAD7C6D895E595E695E795E895E995EA95EB95ECEAD895ED95EEEAD995EF95F095F195F295F395F4D4BB95F5C7FAD2B7B8FC95F695F7EAC295F8B2DC95F995FAC2FC95FBD4F8CCE6D7EE95FC95FD95FE9640964196429643D4C2D3D0EBC3C5F39644B7FE96459646EBD4964796489649CBB7EBDE964AC0CA964B964C964DCDFB964EB3AF964FC6DA965096519652965396549655EBFC9656C4BE9657CEB4C4A9B1BED4FD9658CAF59659D6EC965A965BC6D3B6E4965C965D965E965FBBFA96609661D0E096629663C9B19664D4D3C8A896659666B8CB9667E8BEC9BC96689669E8BB966AC0EED0D3B2C4B4E5966BE8BC966C966DD5C8966E966F967096719672B6C59673E8BDCAF8B8DCCCF5967496759676C0B496779678D1EEE8BFE8C29679967ABABC967BB1ADBDDC967CEABDE8C3967DE8C6967EE8CB9680968196829683E8CC9684CBC9B0E59685BCAB96869687B9B996889689E8C1968ACDF7968BE8CA968C968D968E968FCEF69690969196929693D5ED9694C1D6E8C49695C3B69696B9FBD6A6E8C8969796989699CAE0D4E6969AE8C0969BE8C5E8C7969CC7B9B7E3969DE8C9969EBFDDE8D2969F96A0E8D796A1E8D5BCDCBCCFE8DB96A296A396A496A596A696A796A896A9E8DE96AAE8DAB1FA96AB96AC96AD96AE96AF96B096B196B296B396B4B0D8C4B3B8CCC6E2C8BEC8E196B596B696B7E8CFE8D4E8D696B8B9F1E8D8D7F596B9C4FB96BAE8DC96BB96BCB2E996BD96BE96BFE8D196C096C1BCED96C296C3BFC2E8CDD6F996C4C1F8B2F196C596C696C796C896C996CA96CB96CCE8DF96CDCAC1E8D996CE96CF96D096D1D5A496D2B1EAD5BBE8CEE8D0B6B0E8D396D3E8DDC0B896D4CAF796D5CBA896D696D7C6DCC0F596D896D996DA96DB96DCE8E996DD96DE96DFD0A396E096E196E296E396E496E596E6E8F2D6EA96E796E896E996EA96EB96EC96EDE8E0E8E196EE96EF96F0D1F9BACBB8F996F196F2B8F1D4D4E8EF96F3E8EEE8ECB9F0CCD2E8E6CEA6BFF296F4B0B8E8F1E8F096F5D7C096F6E8E496F7CDA9C9A396F8BBB8BDDBE8EA96F996FA96FB96FC96FD96FE9740974197429743E8E2E8E3E8E5B5B5E8E7C7C5E8EBE8EDBDB0D7AE9744E8F897459746974797489749974A974B974CE8F5974DCDB0E8F6974E974F9750975197529753975497559756C1BA9757E8E89758C3B7B0F09759975A975B975C975D975E975F9760E8F4976197629763E8F7976497659766B9A3976797689769976A976B976C976D976E976F9770C9D2977197729773C3CECEE0C0E69774977597769777CBF39778CCDDD0B59779977ACAE1977BE8F3977C977D977E9780978197829783978497859786BCEC9787E8F997889789978A978B978C978DC3DE978EC6E5978FB9F79790979197929793B0F497949795D7D897969797BCAC9798C5EF9799979A979B979C979DCCC4979E979FE9A697A097A197A297A397A497A597A697A797A897A9C9AD97AAE9A2C0E297AB97AC97ADBFC397AE97AF97B0E8FEB9D797B1E8FB97B297B397B497B5E9A497B697B797B8D2CE97B997BA97BB97BC97BDE9A397BED6B2D7B597BFE9A797C0BDB797C197C297C397C497C597C697C797C897C997CA97CB97CCE8FCE8FD97CD97CE97CFE9A197D097D197D297D397D497D597D697D7CDD697D897D9D2AC97DA97DB97DCE9B297DD97DE97DF97E0E9A997E197E297E3B4AA97E4B4BB97E597E6E9AB97E797E897E997EA97EB97EC97ED97EE97EF97F097F197F297F397F497F597F697F7D0A897F897F9E9A597FA97FBB3FE97FC97FDE9ACC0E397FEE9AA98409841E9B998429843E9B89844984598469847E9AE98489849E8FA984A984BE9A8984C984D984E984F9850BFACE9B1E9BA98519852C2A5985398549855E9AF9856B8C59857E9AD9858D3DCE9B4E9B5E9B79859985A985BE9C7985C985D985E985F98609861C0C6E9C598629863E9B098649865E9BBB0F19866986798689869986A986B986C986D986E986FE9BCD5A598709871E9BE9872E9BF987398749875E9C198769877C1F198789879C8B6987A987B987CE9BD987D987E988098819882E9C29883988498859886988798889889988AE9C3988BE9B3988CE9B6988DBBB1988E988F9890E9C0989198929893989498959896BCF7989798989899E9C4E9C6989A989B989C989D989E989F98A098A198A298A398A498A5E9CA98A698A798A898A9E9CE98AA98AB98AC98AD98AE98AF98B098B198B298B3B2DB98B4E9C898B598B698B798B898B998BA98BB98BC98BD98BEB7AE98BF98C098C198C298C398C498C598C698C798C898C998CAE9CBE9CC98CB98CC98CD98CE98CF98D0D5C198D1C4A398D298D398D498D598D698D7E9D898D8BAE198D998DA98DB98DCE9C998DDD3A398DE98DF98E0E9D498E198E298E398E498E598E698E7E9D7E9D098E898E998EA98EB98ECE9CF98ED98EEC7C198EF98F098F198F298F398F498F598F6E9D298F798F898F998FA98FB98FC98FDE9D9B3C898FEE9D399409941994299439944CFF0994599469947E9CD99489949994A994B994C994D994E994F995099519952B3F79953995499559956995799589959E9D6995A995BE9DA995C995D995ECCB4995F99609961CFAD99629963996499659966996799689969996AE9D5996BE9DCE9DB996C996D996E996F9970E9DE99719972997399749975997699779978E9D19979997A997B997C997D997E99809981E9DD9982E9DFC3CA9983998499859986998799889989998A998B998C998D998E998F9990999199929993999499959996999799989999999A999B999C999D999E999F99A099A199A299A399A499A599A699A799A899A999AA99AB99AC99AD99AE99AF99B099B199B299B399B499B599B699B799B899B999BA99BB99BC99BD99BE99BF99C099C199C299C399C499C599C699C799C899C999CA99CB99CC99CD99CE99CF99D099D199D299D399D499D599D699D799D899D999DA99DB99DC99DD99DE99DF99E099E199E299E399E499E599E699E799E899E999EA99EB99EC99ED99EE99EF99F099F199F299F399F499F5C7B7B4CEBBB6D0C0ECA399F699F7C5B799F899F999FA99FB99FC99FD99FE9A409A419A42D3FB9A439A449A459A46ECA49A47ECA5C6DB9A489A499A4ABFEE9A4B9A4C9A4D9A4EECA69A4F9A50ECA7D0AA9A51C7B89A529A53B8E89A549A559A569A579A589A599A5A9A5B9A5C9A5D9A5E9A5FECA89A609A619A629A639A649A659A669A67D6B9D5FDB4CBB2BDCEE4C6E79A689A69CDE19A6A9A6B9A6C9A6D9A6E9A6F9A709A719A729A739A749A759A769A77B4F59A78CBC0BCDF9A799A7A9A7B9A7CE9E2E9E3D1EAE9E59A7DB4F9E9E49A7ED1B3CAE2B2D09A80E9E89A819A829A839A84E9E6E9E79A859A86D6B39A879A889A89E9E9E9EA9A8A9A8B9A8C9A8D9A8EE9EB9A8F9A909A919A929A939A949A959A96E9EC9A979A989A999A9A9A9B9A9C9A9D9A9EECAFC5B9B6CE9A9FD2F39AA09AA19AA29AA39AA49AA59AA6B5EE9AA7BBD9ECB19AA89AA9D2E39AAA9AAB9AAC9AAD9AAECEE39AAFC4B89AB0C3BF9AB19AB2B6BED8B9B1C8B1CFB1D1C5FE9AB3B1D09AB4C3AB9AB59AB69AB79AB89AB9D5B19ABA9ABB9ABC9ABD9ABE9ABF9AC09AC1EBA4BAC19AC29AC39AC4CCBA9AC59AC69AC7EBA59AC8EBA79AC99ACA9ACBEBA89ACC9ACD9ACEEBA69ACF9AD09AD19AD29AD39AD49AD5EBA9EBABEBAA9AD69AD79AD89AD99ADAEBAC9ADBCACFD8B5C3F19ADCC3A5C6F8EBADC4CA9ADDEBAEEBAFEBB0B7D59ADE9ADF9AE0B7FA9AE1EBB1C7E29AE2EBB39AE3BAA4D1F5B0B1EBB2EBB49AE49AE59AE6B5AAC2C8C7E89AE7EBB59AE8CBAEE3DF9AE99AEAD3C09AEB9AEC9AED9AEED9DB9AEF9AF0CDA1D6ADC7F39AF19AF29AF3D9E0BBE39AF4BABAE3E29AF59AF69AF79AF89AF9CFAB9AFA9AFB9AFCE3E0C9C79AFDBAB99AFE9B409B41D1B4E3E1C8EAB9AFBDADB3D8CEDB9B429B43CCC09B449B459B46E3E8E3E9CDF49B479B489B499B4A9B4BCCAD9B4CBCB39B4DE3EA9B4EE3EB9B4F9B50D0DA9B519B529B53C6FBB7DA9B549B55C7DFD2CACED69B56E3E4E3EC9B57C9F2B3C19B589B59E3E79B5A9B5BC6E3E3E59B5C9B5DEDB3E3E69B5E9B5F9B609B61C9B39B62C5E69B639B649B65B9B59B66C3BB9B67E3E3C5BDC1A4C2D9B2D79B68E3EDBBA6C4AD9B69E3F0BEDA9B6A9B6BE3FBE3F5BAD39B6C9B6D9B6E9B6FB7D0D3CD9B70D6CED5D3B9C1D5B4D1D89B719B729B739B74D0B9C7F69B759B769B77C8AAB2B49B78C3DA9B799B7A9B7BE3EE9B7C9B7DE3FCE3EFB7A8E3F7E3F49B7E9B809B81B7BA9B829B83C5A29B84E3F6C5DDB2A8C6FC9B85C4E09B869B87D7A29B88C0E1E3F99B899B8AE3FAE3FDCCA9E3F39B8BD3BE9B8CB1C3EDB4E3F1E3F29B8DE3F8D0BAC6C3D4F3E3FE9B8E9B8FBDE09B909B91E4A79B929B93E4A69B949B959B96D1F3E4A39B97E4A99B989B999B9AC8F79B9B9B9C9B9D9B9ECFB49B9FE4A8E4AEC2E59BA09BA1B6B49BA29BA39BA49BA59BA69BA7BDF29BA8E4A29BA99BAABAE9E4AA9BAB9BACE4AC9BAD9BAEB6FDD6DEE4B29BAFE4AD9BB09BB19BB2E4A19BB3BBEECDDDC7A2C5C99BB49BB5C1F79BB6E4A49BB7C7B3BDACBDBDE4A59BB8D7C7B2E29BB9E4ABBCC3E4AF9BBABBEBE4B0C5A8E4B19BBB9BBC9BBD9BBED5E3BFA39BBFE4BA9BC0E4B79BC1E4BB9BC29BC3E4BD9BC49BC5C6D69BC69BC7BAC6C0CB9BC89BC99BCAB8A1E4B49BCB9BCC9BCD9BCED4A19BCF9BD0BAA3BDFE9BD19BD29BD3E4BC9BD49BD59BD69BD79BD8CDBF9BD99BDAC4F99BDB9BDCCFFBC9E69BDD9BDED3BF9BDFCFD19BE09BE1E4B39BE2E4B8E4B9CCE99BE39BE49BE59BE69BE7CCCE9BE8C0D4E4B5C1B0E4B6CED09BE9BBC1B5D39BEAC8F3BDA7D5C7C9ACB8A2E4CA9BEB9BECE4CCD1C49BED9BEED2BA9BEF9BF0BAAD9BF19BF2BAD49BF39BF49BF59BF69BF79BF8E4C3B5ED9BF99BFA9BFBD7CDE4C0CFFDE4BF9BFC9BFD9BFEC1DCCCCA9C409C419C429C43CAE79C449C459C469C47C4D79C48CCD4E4C89C499C4A9C4BE4C7E4C19C4CE4C4B5AD9C4D9C4ED3D99C4FE4C69C509C519C529C53D2F9B4E39C54BBB49C559C56C9EE9C57B4BE9C589C599C5ABBEC9C5BD1CD9C5CCCEDEDB59C5D9C5E9C5F9C609C619C629C639C64C7E59C659C669C679C68D4A89C69E4CBD7D5E4C29C6ABDA5E4C59C6B9C6CD3E69C6DE4C9C9F89C6E9C6FE4BE9C709C71D3E59C729C73C7FEB6C99C74D4FCB2B3E4D79C759C769C77CEC29C78E4CD9C79CEBC9C7AB8DB9C7B9C7CE4D69C7DBFCA9C7E9C809C81D3CE9C82C3EC9C839C849C859C869C879C889C899C8AC5C8E4D89C8B9C8C9C8D9C8E9C8F9C909C919C92CDC4E4CF9C939C949C959C96E4D4E4D59C97BAFE9C98CFE69C999C9AD5BF9C9B9C9C9C9DE4D29C9E9C9F9CA09CA19CA29CA39CA49CA59CA69CA79CA8E4D09CA99CAAE4CE9CAB9CAC9CAD9CAE9CAF9CB09CB19CB29CB39CB49CB59CB69CB79CB89CB9CDE5CAAA9CBA9CBB9CBCC0A39CBDBDA6E4D39CBE9CBFB8C89CC09CC19CC29CC39CC4E4E7D4B49CC59CC69CC79CC89CC99CCA9CCBE4DB9CCC9CCD9CCEC1EF9CCF9CD0E4E99CD19CD2D2E79CD39CD4E4DF9CD5E4E09CD69CD7CFAA9CD89CD99CDA9CDBCBDD9CDCE4DAE4D19CDDE4E59CDEC8DCE4E39CDF9CE0C4E7E4E29CE1E4E19CE29CE39CE4B3FCE4E89CE59CE69CE79CE8B5E19CE99CEA9CEBD7CC9CEC9CED9CEEE4E69CEFBBAC9CF0D7D2CCCFEBF89CF1E4E49CF29CF3B9F69CF49CF59CF6D6CDE4D9E4DCC2FAE4DE9CF7C2CBC0C4C2D09CF8B1F5CCB29CF99CFA9CFB9CFC9CFD9CFE9D409D419D429D43B5CE9D449D459D469D47E4EF9D489D499D4A9D4B9D4C9D4D9D4E9D4FC6AF9D509D519D52C6E19D539D54E4F59D559D569D579D589D59C2A99D5A9D5B9D5CC0ECD1DDE4EE9D5D9D5E9D5F9D609D619D629D639D649D659D66C4AE9D679D689D69E4ED9D6A9D6B9D6C9D6DE4F6E4F4C2FE9D6EE4DD9D6FE4F09D70CAFE9D71D5C49D729D73E4F19D749D759D769D779D789D799D7AD1FA9D7B9D7C9D7D9D7E9D809D819D82E4EBE4EC9D839D849D85E4F29D86CEAB9D879D889D899D8A9D8B9D8C9D8D9D8E9D8F9D90C5CB9D919D929D93C7B19D94C2BA9D959D969D97E4EA9D989D999D9AC1CA9D9B9D9C9D9D9D9E9D9F9DA0CCB6B3B19DA19DA29DA3E4FB9DA4E4F39DA59DA69DA7E4FA9DA8E4FD9DA9E4FC9DAA9DAB9DAC9DAD9DAE9DAF9DB0B3CE9DB19DB29DB3B3BAE4F79DB49DB5E4F9E4F8C5EC9DB69DB79DB89DB99DBA9DBB9DBC9DBD9DBE9DBF9DC09DC19DC2C0BD9DC39DC49DC59DC6D4E89DC79DC89DC99DCA9DCBE5A29DCC9DCD9DCE9DCF9DD09DD19DD29DD39DD49DD59DD6B0C49DD79DD8E5A49DD99DDAE5A39DDB9DDC9DDD9DDE9DDF9DE0BCA49DE1E5A59DE29DE39DE49DE59DE69DE7E5A19DE89DE99DEA9DEB9DEC9DED9DEEE4FEB1F49DEF9DF09DF19DF29DF39DF49DF59DF69DF79DF89DF9E5A89DFAE5A9E5A69DFB9DFC9DFD9DFE9E409E419E429E439E449E459E469E47E5A7E5AA9E489E499E4A9E4B9E4C9E4D9E4E9E4F9E509E519E529E539E549E559E569E579E589E599E5A9E5B9E5C9E5D9E5E9E5F9E609E619E629E639E649E659E669E679E68C6D99E699E6A9E6B9E6C9E6D9E6E9E6F9E70E5ABE5AD9E719E729E739E749E759E769E77E5AC9E789E799E7A9E7B9E7C9E7D9E7E9E809E819E829E839E849E859E869E879E889E89E5AF9E8A9E8B9E8CE5AE9E8D9E8E9E8F9E909E919E929E939E949E959E969E979E989E999E9A9E9B9E9C9E9D9E9EB9E09E9F9EA0E5B09EA19EA29EA39EA49EA59EA69EA79EA89EA99EAA9EAB9EAC9EAD9EAEE5B19EAF9EB09EB19EB29EB39EB49EB59EB69EB79EB89EB99EBABBF0ECE1C3F09EBBB5C6BBD29EBC9EBD9EBE9EBFC1E9D4EE9EC0BEC49EC19EC29EC3D7C69EC4D4D6B2D3ECBE9EC59EC69EC79EC8EAC19EC99ECA9ECBC2AFB4B69ECC9ECD9ECED1D79ECF9ED09ED1B3B49ED2C8B2BFBBECC09ED39ED4D6CB9ED59ED6ECBFECC19ED79ED89ED99EDA9EDB9EDC9EDD9EDE9EDF9EE09EE19EE29EE3ECC5BEE6CCBFC5DABEBC9EE4ECC69EE5B1FE9EE69EE79EE8ECC4D5A8B5E39EE9ECC2C1B6B3E39EEA9EEBECC3CBB8C0C3CCFE9EEC9EED9EEE9EEFC1D29EF0ECC89EF19EF29EF39EF49EF59EF69EF79EF89EF99EFA9EFB9EFC9EFDBAE6C0D39EFED6F29F409F419F42D1CC9F439F449F459F46BFBE9F47B7B3C9D5ECC7BBE29F48CCCCBDFDC8C89F49CFA99F4A9F4B9F4C9F4D9F4E9F4F9F50CDE99F51C5EB9F529F539F54B7E99F559F569F579F589F599F5A9F5B9F5C9F5D9F5E9F5FD1C9BAB89F609F619F629F639F64ECC99F659F66ECCA9F67BBC0ECCB9F68ECE2B1BAB7D99F699F6A9F6B9F6C9F6D9F6E9F6F9F709F719F729F73BDB99F749F759F769F779F789F799F7A9F7BECCCD1E6ECCD9F7C9F7D9F7E9F80C8BB9F819F829F839F849F859F869F879F889F899F8A9F8B9F8C9F8D9F8EECD19F8F9F909F919F92ECD39F93BBCD9F94BCE59F959F969F979F989F999F9A9F9B9F9C9F9D9F9E9F9F9FA09FA1ECCF9FA2C9B79FA39FA49FA59FA69FA7C3BA9FA8ECE3D5D5ECD09FA99FAA9FAB9FAC9FADD6F39FAE9FAF9FB0ECD2ECCE9FB19FB29FB39FB4ECD49FB5ECD59FB69FB7C9BF9FB89FB99FBA9FBB9FBC9FBDCFA89FBE9FBF9FC09FC19FC2D0DC9FC39FC49FC59FC6D1AC9FC79FC89FC99FCAC8DB9FCB9FCC9FCDECD6CEF59FCE9FCF9FD09FD19FD2CAECECDA9FD39FD49FD59FD69FD79FD89FD9ECD99FDA9FDB9FDCB0BE9FDD9FDE9FDF9FE09FE19FE2ECD79FE3ECD89FE49FE59FE6ECE49FE79FE89FE99FEA9FEB9FEC9FED9FEE9FEFC8BC9FF09FF19FF29FF39FF49FF59FF69FF79FF89FF9C1C79FFA9FFB9FFC9FFD9FFEECDCD1E0A040A041A042A043A044A045A046A047A048A049ECDBA04AA04BA04CA04DD4EFA04EECDDA04FA050A051A052A053A054DBC6A055A056A057A058A059A05AA05BA05CA05DA05EECDEA05FA060A061A062A063A064A065A066A067A068A069A06AB1ACA06BA06CA06DA06EA06FA070A071A072A073A074A075A076A077A078A079A07AA07BA07CA07DA07EA080A081ECDFA082A083A084A085A086A087A088A089A08AA08BECE0A08CD7A6A08DC5C0A08EA08FA090EBBCB0AEA091A092A093BEF4B8B8D2AFB0D6B5F9A094D8B3A095CBACA096E3DDA097A098A099A09AA09BA09CA09DC6ACB0E6A09EA09FA0A0C5C6EBB9A0A1A0A2A0A3A0A4EBBAA0A5A0A6A0A7EBBBA0A8A0A9D1C0A0AAC5A3A0ABEAF2A0ACC4B2A0ADC4B5C0CEA0AEA0AFA0B0EAF3C4C1A0B1CEEFA0B2A0B3A0B4A0B5EAF0EAF4A0B6A0B7C9FCA0B8A0B9C7A3A0BAA0BBA0BCCCD8CEFEA0BDA0BEA0BFEAF5EAF6CFACC0E7A0C0A0C1EAF7A0C2A0C3A0C4A0C5A0C6B6BFEAF8A0C7EAF9A0C8EAFAA0C9A0CAEAFBA0CBA0CCA0CDA0CEA0CFA0D0A0D1A0D2A0D3A0D4A0D5A0D6EAF1A0D7A0D8A0D9A0DAA0DBA0DCA0DDA0DEA0DFA0E0A0E1A0E2C8AEE1EBA0E3B7B8E1ECA0E4A0E5A0E6E1EDA0E7D7B4E1EEE1EFD3CCA0E8A0E9A0EAA0EBA0ECA0EDA0EEE1F1BFF1E1F0B5D2A0EFA0F0A0F1B1B7A0F2A0F3A0F4A0F5E1F3E1F2A0F6BAFCA0F7E1F4A0F8A0F9A0FAA0FBB9B7A0FCBED1A0FDA0FEAA40AA41C4FCAA42BADDBDC6AA43AA44AA45AA46AA47AA48E1F5E1F7AA49AA4AB6C0CFC1CAA8E1F6D5F8D3FCE1F8E1FCE1F9AA4BAA4CE1FAC0EAAA4DE1FEE2A1C0C7AA4EAA4FAA50AA51E1FBAA52E1FDAA53AA54AA55AA56AA57AA58E2A5AA59AA5AAA5BC1D4AA5CAA5DAA5EAA5FE2A3AA60E2A8B2FEE2A2AA61AA62AA63C3CDB2C2E2A7E2A6AA64AA65E2A4E2A9AA66AA67E2ABAA68AA69AA6AD0C9D6EDC3A8E2ACAA6BCFD7AA6CAA6DE2AEAA6EAA6FBAEFAA70AA71E9E0E2ADE2AAAA72AA73AA74AA75BBABD4B3AA76AA77AA78AA79AA7AAA7BAA7CAA7DAA7EAA80AA81AA82AA83E2B0AA84AA85E2AFAA86E9E1AA87AA88AA89AA8AE2B1AA8BAA8CAA8DAA8EAA8FAA90AA91AA92E2B2AA93AA94AA95AA96AA97AA98AA99AA9AAA9BAA9CAA9DE2B3CCA1AA9EE2B4AA9FAAA0AB40AB41AB42AB43AB44AB45AB46AB47AB48AB49AB4AAB4BE2B5AB4CAB4DAB4EAB4FAB50D0FEAB51AB52C2CAAB53D3F1AB54CDF5AB55AB56E7E0AB57AB58E7E1AB59AB5AAB5BAB5CBEC1AB5DAB5EAB5FAB60C2EAAB61AB62AB63E7E4AB64AB65E7E3AB66AB67AB68AB69AB6AAB6BCDE6AB6CC3B5AB6DAB6EE7E2BBB7CFD6AB6FC1E1E7E9AB70AB71AB72E7E8AB73AB74E7F4B2A3AB75AB76AB77AB78E7EAAB79E7E6AB7AAB7BAB7CAB7DAB7EE7ECE7EBC9BAAB80AB81D5E4AB82E7E5B7A9E7E7AB83AB84AB85AB86AB87AB88AB89E7EEAB8AAB8BAB8CAB8DE7F3AB8ED6E9AB8FAB90AB91AB92E7EDAB93E7F2AB94E7F1AB95AB96AB97B0E0AB98AB99AB9AAB9BE7F5AB9CAB9DAB9EAB9FABA0AC40AC41AC42AC43AC44AC45AC46AC47AC48AC49AC4AC7F2AC4BC0C5C0EDAC4CAC4DC1F0E7F0AC4EAC4FAC50AC51E7F6CBF6AC52AC53AC54AC55AC56AC57AC58AC59AC5AE8A2E8A1AC5BAC5CAC5DAC5EAC5FAC60D7C1AC61AC62E7FAE7F9AC63E7FBAC64E7F7AC65E7FEAC66E7FDAC67E7FCAC68AC69C1D5C7D9C5FDC5C3AC6AAC6BAC6CAC6DAC6EC7EDAC6FAC70AC71AC72E8A3AC73AC74AC75AC76AC77AC78AC79AC7AAC7BAC7CAC7DAC7EAC80AC81AC82AC83AC84AC85AC86E8A6AC87E8A5AC88E8A7BAF7E7F8E8A4AC89C8F0C9AAAC8AAC8BAC8CAC8DAC8EAC8FAC90AC91AC92AC93AC94AC95AC96E8A9AC97AC98B9E5AC99AC9AAC9BAC9CAC9DD1FEE8A8AC9EAC9FACA0AD40AD41AD42E8AAAD43E8ADE8AEAD44C1A7AD45AD46AD47E8AFAD48AD49AD4AE8B0AD4BAD4CE8ACAD4DE8B4AD4EAD4FAD50AD51AD52AD53AD54AD55AD56AD57AD58E8ABAD59E8B1AD5AAD5BAD5CAD5DAD5EAD5FAD60AD61E8B5E8B2E8B3AD62AD63AD64AD65AD66AD67AD68AD69AD6AAD6BAD6CAD6DAD6EAD6FAD70AD71E8B7AD72AD73AD74AD75AD76AD77AD78AD79AD7AAD7BAD7CAD7DAD7EAD80AD81AD82AD83AD84AD85AD86AD87AD88AD89E8B6AD8AAD8BAD8CAD8DAD8EAD8FAD90AD91AD92B9CFAD93F0ACAD94F0ADAD95C6B0B0EAC8BFAD96CDDFAD97AD98AD99AD9AAD9BAD9CAD9DCECDEAB1AD9EAD9FADA0AE40EAB2AE41C6BFB4C9AE42AE43AE44AE45AE46AE47AE48EAB3AE49AE4AAE4BAE4CD5E7AE4DAE4EAE4FAE50AE51AE52AE53AE54DDF9AE55EAB4AE56EAB5AE57EAB6AE58AE59AE5AAE5BB8CADFB0C9F5AE5CCCF0AE5DAE5EC9FAAE5FAE60AE61AE62AE63C9FBAE64AE65D3C3CBA6AE66B8A6F0AEB1C2AE67E5B8CCEFD3C9BCD7C9EAAE68B5E7AE69C4D0B5E9AE6AEEAEBBADAE6BAE6CE7DEAE6DEEAFAE6EAE6FAE70AE71B3A9AE72AE73EEB2AE74AE75EEB1BDE7AE76EEB0CEB7AE77AE78AE79AE7AC5CFAE7BAE7CAE7DAE7EC1F4DBCEEEB3D0F3AE80AE81AE82AE83AE84AE85AE86AE87C2D4C6E8AE88AE89AE8AB7ACAE8BAE8CAE8DAE8EAE8FAE90AE91EEB4AE92B3EBAE93AE94AE95BBFBEEB5AE96AE97AE98AE99AE9AE7DCAE9BAE9CAE9DEEB6AE9EAE9FBDAEAEA0AF40AF41AF42F1E2AF43AF44AF45CAE8AF46D2C9F0DAAF47F0DBAF48F0DCC1C6AF49B8EDBECEAF4AAF4BF0DEAF4CC5B1F0DDD1F1AF4DF0E0B0CCBDEAAF4EAF4FAF50AF51AF52D2DFF0DFAF53B4AFB7E8F0E6F0E5C6A3F0E1F0E2B4C3AF54AF55F0E3D5EEAF56AF57CCDBBED2BCB2AF58AF59AF5AF0E8F0E7F0E4B2A1AF5BD6A2D3B8BEB7C8ACAF5CAF5DF0EAAF5EAF5FAF60AF61D1F7AF62D6CCBADBF0E9AF63B6BBAF64AF65CDB4AF66AF67C6A6AF68AF69AF6AC1A1F0EBF0EEAF6BF0EDF0F0F0ECAF6CBBBEF0EFAF6DAF6EAF6FAF70CCB5F0F2AF71AF72B3D5AF73AF74AF75AF76B1D4AF77AF78F0F3AF79AF7AF0F4F0F6B4E1AF7BF0F1AF7CF0F7AF7DAF7EAF80AF81F0FAAF82F0F8AF83AF84AF85F0F5AF86AF87AF88AF89F0FDAF8AF0F9F0FCF0FEAF8BF1A1AF8CAF8DAF8ECEC1F1A4AF8FF1A3AF90C1F6F0FBCADDAF91AF92B4F1B1F1CCB1AF93F1A6AF94AF95F1A7AF96AF97F1ACD5CEF1A9AF98AF99C8B3AF9AAF9BAF9CF1A2AF9DF1ABF1A8F1A5AF9EAF9FF1AAAFA0B040B041B042B043B044B045B046B0A9F1ADB047B048B049B04AB04BB04CF1AFB04DF1B1B04EB04FB050B051B052F1B0B053F1AEB054B055B056B057D1A2B058B059B05AB05BB05CB05DB05EF1B2B05FB060B061F1B3B062B063B064B065B066B067B068B069B9EFB06AB06BB5C7B06CB0D7B0D9B06DB06EB06FD4EDB070B5C4B071BDD4BBCAF0A7B072B073B8DEB074B075F0A8B076B077B0A8B078F0A9B079B07ACDEEB07BB07CF0AAB07DB07EB080B081B082B083B084B085B086B087F0ABB088B089B08AB08BB08CB08DB08EB08FB090C6A4B091B092D6E5F1E4B093F1E5B094B095B096B097B098B099B09AB09BB09CB09DC3F3B09EB09FD3DBB0A0B140D6D1C5E8B141D3AFB142D2E6B143B144EEC1B0BBD5B5D1CEBCE0BAD0B145BFF8B146B8C7B5C1C5CCB147B148CAA2B149B14AB14BC3CBB14CB14DB14EB14FB150EEC2B151B152B153B154B155B156B157B158C4BFB6A2B159EDECC3A4B15AD6B1B15BB15CB15DCFE0EDEFB15EB15FC5CEB160B6DCB161B162CAA1B163B164EDEDB165B166EDF0EDF1C3BCB167BFB4B168EDEEB169B16AB16BB16CB16DB16EB16FB170B171B172B173EDF4EDF2B174B175B176B177D5E6C3DFB178EDF3B179B17AB17BEDF6B17CD5A3D1A3B17DB17EB180EDF5B181C3D0B182B183B184B185B186EDF7BFF4BEECEDF8B187CCF7B188D1DBB189B18AB18BD7C5D5F6B18CEDFCB18DB18EB18FEDFBB190B191B192B193B194B195B196B197EDF9EDFAB198B199B19AB19BB19CB19DB19EB19FEDFDBEA6B1A0B240B241B242B243CBAFEEA1B6BDB244EEA2C4C0B245EDFEB246B247BDDEB2C7B248B249B24AB24BB24CB24DB24EB24FB250B251B252B253B6C3B254B255B256EEA5D8BAEEA3EEA6B257B258B259C3E9B3F2B25AB25BB25CB25DB25EB25FEEA7EEA4CFB9B260B261EEA8C2F7B262B263B264B265B266B267B268B269B26AB26BB26CB26DEEA9EEAAB26EDEABB26FB270C6B3B271C7C6B272D6F5B5C9B273CBB2B274B275B276EEABB277B278CDABB279EEACB27AB27BB27CB27DB27ED5B0B280EEADB281F6C4B282B283B284B285B286B287B288B289B28AB28BB28CB28DB28EDBC7B28FB290B291B292B293B294B295B296B297B4A3B298B299B29AC3ACF1E6B29BB29CB29DB29EB29FCAB8D2D3B2A0D6AAB340EFF2B341BED8B342BDC3EFF3B6CCB0ABB343B344B345B346CAAFB347B348EDB6B349EDB7B34AB34BB34CB34DCEF9B7AFBFF3EDB8C2EBC9B0B34EB34FB350B351B352B353EDB9B354B355C6F6BFB3B356B357B358EDBCC5F8B359D1D0B35AD7A9EDBAEDBBB35BD1E2B35CEDBFEDC0B35DEDC4B35EB35FB360EDC8B361EDC6EDCED5E8B362EDC9B363B364EDC7EDBEB365B366C5E9B367B368B369C6C6B36AB36BC9E9D4D2EDC1EDC2EDC3EDC5B36CC0F9B36DB4A1B36EB36FB370B371B9E8B372EDD0B373B374B375B376EDD1B377EDCAB378EDCFB379CEF8B37AB37BCBB6EDCCEDCDB37CB37DB37EB380B381CFF5B382B383B384B385B386B387B388B389B38AB38BB38CB38DEDD2C1F2D3B2EDCBC8B7B38EB38FB390B391B392B393B394B395BCEFB396B397B398B399C5F0B39AB39BB39CB39DB39EB39FB3A0B440B441B442EDD6B443B5EFB444B445C2B5B0ADCBE9B446B447B1AEB448EDD4B449B44AB44BCDEBB5E2B44CEDD5EDD3EDD7B44DB44EB5FAB44FEDD8B450EDD9B451EDDCB452B1CCB453B454B455B456B457B458B459B45AC5F6BCEEEDDACCBCB2EAB45BB45CB45DB45EEDDBB45FB460B461B462C4EBB463B464B4C5B465B466B467B0F5B468B469B46AEDDFC0DAB4E8B46BB46CB46DB46EC5CDB46FB470B471EDDDBFC4B472B473B474EDDEB475B476B477B478B479B47AB47BB47CB47DB47EB480B481B482B483C4A5B484B485B486EDE0B487B488B489B48AB48BEDE1B48CEDE3B48DB48EC1D7B48FB490BBC7B491B492B493B494B495B496BDB8B497B498B499EDE2B49AB49BB49CB49DB49EB49FB4A0B540B541B542B543B544B545EDE4B546B547B548B549B54AB54BB54CB54DB54EB54FEDE6B550B551B552B553B554EDE5B555B556B557B558B559B55AB55BB55CB55DB55EB55FB560B561B562B563EDE7B564B565B566B567B568CABEECEAC0F1B569C9E7B56AECEBC6EEB56BB56CB56DB56EECECB56FC6EDECEDB570B571B572B573B574B575B576B577B578ECF0B579B57AD7E6ECF3B57BB57CECF1ECEEECEFD7A3C9F1CBEEECF4B57DECF2B57EB580CFE9B581ECF6C6B1B582B583B584B585BCC0B586ECF5B587B588B589B58AB58BB58CB58DB5BBBBF6B58EECF7B58FB590B591B592B593D9F7BDFBB594B595C2BBECF8B596B597B598B599ECF9B59AB59BB59CB59DB8A3B59EB59FB5A0B640B641B642B643B644B645B646ECFAB647B648B649B64AB64BB64CB64DB64EB64FB650B651B652ECFBB653B654B655B656B657B658B659B65AB65BB65CB65DECFCB65EB65FB660B661B662D3EDD8AEC0EBB663C7DDBACCB664D0E3CBBDB665CDBAB666B667B8D1B668B669B1FCB66AC7EFB66BD6D6B66CB66DB66EBFC6C3EBB66FB670EFF5B671B672C3D8B673B674B675B676B677B678D7E2B679B67AB67BEFF7B3D3B67CC7D8D1EDB67DD6C8B67EEFF8B680EFF6B681BBFDB3C6B682B683B684B685B686B687B688BDD5B689B68AD2C6B68BBBE0B68CB68DCFA1B68EEFFCEFFBB68FB690EFF9B691B692B693B694B3CCB695C9D4CBB0B696B697B698B699B69AEFFEB69BB69CB0DEB69DB69ED6C9B69FB6A0B740EFFDB741B3EDB742B743F6D5B744B745B746B747B748B749B74AB74BB74CB74DB74EB74FB750B751B752CEC8B753B754B755F0A2B756F0A1B757B5BEBCDABBFCB758B8E5B759B75AB75BB75CB75DB75EC4C2B75FB760B761B762B763B764B765B766B767B768F0A3B769B76AB76BB76CB76DCBEBB76EB76FB770B771B772B773B774B775B776B777B778B779B77AB77BB77CB77DB77EB780B781B782B783B784B785B786F0A6B787B788B789D1A8B78ABEBFC7EEF1B6F1B7BFD5B78BB78CB78DB78EB4A9F1B8CDBBB78FC7D4D5ADB790F1B9B791F1BAB792B793B794B795C7CFB796B797B798D2A4D6CFB799B79AF1BBBDD1B4B0BEBDB79BB79CB79DB4DCCED1B79EBFDFF1BDB79FB7A0B840B841BFFAF1BCB842F1BFB843B844B845F1BEF1C0B846B847B848B849B84AF1C1B84BB84CB84DB84EB84FB850B851B852B853B854B855C1FEB856B857B858B859B85AB85BB85CB85DB85EB85FB860C1A2B861B862B863B864B865B866B867B868B869B86ACAFAB86BB86CD5BEB86DB86EB86FB870BEBABEB9D5C2B871B872BFA2B873CDAFF1B5B874B875B876B877B878B879BDDFB87AB6CBB87BB87CB87DB87EB880B881B882B883B884D6F1F3C3B885B886F3C4B887B8CDB888B889B88AF3C6F3C7B88BB0CAB88CF3C5B88DF3C9CBF1B88EB88FB890F3CBB891D0A6B892B893B1CAF3C8B894B895B896F3CFB897B5D1B898B899F3D7B89AF3D2B89BB89CB89DF3D4F3D3B7FBB89EB1BFB89FF3CEF3CAB5DAB8A0F3D0B940B941F3D1B942F3D5B943B944B945B946F3CDB947BCE3B948C1FDB949F3D6B94AB94BB94CB94DB94EB94FF3DAB950F3CCB951B5C8B952BDEEF3DCB953B954B7A4BFF0D6FECDB2B955B4F0B956B2DFB957F3D8B958F3D9C9B8B959F3DDB95AB95BF3DEB95CF3E1B95DB95EB95FB960B961B962B963B964B965B966B967F3DFB968B969F3E3F3E2B96AB96BF3DBB96CBFEAB96DB3EFB96EF3E0B96FB970C7A9B971BCF2B972B973B974B975F3EBB976B977B978B979B97AB97BB97CB9BFB97DB97EF3E4B980B981B982B2ADBBFEB983CBE3B984B985B986B987F3EDF3E9B988B989B98AB9DCF3EEB98BB98CB98DF3E5F3E6F3EAC2E1F3ECF3EFF3E8BCFDB98EB98FB990CFE4B991B992F3F0B993B994B995F3E7B996B997B998B999B99AB99BB99CB99DF3F2B99EB99FB9A0BA40D7ADC6AABA41BA42BA43BA44F3F3BA45BA46BA47BA48F3F1BA49C2A8BA4ABA4BBA4CBA4DBA4EB8DDF3F5BA4FBA50F3F4BA51BA52BA53B4DBBA54BA55BA56F3F6F3F7BA57BA58BA59F3F8BA5ABA5BBA5CC0BABA5DBA5EC0E9BA5FBA60BA61BA62BA63C5F1BA64BA65BA66BA67F3FBBA68F3FABA69BA6ABA6BBA6CBA6DBA6EBA6FBA70B4D8BA71BA72BA73F3FEF3F9BA74BA75F3FCBA76BA77BA78BA79BA7ABA7BF3FDBA7CBA7DBA7EBA80BA81BA82BA83BA84F4A1BA85BA86BA87BA88BA89BA8AF4A3BBC9BA8BBA8CF4A2BA8DBA8EBA8FBA90BA91BA92BA93BA94BA95BA96BA97BA98BA99F4A4BA9ABA9BBA9CBA9DBA9EBA9FB2BEF4A6F4A5BAA0BB40BB41BB42BB43BB44BB45BB46BB47BB48BB49BCAEBB4ABB4BBB4CBB4DBB4EBB4FBB50BB51BB52BB53BB54BB55BB56BB57BB58BB59BB5ABB5BBB5CBB5DBB5EBB5FBB60BB61BB62BB63BB64BB65BB66BB67BB68BB69BB6ABB6BBB6CBB6DBB6EC3D7D9E1BB6FBB70BB71BB72BB73BB74C0E0F4CCD7D1BB75BB76BB77BB78BB79BB7ABB7BBB7CBB7DBB7EBB80B7DBBB81BB82BB83BB84BB85BB86BB87F4CEC1A3BB88BB89C6C9BB8AB4D6D5B3BB8BBB8CBB8DF4D0F4CFF4D1CBDABB8EBB8FF4D2BB90D4C1D6E0BB91BB92BB93BB94B7E0BB95BB96BB97C1B8BB98BB99C1BBF4D3BEACBB9ABB9BBB9CBB9DBB9EB4E2BB9FBBA0F4D4F4D5BEABBC40BC41F4D6BC42BC43BC44F4DBBC45F4D7F4DABC46BAFDBC47F4D8F4D9BC48BC49BC4ABC4BBC4CBC4DBC4EB8E2CCC7F4DCBC4FB2DABC50BC51C3D3BC52BC53D4E3BFB7BC54BC55BC56BC57BC58BC59BC5AF4DDBC5BBC5CBC5DBC5EBC5FBC60C5B4BC61BC62BC63BC64BC65BC66BC67BC68F4E9BC69BC6ACFB5BC6BBC6CBC6DBC6EBC6FBC70BC71BC72BC73BC74BC75BC76BC77BC78CEC9BC79BC7ABC7BBC7CBC7DBC7EBC80BC81BC82BC83BC84BC85BC86BC87BC88BC89BC8ABC8BBC8CBC8DBC8ECBD8BC8FCBF7BC90BC91BC92BC93BDF4BC94BC95BC96D7CFBC97BC98BC99C0DBBC9ABC9BBC9CBC9DBC9EBC9FBCA0BD40BD41BD42BD43BD44BD45BD46BD47BD48BD49BD4ABD4BBD4CBD4DBD4EBD4FBD50BD51BD52BD53BD54BD55BD56BD57BD58BD59BD5ABD5BBD5CBD5DBD5EBD5FBD60BD61BD62BD63BD64BD65BD66BD67BD68BD69BD6ABD6BBD6CBD6DBD6EBD6FBD70BD71BD72BD73BD74BD75BD76D0F5BD77BD78BD79BD7ABD7BBD7CBD7DBD7EF4EABD80BD81BD82BD83BD84BD85BD86BD87BD88BD89BD8ABD8BBD8CBD8DBD8EBD8FBD90BD91BD92BD93BD94BD95BD96BD97BD98BD99BD9ABD9BBD9CBD9DBD9EBD9FBDA0BE40BE41BE42BE43BE44BE45BE46BE47BE48BE49BE4ABE4BBE4CF4EBBE4DBE4EBE4FBE50BE51BE52BE53F4ECBE54BE55BE56BE57BE58BE59BE5ABE5BBE5CBE5DBE5EBE5FBE60BE61BE62BE63BE64BE65BE66BE67BE68BE69BE6ABE6BBE6CBE6DBE6EBE6FBE70BE71BE72BE73BE74BE75BE76BE77BE78BE79BE7ABE7BBE7CBE7DBE7EBE80BE81BE82BE83BE84BE85BE86BE87BE88BE89BE8ABE8BBE8CBE8DBE8EBE8FBE90BE91BE92BE93BE94BE95BE96BE97BE98BE99BE9ABE9BBE9CBE9DBE9EBE9FBEA0BF40BF41BF42BF43BF44BF45BF46BF47BF48BF49BF4ABF4BBF4CBF4DBF4EBF4FBF50BF51BF52BF53BF54BF55BF56BF57BF58BF59BF5ABF5BBF5CBF5DBF5EBF5FBF60BF61BF62BF63BF64BF65BF66BF67BF68BF69BF6ABF6BBF6CBF6DBF6EBF6FBF70BF71BF72BF73BF74BF75BF76BF77BF78BF79BF7ABF7BBF7CBF7DBF7EBF80F7E3BF81BF82BF83BF84BF85B7B1BF86BF87BF88BF89BF8AF4EDBF8BBF8CBF8DBF8EBF8FBF90BF91BF92BF93BF94BF95BF96BF97BF98BF99BF9ABF9BBF9CBF9DBF9EBF9FBFA0C040C041C042C043C044C045C046C047C048C049C04AC04BC04CC04DC04EC04FC050C051C052C053C054C055C056C057C058C059C05AC05BC05CC05DC05EC05FC060C061C062C063D7EBC064C065C066C067C068C069C06AC06BC06CC06DC06EC06FC070C071C072C073C074C075C076C077C078C079C07AC07BF4EEC07CC07DC07EE6F9BEC0E6FABAECE6FBCFCBE6FCD4BCBCB6E6FDE6FEBCCDC8D2CEB3E7A1C080B4BFE7A2C9B4B8D9C4C9C081D7DDC2DAB7D7D6BDCEC6B7C4C082C083C5A6E7A3CFDFE7A4E7A5E7A6C1B7D7E9C9F0CFB8D6AFD6D5E7A7B0EDE7A8E7A9C9DCD2EFBEADE7AAB0F3C8DEBDE1E7ABC8C6C084E7ACBBE6B8F8D1A4E7ADC2E7BEF8BDCACDB3E7AEE7AFBEEED0E5C085CBE7CCD0BCCCE7B0BCA8D0F7E7B1C086D0F8E7B2E7B3B4C2E7B4E7B5C9FECEACC3E0E7B7B1C1B3F1C087E7B8E7B9D7DBD5C0E7BAC2CCD7BAE7BBE7BCE7BDBCEAC3E5C0C2E7BEE7BFBCA9C088E7C0E7C1E7B6B6D0E7C2C089E7C3E7C4BBBAB5DEC2C6B1E0E7C5D4B5E7C6B8BFE7C8E7C7B7ECC08AE7C9B2F8E7CAE7CBE7CCE7CDE7CEE7CFE7D0D3A7CBF5E7D1E7D2E7D3E7D4C9C9E7D5E7D6E7D7E7D8E7D9BDC9E7DAF3BEC08BB8D7C08CC8B1C08DC08EC08FC090C091C092C093F3BFC094F3C0F3C1C095C096C097C098C099C09AC09BC09CC09DC09EB9DECDF8C09FC0A0D8E8BAB1C140C2DEEEB7C141B7A3C142C143C144C145EEB9C146EEB8B0D5C147C148C149C14AC14BEEBBD5D6D7EFC14CC14DC14ED6C3C14FC150EEBDCAF0C151EEBCC152C153C154C155EEBEC156C157C158C159EEC0C15AC15BEEBFC15CC15DC15EC15FC160C161C162C163D1F2C164C7BCC165C3C0C166C167C168C169C16AB8E1C16BC16CC16DC16EC16FC1E7C170C171F4C6D0DFF4C7C172CFDBC173C174C8BAC175C176F4C8C177C178C179C17AC17BC17CC17DF4C9F4CAC17EF4CBC180C181C182C183C184D9FAB8FEC185C186E5F1D3F0C187F4E0C188CECCC189C18AC18BB3E1C18CC18DC18EC18FF1B4C190D2EEC191F4E1C192C193C194C195C196CFE8F4E2C197C198C7CCC199C19AC19BC19CC19DC19EB5D4B4E4F4E4C19FC1A0C240F4E3F4E5C241C242F4E6C243C244C245C246F4E7C247BAB2B0BFC248F4E8C249C24AC24BC24CC24DC24EC24FB7ADD2EDC250C251C252D2ABC0CFC253BFBCEBA3D5DFEAC8C254C255C256C257F1F3B6F8CBA3C258C259C4CDC25AF1E7C25BF1E8B8FBF1E9BAC4D4C5B0D2C25CC25DF1EAC25EC25FC260F1EBC261F1ECC262C263F1EDF1EEF1EFF1F1F1F0C5D5C264C265C266C267C268C269F1F2C26AB6FAC26BF1F4D2AEDEC7CBCAC26CC26DB3DCC26EB5A2C26FB9A2C270C271C4F4F1F5C272C273F1F6C274C275C276C1C4C1FBD6B0F1F7C277C278C279C27AF1F8C27BC1AAC27CC27DC27EC6B8C280BEDBC281C282C283C284C285C286C287C288C289C28AC28BC28CC28DC28EF1F9B4CFC28FC290C291C292C293C294F1FAC295C296C297C298C299C29AC29BC29CC29DC29EC29FC2A0C340EDB2EDB1C341C342CBE0D2DEC343CBC1D5D8C344C8E2C345C0DFBCA1C346C347C348C349C34AC34BEBC1C34CC34DD0A4C34ED6E2C34FB6C7B8D8EBC0B8CEC350EBBFB3A6B9C9D6ABC351B7F4B7CAC352C353C354BCE7B7BEEBC6C355EBC7B0B9BFCFC356EBC5D3FDC357EBC8C358C359EBC9C35AC35BB7CEC35CEBC2EBC4C9F6D6D7D5CDD0B2EBCFCEB8EBD0C35DB5A8C35EC35FC360C361C362B1B3EBD2CCA5C363C364C365C366C367C368C369C5D6EBD3C36AEBD1C5DFEBCECAA4EBD5B0FBC36BC36CBAFAC36DC36ED8B7F1E3C36FEBCAEBCBEBCCEBCDEBD6E6C0EBD9C370BFE8D2C8EBD7EBDCB8ECEBD8C371BDBAC372D0D8C373B0B7C374EBDDC4DCC375C376C377C378D6ACC379C37AC37BB4E0C37CC37DC2F6BCB9C37EC380EBDAEBDBD4E0C6EAC4D4EBDFC5A7D9F5C381B2B1C382EBE4C383BDC5C384C385C386EBE2C387C388C389C38AC38BC38CC38DC38EC38FC390C391C392C393EBE3C394C395B8ACC396CDD1EBE5C397C398C399EBE1C39AC1B3C39BC39CC39DC39EC39FC6A2C3A0C440C441C442C443C444C445CCF3C446EBE6C447C0B0D2B8EBE7C448C449C44AB8AFB8ADC44BEBE8C7BBCDF3C44CC44DC44EEBEAEBEBC44FC450C451C452C453EBEDC454C455C456C457D0C8C458EBF2C459EBEEC45AC45BC45CEBF1C8F9C45DD1FCEBECC45EC45FEBE9C460C461C462C463B8B9CFD9C4E5EBEFEBF0CCDACDC8B0F2C464EBF6C465C466C467C468C469EBF5C46AB2B2C46BC46CC46DC46EB8E0C46FEBF7C470C471C472C473C474C475B1ECC476C477CCC5C4A4CFA5C478C479C47AC47BC47CEBF9C47DC47EECA2C480C5F2C481EBFAC482C483C484C485C486C487C488C489C9C5C48AC48BC48CC48DC48EC48FE2DFEBFEC490C491C492C493CDCEECA1B1DBD3B7C494C495D2DCC496C497C498EBFDC499EBFBC49AC49BC49CC49DC49EC49FC4A0C540C541C542C543C544C545C546C547C548C549C54AC54BC54CC54DC54EB3BCC54FC550C551EAB0C552C553D7D4C554F4ABB3F4C555C556C557C558C559D6C1D6C2C55AC55BC55CC55DC55EC55FD5E9BECAC560F4A7C561D2A8F4A8F4A9C562F4AABECBD3DFC563C564C565C566C567C9E0C9E1C568C569F3C2C56ACAE6C56BCCF2C56CC56DC56EC56FC570C571E2B6CBB4C572CEE8D6DBC573F4ADF4AEF4AFC574C575C576C577F4B2C578BABDF4B3B0E3F4B0C579F4B1BDA2B2D5C57AF4B6F4B7B6E6B2B0CFCFF4B4B4ACC57BF4B5C57CC57DF4B8C57EC580C581C582C583F4B9C584C585CDA7C586F4BAC587F4BBC588C589C58AF4BCC58BC58CC58DC58EC58FC590C591C592CBD2C593F4BDC594C595C596C597F4BEC598C599C59AC59BC59CC59DC59EC59FF4BFC5A0C640C641C642C643F4DEC1BCBCE8C644C9ABD1DEE5F5C645C646C647C648DCB3D2D5C649C64ADCB4B0ACDCB5C64BC64CBDDAC64DDCB9C64EC64FC650D8C2C651DCB7D3F3C652C9D6DCBADCB6C653DCBBC3A2C654C655C656C657DCBCDCC5DCBDC658C659CEDFD6A5C65ADCCFC65BDCCDC65CC65DDCD2BDE6C2ABC65EDCB8DCCBDCCEDCBEB7D2B0C5DCC7D0BEDCC1BBA8C65FB7BCDCCCC660C661DCC6DCBFC7DBC662C663C664D1BFDCC0C665C666DCCAC667C668DCD0C669C66ACEADDCC2C66BDCC3DCC8DCC9B2D4DCD1CBD5C66CD4B7DCDBDCDFCCA6DCE6C66DC3E7DCDCC66EC66FBFC1DCD9C670B0FAB9B6DCE5DCD3C671DCC4DCD6C8F4BFE0C672C673C674C675C9BBC676C677C678B1BDC679D3A2C67AC67BDCDAC67CC67DDCD5C67EC6BBC680DCDEC681C682C683C684C685D7C2C3AFB7B6C7D1C3A9DCE2DCD8DCEBDCD4C686C687DCDDC688BEA5DCD7C689DCE0C68AC68BDCE3DCE4C68CDCF8C68DC68EDCE1DDA2DCE7C68FC690C691C692C693C694C695C696C697C698BCEBB4C4C699C69AC3A3B2E7DCFAC69BDCF2C69CDCEFC69DDCFCDCEED2F0B2E8C69EC8D7C8E3DCFBC69FDCEDC6A0C740C741DCF7C742C743DCF5C744C745BEA3DCF4C746B2DDC747C748C749C74AC74BDCF3BCF6DCE8BBC4C74CC0F3C74DC74EC74FC750C751BCD4DCE9DCEAC752DCF1DCF6DCF9B5B4C753C8D9BBE7DCFEDCFDD3ABDDA1DDA3DDA5D2F1DDA4DDA6DDA7D2A9C754C755C756C757C758C759C75ABAC9DDA9C75BC75CDDB6DDB1DDB4C75DC75EC75FC760C761C762C763DDB0C6CEC764C765C0F2C766C767C768C769C9AFC76AC76BC76CDCECDDAEC76DC76EC76FC770DDB7C771C772DCF0DDAFC773DDB8C774DDACC775C776C777C778C779C77AC77BDDB9DDB3DDADC4AAC77CC77DC77EC780DDA8C0B3C1ABDDAADDABC781DDB2BBF1DDB5D3A8DDBAC782DDBBC3A7C783C784DDD2DDBCC785C786C787DDD1C788B9BDC789C78ABED5C78BBEFAC78CC78DBACAC78EC78FC790C791DDCAC792DDC5C793DDBFC794C795C796B2CBDDC3C797DDCBB2A4DDD5C798C799C79ADDBEC79BC79CC79DC6D0DDD0C79EC79FC7A0C840C841DDD4C1E2B7C6C842C843C844C845C846DDCEDDCFC847C848C849DDC4C84AC84BC84CDDBDC84DDDCDCCD1C84EDDC9C84FC850C851C852DDC2C3C8C6BCCEAEDDCCC853DDC8C854C855C856C857C858C859DDC1C85AC85BC85CDDC6C2DCC85DC85EC85FC860C861C862D3A9D3AADDD3CFF4C8F8C863C864C865C866C867C868C869C86ADDE6C86BC86CC86DC86EC86FC870DDC7C871C872C873DDE0C2E4C874C875C876C877C878C879C87AC87BDDE1C87CC87DC87EC880C881C882C883C884C885C886DDD7C887C888C889C88AC88BD6F8C88CDDD9DDD8B8F0DDD6C88DC88EC88FC890C6CFC891B6ADC892C893C894C895C896DDE2C897BAF9D4E1DDE7C898C899C89AB4D0C89BDDDAC89CBFFBDDE3C89DDDDFC89EDDDDC89FC8A0C940C941C942C943C944B5D9C945C946C947C948DDDBDDDCDDDEC949BDAFDDE4C94ADDE5C94BC94CC94DC94EC94FC950C951C952DDF5C953C3C9C954C955CBE2C956C957C958C959DDF2C95AC95BC95CC95DC95EC95FC960C961C962C963C964C965C966D8E1C967C968C6D1C969DDF4C96AC96BC96CD5F4DDF3DDF0C96DC96EDDECC96FDDEFC970DDE8C971C972D0EEC973C974C975C976C8D8DDEEC977C978DDE9C979C97ADDEACBF2C97BDDEDC97CC97DB1CDC97EC980C981C982C983C984C0B6C985BCBBDDF1C986C987DDF7C988DDF6DDEBC989C98AC98BC98CC98DC5EEC98EC98FC990DDFBC991C992C993C994C995C996C997C998C999C99AC99BDEA4C99CC99DDEA3C99EC99FC9A0CA40CA41CA42CA43CA44CA45CA46CA47CA48DDF8CA49CA4ACA4BCA4CC3EFCA4DC2FBCA4ECA4FCA50D5E1CA51CA52CEB5CA53CA54CA55CA56DDFDCA57B2CCCA58CA59CA5ACA5BCA5CCA5DCA5ECA5FCA60C4E8CADFCA61CA62CA63CA64CA65CA66CA67CA68CA69CA6AC7BEDDFADDFCDDFEDEA2B0AAB1CECA6BCA6CCA6DCA6ECA6FDEACCA70CA71CA72CA73DEA6BDB6C8EFCA74CA75CA76CA77CA78CA79CA7ACA7BCA7CCA7DCA7EDEA1CA80CA81DEA5CA82CA83CA84CA85DEA9CA86CA87CA88CA89CA8ADEA8CA8BCA8CCA8DDEA7CA8ECA8FCA90CA91CA92CA93CA94CA95CA96DEADCA97D4CCCA98CA99CA9ACA9BDEB3DEAADEAECA9CCA9DC0D9CA9ECA9FCAA0CB40CB41B1A1DEB6CB42DEB1CB43CB44CB45CB46CB47CB48CB49DEB2CB4ACB4BCB4CCB4DCB4ECB4FCB50CB51CB52CB53CB54D1A6DEB5CB55CB56CB57CB58CB59CB5ACB5BDEAFCB5CCB5DCB5EDEB0CB5FD0BDCB60CB61CB62DEB4CAEDDEB9CB63CB64CB65CB66CB67CB68DEB8CB69DEB7CB6ACB6BCB6CCB6DCB6ECB6FCB70DEBBCB71CB72CB73CB74CB75CB76CB77BDE5CB78CB79CB7ACB7BCB7CB2D8C3EACB7DCB7EDEBACB80C5BACB81CB82CB83CB84CB85CB86DEBCCB87CB88CB89CB8ACB8BCB8CCB8DCCD9CB8ECB8FCB90CB91B7AACB92CB93CB94CB95CB96CB97CB98CB99CB9ACB9BCB9CCB9DCB9ECB9FCBA0CC40CC41D4E5CC42CC43CC44DEBDCC45CC46CC47CC48CC49DEBFCC4ACC4BCC4CCC4DCC4ECC4FCC50CC51CC52CC53CC54C4A2CC55CC56CC57CC58DEC1CC59CC5ACC5BCC5CCC5DCC5ECC5FCC60CC61CC62CC63CC64CC65CC66CC67CC68DEBECC69DEC0CC6ACC6BCC6CCC6DCC6ECC6FCC70CC71CC72CC73CC74CC75CC76CC77D5BACC78CC79CC7ADEC2CC7BCC7CCC7DCC7ECC80CC81CC82CC83CC84CC85CC86CC87CC88CC89CC8ACC8BF2AEBBA2C2B2C5B0C2C7CC8CCC8DF2AFCC8ECC8FCC90CC91CC92D0E9CC93CC94CC95D3DDCC96CC97CC98EBBDCC99CC9ACC9BCC9CCC9DCC9ECC9FCCA0B3E6F2B0CD40F2B1CD41CD42CAADCD43CD44CD45CD46CD47CD48CD49BAE7F2B3F2B5F2B4CBE4CFBAF2B2CAB4D2CFC2ECCD4ACD4BCD4CCD4DCD4ECD4FCD50CEC3F2B8B0F6F2B7CD51CD52CD53CD54CD55F2BECD56B2CFCD57CD58CD59CD5ACD5BCD5CD1C1F2BACD5DCD5ECD5FCD60CD61F2BCD4E9CD62CD63F2BBF2B6F2BFF2BDCD64F2B9CD65CD66F2C7F2C4F2C6CD67CD68F2CAF2C2F2C0CD69CD6ACD6BF2C5CD6CCD6DCD6ECD6FCD70D6FBCD71CD72CD73F2C1CD74C7F9C9DFCD75F2C8B9C6B5B0CD76CD77F2C3F2C9F2D0F2D6CD78CD79BBD7CD7ACD7BCD7CF2D5CDDCCD7DD6EBCD7ECD80F2D2F2D4CD81CD82CD83CD84B8F2CD85CD86CD87CD88F2CBCD89CD8ACD8BF2CEC2F9CD8CD5DDF2CCF2CDF2CFF2D3CD8DCD8ECD8FF2D9D3BCCD90CD91CD92CD93B6EACD94CAF1CD95B7E4F2D7CD96CD97CD98F2D8F2DAF2DDF2DBCD99CD9AF2DCCD9BCD9CCD9DCD9ED1D1F2D1CD9FCDC9CDA0CECFD6A9CE40F2E3CE41C3DBCE42F2E0CE43CE44C0AFF2ECF2DECE45F2E1CE46CE47CE48F2E8CE49CE4ACE4BCE4CF2E2CE4DCE4EF2E7CE4FCE50F2E6CE51CE52F2E9CE53CE54CE55F2DFCE56CE57F2E4F2EACE58CE59CE5ACE5BCE5CCE5DCE5ED3ACF2E5B2F5CE5FCE60F2F2CE61D0ABCE62CE63CE64CE65F2F5CE66CE67CE68BBC8CE69F2F9CE6ACE6BCE6CCE6DCE6ECE6FF2F0CE70CE71F2F6F2F8F2FACE72CE73CE74CE75CE76CE77CE78CE79F2F3CE7AF2F1CE7BCE7CCE7DBAFBCE7EB5FBCE80CE81CE82CE83F2EFF2F7F2EDF2EECE84CE85CE86F2EBF3A6CE87F3A3CE88CE89F3A2CE8ACE8BF2F4CE8CC8DACE8DCE8ECE8FCE90CE91F2FBCE92CE93CE94F3A5CE95CE96CE97CE98CE99CE9ACE9BC3F8CE9CCE9DCE9ECE9FCEA0CF40CF41CF42F2FDCF43CF44F3A7F3A9F3A4CF45F2FCCF46CF47CF48F3ABCF49F3AACF4ACF4BCF4CCF4DC2DDCF4ECF4FF3AECF50CF51F3B0CF52CF53CF54CF55CF56F3A1CF57CF58CF59F3B1F3ACCF5ACF5BCF5CCF5DCF5EF3AFF2FEF3ADCF5FCF60CF61CF62CF63CF64CF65F3B2CF66CF67CF68CF69F3B4CF6ACF6BCF6CCF6DF3A8CF6ECF6FCF70CF71F3B3CF72CF73CF74F3B5CF75CF76CF77CF78CF79CF7ACF7BCF7CCF7DCF7ED0B7CF80CF81CF82CF83F3B8CF84CF85CF86CF87D9F9CF88CF89CF8ACF8BCF8CCF8DF3B9CF8ECF8FCF90CF91CF92CF93CF94CF95F3B7CF96C8E4F3B6CF97CF98CF99CF9AF3BACF9BCF9CCF9DCF9ECF9FF3BBB4C0CFA0D040D041D042D043D044D045D046D047D048D049D04AD04BD04CD04DEEC3D04ED04FD050D051D052D053F3BCD054D055F3BDD056D057D058D1AAD059D05AD05BF4ACD0C6D05CD05DD05ED05FD060D061D0D0D1DCD062D063D064D065D066D067CFCED068D069BDD6D06AD1C3D06BD06CD06DD06ED06FD070D071BAE2E1E9D2C2F1C2B2B9D072D073B1EDF1C3D074C9C0B3C4D075D9F2D076CBA5D077F1C4D078D079D07AD07BD6D4D07CD07DD07ED080D081F1C5F4C0F1C6D082D4ACF1C7D083B0C0F4C1D084D085F4C2D086D087B4FCD088C5DBD089D08AD08BD08CCCBBD08DD08ED08FD0E4D090D091D092D093D094CDE0D095D096D097D098D099F1C8D09AD9F3D09BD09CD09DD09ED09FD0A0B1BBD140CFAED141D142D143B8A4D144D145D146D147D148F1CAD149D14AD14BD14CF1CBD14DD14ED14FD150B2C3C1D1D151D152D7B0F1C9D153D154F1CCD155D156D157D158F1CED159D15AD15BD9F6D15CD2E1D4A3D15DD15EF4C3C8B9D15FD160D161D162D163F4C4D164D165F1CDF1CFBFE3F1D0D166D167F1D4D168D169D16AD16BD16CD16DD16EF1D6F1D1D16FC9D1C5E1D170D171D172C2E3B9FCD173D174F1D3D175F1D5D176D177D178B9D3D179D17AD17BD17CD17DD17ED180F1DBD181D182D183D184D185BAD6D186B0FDF1D9D187D188D189D18AD18BF1D8F1D2F1DAD18CD18DD18ED18FD190F1D7D191D192D193C8ECD194D195D196D197CDCAF1DDD198D199D19AD19BE5BDD19CD19DD19EF1DCD19FF1DED1A0D240D241D242D243D244D245D246D247D248F1DFD249D24ACFE5D24BD24CD24DD24ED24FD250D251D252D253D254D255D256D257D258D259D25AD25BD25CD25DD25ED25FD260D261D262D263F4C5BDF3D264D265D266D267D268D269F1E0D26AD26BD26CD26DD26ED26FD270D271D272D273D274D275D276D277D278D279D27AD27BD27CD27DF1E1D27ED280D281CEF7D282D2AAD283F1FBD284D285B8B2D286D287D288D289D28AD28BD28CD28DD28ED28FD290D291D292D293D294D295D296D297D298D299D29AD29BD29CD29DD29ED29FD2A0D340D341D342D343D344D345D346D347D348D349D34AD34BD34CD34DD34ED34FD350D351D352D353D354D355D356D357D358D359D35AD35BD35CD35DD35EBCFBB9DBD35FB9E6C3D9CAD3EAE8C0C0BEF5EAE9EAEAEAEBD360EAECEAEDEAEEEAEFBDC7D361D362D363F5FBD364D365D366F5FDD367F5FED368F5FCD369D36AD36BD36CBDE2D36DF6A1B4A5D36ED36FD370D371F6A2D372D373D374F6A3D375D376D377ECB2D378D379D37AD37BD37CD37DD37ED380D381D382D383D384D1D4D385D386D387D388D389D38AD9EAD38BD38CD38DD38ED38FD390D391D392D393D394D395D396D397D398D399D39AD39BD39CD39DD39ED39FD3A0D440D441D442D443D444D445D446D447D448D449D44AD44BD44CD44DD44ED44FD450D451D452D453D454D455D456D457D458D459D45AD45BD45CD45DD45ED45FF6A4D460D461D462D463D464D465D466D467D468EEBAD469D46AD46BD46CD46DD46ED46FD470D471D472D473D474D475D476D477D478D479D47AD47BD47CD47DD47ED480D481D482D483D484D485D486D487D488D489D48AD48BD48CD48DD48ED48FD490D491D492D493D494D495D496D497D498D499D5B2D49AD49BD49CD49DD49ED49FD4A0D540D541D542D543D544D545D546D547D3FECCDCD548D549D54AD54BD54CD54DD54ED54FCAC4D550D551D552D553D554D555D556D557D558D559D55AD55BD55CD55DD55ED55FD560D561D562D563D564D565D566D567D568D569D56AD56BD56CD56DD56ED56FD570D571D572D573D574D575D576D577D578D579D57AD57BD57CD57DD57ED580D581D582D583D584D585D586D587D588D589D58AD58BD58CD58DD58ED58FD590D591D592D593D594D595D596D597D598D599D59AD59BD59CD59DD59ED59FD5A0D640D641D642D643D644D645D646D647D648D649D64AD64BD64CD64DD64ED64FD650D651D652D653D654D655D656D657D658D659D65AD65BD65CD65DD65ED65FD660D661D662E5C0D663D664D665D666D667D668D669D66AD66BD66CD66DD66ED66FD670D671D672D673D674D675D676D677D678D679D67AD67BD67CD67DD67ED680D681F6A5D682D683D684D685D686D687D688D689D68AD68BD68CD68DD68ED68FD690D691D692D693D694D695D696D697D698D699D69AD69BD69CD69DD69ED69FD6A0D740D741D742D743D744D745D746D747D748D749D74AD74BD74CD74DD74ED74FD750D751D752D753D754D755D756D757D758D759D75AD75BD75CD75DD75ED75FBEAFD760D761D762D763D764C6A9D765D766D767D768D769D76AD76BD76CD76DD76ED76FD770D771D772D773D774D775D776D777D778D779D77AD77BD77CD77DD77ED780D781D782D783D784D785D786D787D788D789D78AD78BD78CD78DD78ED78FD790D791D792D793D794D795D796D797D798DAA5BCC6B6A9B8BCC8CFBCA5DAA6DAA7CCD6C8C3DAA8C6FDD799D1B5D2E9D1B6BCC7D79ABDB2BBE4DAA9DAAAD1C8DAABD0EDB6EFC2DBD79BCBCFB7EDC9E8B7C3BEF7D6A4DAACDAADC6C0D7E7CAB6D79CD5A9CBDFD5EFDAAED6DFB4CADAB0DAAFD79DD2EBDAB1DAB2DAB3CAD4DAB4CAABDAB5DAB6B3CFD6EFDAB7BBB0B5AEDAB8DAB9B9EED1AFD2E8DABAB8C3CFEAB2EFDABBDABCD79EBDEBCEDCD3EFDABDCEF3DABED3D5BBE5DABFCBB5CBD0DAC0C7EBD6EEDAC1C5B5B6C1DAC2B7CCBFCEDAC3DAC4CBADDAC5B5F7DAC6C1C2D7BBDAC7CCB8D79FD2EAC4B1DAC8B5FDBBD1DAC9D0B3DACADACBCEBDDACCDACDDACEB2F7DAD1DACFD1E8DAD0C3D5DAD2D7A0DAD3DAD4DAD5D0BBD2A5B0F9DAD6C7ABDAD7BDF7C3A1DAD8DAD9C3FDCCB7DADADADBC0BEC6D7DADCDADDC7B4DADEDADFB9C8D840D841D842D843D844D845D846D847D848BBEDD849D84AD84BD84CB6B9F4F8D84DF4F9D84ED84FCDE3D850D851D852D853D854D855D856D857F5B9D858D859D85AD85BEBE0D85CD85DD85ED85FD860D861CFF3BBBFD862D863D864D865D866D867D868BAC0D4A5D869D86AD86BD86CD86DD86ED86FE1D9D870D871D872D873F5F4B1AAB2F2D874D875D876D877D878D879D87AF5F5D87BD87CF5F7D87DD87ED880BAD1F5F6D881C3B2D882D883D884D885D886D887D888F5F9D889D88AD88BF5F8D88CD88DD88ED88FD890D891D892D893D894D895D896D897D898D899D89AD89BD89CD89DD89ED89FD8A0D940D941D942D943D944D945D946D947D948D949D94AD94BD94CD94DD94ED94FD950D951D952D953D954D955D956D957D958D959D95AD95BD95CD95DD95ED95FD960D961D962D963D964D965D966D967D968D969D96AD96BD96CD96DD96ED96FD970D971D972D973D974D975D976D977D978D979D97AD97BD97CD97DD97ED980D981D982D983D984D985D986D987D988D989D98AD98BD98CD98DD98ED98FD990D991D992D993D994D995D996D997D998D999D99AD99BD99CD99DD99ED99FD9A0DA40DA41DA42DA43DA44DA45DA46DA47DA48DA49DA4ADA4BDA4CDA4DDA4EB1B4D5EAB8BADA4FB9B1B2C6D4F0CFCDB0DCD5CBBBF5D6CAB7B7CCB0C6B6B1E1B9BAD6FCB9E1B7A1BCFAEADAEADBCCF9B9F3EADCB4FBC3B3B7D1BAD8EADDD4F4EADEBCD6BBDFEADFC1DEC2B8D4DFD7CAEAE0EAE1EAE4EAE2EAE3C9DEB8B3B6C4EAE5CAEAC9CDB4CDDA50DA51E2D9C5E2EAE6C0B5DA52D7B8EAE7D7ACC8FCD8D3D8CDD4DEDA53D4F9C9C4D3AEB8D3B3E0DA54C9E2F4F6DA55DA56DA57BAD5DA58F4F7DA59DA5AD7DFDA5BDA5CF4F1B8B0D5D4B8CFC6F0DA5DDA5EDA5FDA60DA61DA62DA63DA64DA65B3C3DA66DA67F4F2B3ACDA68DA69DA6ADA6BD4BDC7F7DA6CDA6DDA6EDA6FDA70F4F4DA71DA72F4F3DA73DA74DA75DA76DA77DA78DA79DA7ADA7BDA7CCCCBDA7DDA7EDA80C8A4DA81DA82DA83DA84DA85DA86DA87DA88DA89DA8ADA8BDA8CDA8DF4F5DA8ED7E3C5BFF5C0DA8FDA90F5BBDA91F5C3DA92F5C2DA93D6BAF5C1DA94DA95DA96D4BEF5C4DA97F5CCDA98DA99DA9ADA9BB0CFB5F8DA9CF5C9F5CADA9DC5DCDA9EDA9FDAA0DB40F5C5F5C6DB41DB42F5C7F5CBDB43BEE0F5C8B8FADB44DB45DB46F5D0F5D3DB47DB48DB49BFE7DB4AB9F2F5BCF5CDDB4BDB4CC2B7DB4DDB4EDB4FCCF8DB50BCF9DB51F5CEF5CFF5D1B6E5F5D2DB52F5D5DB53DB54DB55DB56DB57DB58DB59F5BDDB5ADB5BDB5CF5D4D3BBDB5DB3ECDB5EDB5FCCA4DB60DB61DB62DB63F5D6DB64DB65DB66DB67DB68DB69DB6ADB6BF5D7BEE1F5D8DB6CDB6DCCDFF5DBDB6EDB6FDB70DB71DB72B2C8D7D9DB73F5D9DB74F5DAF5DCDB75F5E2DB76DB77DB78F5E0DB79DB7ADB7BF5DFF5DDDB7CDB7DF5E1DB7EDB80F5DEF5E4F5E5DB81CCE3DB82DB83E5BFB5B8F5E3F5E8CCA3DB84DB85DB86DB87DB88F5E6F5E7DB89DB8ADB8BDB8CDB8DDB8EF5BEDB8FDB90DB91DB92DB93DB94DB95DB96DB97DB98DB99DB9AB1C4DB9BDB9CF5BFDB9DDB9EB5C5B2E4DB9FF5ECF5E9DBA0B6D7DC40F5EDDC41F5EADC42DC43DC44DC45DC46F5EBDC47DC48B4DADC49D4EADC4ADC4BDC4CF5EEDC4DB3F9DC4EDC4FDC50DC51DC52DC53DC54F5EFF5F1DC55DC56DC57F5F0DC58DC59DC5ADC5BDC5CDC5DDC5EF5F2DC5FF5F3DC60DC61DC62DC63DC64DC65DC66DC67DC68DC69DC6ADC6BC9EDB9AADC6CDC6DC7FBDC6EDC6FB6E3DC70DC71DC72DC73DC74DC75DC76CCC9DC77DC78DC79DC7ADC7BDC7CDC7DDC7EDC80DC81DC82DC83DC84DC85DC86DC87DC88DC89DC8AEAA6DC8BDC8CDC8DDC8EDC8FDC90DC91DC92DC93DC94DC95DC96DC97DC98DC99DC9ADC9BDC9CDC9DDC9EDC9FDCA0DD40DD41DD42DD43DD44DD45DD46DD47DD48DD49DD4ADD4BDD4CDD4DDD4EDD4FDD50DD51DD52DD53DD54DD55DD56DD57DD58DD59DD5ADD5BDD5CDD5DDD5EDD5FDD60DD61DD62DD63DD64DD65DD66DD67DD68DD69DD6ADD6BDD6CDD6DDD6EDD6FDD70DD71DD72DD73DD74DD75DD76DD77DD78DD79DD7ADD7BDD7CDD7DDD7EDD80DD81DD82DD83DD84DD85DD86DD87DD88DD89DD8ADD8BDD8CDD8DDD8EDD8FDD90DD91DD92DD93DD94DD95DD96DD97DD98DD99DD9ADD9BDD9CDD9DDD9EDD9FDDA0DE40DE41DE42DE43DE44DE45DE46DE47DE48DE49DE4ADE4BDE4CDE4DDE4EDE4FDE50DE51DE52DE53DE54DE55DE56DE57DE58DE59DE5ADE5BDE5CDE5DDE5EDE5FDE60B3B5D4FEB9ECD0F9DE61E9EDD7AAE9EEC2D6C8EDBAE4E9EFE9F0E9F1D6E1E9F2E9F3E9F5E9F4E9F6E9F7C7E1E9F8D4D8E9F9BDCEDE62E9FAE9FBBDCFE9FCB8A8C1BEE9FDB1B2BBD4B9F5E9FEDE63EAA1EAA2EAA3B7F8BCADDE64CAE4E0CED4AFCFBDD5B7EAA4D5DEEAA5D0C1B9BCDE65B4C7B1D9DE66DE67DE68C0B1DE69DE6ADE6BDE6CB1E6B1E7DE6DB1E8DE6EDE6FDE70DE71B3BDC8E8DE72DE73DE74DE75E5C1DE76DE77B1DFDE78DE79DE7AC1C9B4EFDE7BDE7CC7A8D3D8DE7DC6F9D1B8DE7EB9FDC2F5DE80DE81DE82DE83DE84D3ADDE85D4CBBDFCDE86E5C2B7B5E5C3DE87DE88BBB9D5E2DE89BDF8D4B6CEA5C1ACB3D9DE8ADE8BCCF6DE8CE5C6E5C4E5C8DE8DE5CAE5C7B5CFC6C8DE8EB5FCE5C5DE8FCAF6DE90DE91E5C9DE92DE93DE94C3D4B1C5BCA3DE95DE96DE97D7B7DE98DE99CDCBCBCDCACACCD3E5CCE5CBC4E6DE9ADE9BD1A1D1B7E5CDDE9CE5D0DE9DCDB8D6F0E5CFB5DDDE9ECDBEDE9FE5D1B6BADEA0DF40CDA8B9E4DF41CAC5B3D1CBD9D4ECE5D2B7EADF42DF43DF44E5CEDF45DF46DF47DF48DF49DF4AE5D5B4FEE5D6DF4BDF4CDF4DDF4EDF4FE5D3E5D4DF50D2DDDF51DF52C2DFB1C6DF53D3E2DF54DF55B6DDCBECDF56E5D7DF57DF58D3F6DF59DF5ADF5BDF5CDF5DB1E9DF5EB6F4E5DAE5D8E5D9B5C0DF5FDF60DF61D2C5E5DCDF62DF63E5DEDF64DF65DF66DF67DF68DF69E5DDC7B2DF6AD2A3DF6BDF6CE5DBDF6DDF6EDF6FDF70D4E2D5DADF71DF72DF73DF74DF75E5E0D7F1DF76DF77DF78DF79DF7ADF7BDF7CE5E1DF7DB1DCD1FBDF7EE5E2E5E4DF80DF81DF82DF83E5E3DF84DF85E5E5DF86DF87DF88DF89DF8AD2D8DF8BB5CBDF8CE7DFDF8DDAF5DF8EDAF8DF8FDAF6DF90DAF7DF91DF92DF93DAFAD0CFC4C7DF94DF95B0EEDF96DF97DF98D0B0DF99DAF9DF9AD3CABAAADBA2C7F1DF9BDAFCDAFBC9DBDAFDDF9CDBA1D7DEDAFEC1DADF9DDF9EDBA5DF9FDFA0D3F4E040E041DBA7DBA4E042DBA8E043E044BDBCE045E046E047C0C9DBA3DBA6D6A3E048DBA9E049E04AE04BDBADE04CE04DE04EDBAEDBACBAC2E04FE050E051BFA4DBABE052E053E054DBAAD4C7B2BFE055E056DBAFE057B9F9E058DBB0E059E05AE05BE05CB3BBE05DE05EE05FB5A6E060E061E062E063B6BCDBB1E064E065E066B6F5E067DBB2E068E069E06AE06BE06CE06DE06EE06FE070E071E072E073E074E075E076E077E078E079E07AE07BB1C9E07CE07DE07EE080DBB4E081E082E083DBB3DBB5E084E085E086E087E088E089E08AE08BE08CE08DE08EDBB7E08FDBB6E090E091E092E093E094E095E096DBB8E097E098E099E09AE09BE09CE09DE09EE09FDBB9E0A0E140DBBAE141E142D3CFF4FAC7F5D7C3C5E4F4FCF4FDF4FBE143BEC6E144E145E146E147D0EFE148E149B7D3E14AE14BD4CDCCAAE14CE14DF5A2F5A1BAA8F4FECBD6E14EE14FE150F5A4C0D2E151B3EAE152CDAAF5A5F5A3BDB4F5A8E153F5A9BDCDC3B8BFE1CBE1F5AAE154E155E156F5A6F5A7C4F0E157E158E159E15AE15BF5ACE15CB4BCE15DD7EDE15EB4D7F5ABF5AEE15FE160F5ADF5AFD0D1E161E162E163E164E165E166E167C3D1C8A9E168E169E16AE16BE16CE16DF5B0F5B1E16EE16FE170E171E172E173F5B2E174E175F5B3F5B4F5B5E176E177E178E179F5B7F5B6E17AE17BE17CE17DF5B8E17EE180E181E182E183E184E185E186E187E188E189E18AB2C9E18BD3D4CACDE18CC0EFD6D8D2B0C1BFE18DBDF0E18EE18FE190E191E192E193E194E195E196E197B8AAE198E199E19AE19BE19CE19DE19EE19FE1A0E240E241E242E243E244E245E246E247E248E249E24AE24BE24CE24DE24EE24FE250E251E252E253E254E255E256E257E258E259E25AE25BE25CE25DE25EE25FE260E261E262E263E264E265E266E267E268E269E26AE26BE26CE26DE26EE26FE270E271E272E273E274E275E276E277E278E279E27AE27BE27CE27DE27EE280E281E282E283E284E285E286E287E288E289E28AE28BE28CE28DE28EE28FE290E291E292E293E294E295E296E297E298E299E29AE29BE29CE29DE29EE29FE2A0E340E341E342E343E344E345E346E347E348E349E34AE34BE34CE34DE34EE34FE350E351E352E353E354E355E356E357E358E359E35AE35BE35CE35DE35EE35FE360E361E362E363E364E365E366E367E368E369E36AE36BE36CE36DBCF8E36EE36FE370E371E372E373E374E375E376E377E378E379E37AE37BE37CE37DE37EE380E381E382E383E384E385E386E387F6C6E388E389E38AE38BE38CE38DE38EE38FE390E391E392E393E394E395E396E397E398E399E39AE39BE39CE39DE39EE39FE3A0E440E441E442E443E444E445F6C7E446E447E448E449E44AE44BE44CE44DE44EE44FE450E451E452E453E454E455E456E457E458E459E45AE45BE45CE45DE45EF6C8E45FE460E461E462E463E464E465E466E467E468E469E46AE46BE46CE46DE46EE46FE470E471E472E473E474E475E476E477E478E479E47AE47BE47CE47DE47EE480E481E482E483E484E485E486E487E488E489E48AE48BE48CE48DE48EE48FE490E491E492E493E494E495E496E497E498E499E49AE49BE49CE49DE49EE49FE4A0E540E541E542E543E544E545E546E547E548E549E54AE54BE54CE54DE54EE54FE550E551E552E553E554E555E556E557E558E559E55AE55BE55CE55DE55EE55FE560E561E562E563E564E565E566E567E568E569E56AE56BE56CE56DE56EE56FE570E571E572E573F6C9E574E575E576E577E578E579E57AE57BE57CE57DE57EE580E581E582E583E584E585E586E587E588E589E58AE58BE58CE58DE58EE58FE590E591E592E593E594E595E596E597E598E599E59AE59BE59CE59DE59EE59FF6CAE5A0E640E641E642E643E644E645E646E647E648E649E64AE64BE64CE64DE64EE64FE650E651E652E653E654E655E656E657E658E659E65AE65BE65CE65DE65EE65FE660E661E662F6CCE663E664E665E666E667E668E669E66AE66BE66CE66DE66EE66FE670E671E672E673E674E675E676E677E678E679E67AE67BE67CE67DE67EE680E681E682E683E684E685E686E687E688E689E68AE68BE68CE68DE68EE68FE690E691E692E693E694E695E696E697E698E699E69AE69BE69CE69DF6CBE69EE69FE6A0E740E741E742E743E744E745E746E747F7E9E748E749E74AE74BE74CE74DE74EE74FE750E751E752E753E754E755E756E757E758E759E75AE75BE75CE75DE75EE75FE760E761E762E763E764E765E766E767E768E769E76AE76BE76CE76DE76EE76FE770E771E772E773E774E775E776E777E778E779E77AE77BE77CE77DE77EE780E781E782E783E784E785E786E787E788E789E78AE78BE78CE78DE78EE78FE790E791E792E793E794E795E796E797E798E799E79AE79BE79CE79DE79EE79FE7A0E840E841E842E843E844E845E846E847E848E849E84AE84BE84CE84DE84EF6CDE84FE850E851E852E853E854E855E856E857E858E859E85AE85BE85CE85DE85EE85FE860E861E862E863E864E865E866E867E868E869E86AE86BE86CE86DE86EE86FE870E871E872E873E874E875E876E877E878E879E87AF6CEE87BE87CE87DE87EE880E881E882E883E884E885E886E887E888E889E88AE88BE88CE88DE88EE88FE890E891E892E893E894EEC4EEC5EEC6D5EBB6A4EEC8EEC7EEC9EECAC7A5EECBEECCE895B7B0B5F6EECDEECFE896EECEE897B8C6EED0EED1EED2B6DBB3AED6D3C4C6B1B5B8D6EED3EED4D4BFC7D5BEFBCED9B9B3EED6EED5EED8EED7C5A5EED9EEDAC7AEEEDBC7AFEEDCB2A7EEDDEEDEEEDFEEE0EEE1D7EAEEE2EEE3BCD8EEE4D3CBCCFAB2ACC1E5EEE5C7A6C3ADE898EEE6EEE7EEE8EEE9EEEAEEEBEEECE899EEEDEEEEEEEFE89AE89BEEF0EEF1EEF2EEF4EEF3E89CEEF5CDADC2C1EEF6EEF7EEF8D5A1EEF9CFB3EEFAEEFBE89DEEFCEEFDEFA1EEFEEFA2B8F5C3FAEFA3EFA4BDC2D2BFB2F9EFA5EFA6EFA7D2F8EFA8D6FDEFA9C6CCE89EEFAAEFABC1B4EFACCFFACBF8EFAEEFADB3FAB9F8EFAFEFB0D0E2EFB1EFB2B7E6D0BFEFB3EFB4EFB5C8F1CCE0EFB6EFB7EFB8EFB9EFBAD5E0EFBBB4EDC3AAEFBCE89FEFBDEFBEEFBFE8A0CEFDEFC0C2E0B4B8D7B6BDF5E940CFC7EFC3EFC1EFC2EFC4B6A7BCFCBEE2C3CCEFC5EFC6E941EFC7EFCFEFC8EFC9EFCAC7C2EFF1B6CDEFCBE942EFCCEFCDB6C6C3BEEFCEE943EFD0EFD1EFD2D5F2E944EFD3C4F7E945EFD4C4F8EFD5EFD6B8E4B0F7EFD7EFD8EFD9E946EFDAEFDBEFDCEFDDE947EFDEBEB5EFE1EFDFEFE0E948EFE2EFE3C1CDEFE4EFE5EFE6EFE7EFE8EFE9EFEAEFEBEFECC0D8E949EFEDC1ADEFEEEFEFEFF0E94AE94BCFE2E94CE94DE94EE94FE950E951E952E953B3A4E954E955E956E957E958E959E95AE95BE95CE95DE95EE95FE960E961E962E963E964E965E966E967E968E969E96AE96BE96CE96DE96EE96FE970E971E972E973E974E975E976E977E978E979E97AE97BE97CE97DE97EE980E981E982E983E984E985E986E987E988E989E98AE98BE98CE98DE98EE98FE990E991E992E993E994E995E996E997E998E999E99AE99BE99CE99DE99EE99FE9A0EA40EA41EA42EA43EA44EA45EA46EA47EA48EA49EA4AEA4BEA4CEA4DEA4EEA4FEA50EA51EA52EA53EA54EA55EA56EA57EA58EA59EA5AEA5BC3C5E3C5C9C1E3C6EA5CB1D5CECAB4B3C8F2E3C7CFD0E3C8BCE4E3C9E3CAC3C6D5A2C4D6B9EBCEC5E3CBC3F6E3CCEA5DB7A7B8F3BAD2E3CDE3CED4C4E3CFEA5EE3D0D1CBE3D1E3D2E3D3E3D4D1D6E3D5B2FBC0BBE3D6EA5FC0ABE3D7E3D8E3D9EA60E3DAE3DBEA61B8B7DAE2EA62B6D3EA63DAE4DAE3EA64EA65EA66EA67EA68EA69EA6ADAE6EA6BEA6CEA6DC8EEEA6EEA6FDAE5B7C0D1F4D2F5D5F3BDD7EA70EA71EA72EA73D7E8DAE8DAE7EA74B0A2CDD3EA75DAE9EA76B8BDBCCAC2BDC2A4B3C2DAEAEA77C2AAC4B0BDB5EA78EA79CFDEEA7AEA7BEA7CDAEBC9C2EA7DEA7EEA80EA81EA82B1DDEA83EA84EA85DAECEA86B6B8D4BAEA87B3FDEA88EA89DAEDD4C9CFD5C5E3EA8ADAEEEA8BEA8CEA8DEA8EEA8FDAEFEA90DAF0C1EACCD5CFDDEA91EA92EA93EA94EA95EA96EA97EA98EA99EA9AEA9BEA9CEA9DD3E7C2A1EA9EDAF1EA9FEAA0CBE5EB40DAF2EB41CBE6D2FEEB42EB43EB44B8F4EB45EB46DAF3B0AFCFB6EB47EB48D5CFEB49EB4AEB4BEB4CEB4DEB4EEB4FEB50EB51EB52CBEDEB53EB54EB55EB56EB57EB58EB59EB5ADAF4EB5BEB5CE3C4EB5DEB5EC1A5EB5FEB60F6BFEB61EB62F6C0F6C1C4D1EB63C8B8D1E3EB64EB65D0DBD1C5BCAFB9CDEB66EFF4EB67EB68B4C6D3BAF6C2B3FBEB69EB6AF6C3EB6BEB6CB5F1EB6DEB6EEB6FEB70EB71EB72EB73EB74EB75EB76F6C5EB77EB78EB79EB7AEB7BEB7CEB7DD3EAF6A7D1A9EB7EEB80EB81EB82F6A9EB83EB84EB85F6A8EB86EB87C1E3C0D7EB88B1A2EB89EB8AEB8BEB8CCEEDEB8DD0E8F6ABEB8EEB8FCFF6EB90F6AAD5F0F6ACC3B9EB91EB92EB93BBF4F6AEF6ADEB94EB95EB96C4DEEB97EB98C1D8EB99EB9AEB9BEB9CEB9DCBAAEB9ECFBCEB9FEBA0EC40EC41EC42EC43EC44EC45EC46EC47EC48F6AFEC49EC4AF6B0EC4BEC4CF6B1EC4DC2B6EC4EEC4FEC50EC51EC52B0D4C5F9EC53EC54EC55EC56F6B2EC57EC58EC59EC5AEC5BEC5CEC5DEC5EEC5FEC60EC61EC62EC63EC64EC65EC66EC67EC68EC69C7E0F6A6EC6AEC6BBEB8EC6CEC6DBEB2EC6EB5E5EC6FEC70B7C7EC71BFBFC3D2C3E6EC72EC73D8CCEC74EC75EC76B8EFEC77EC78EC79EC7AEC7BEC7CEC7DEC7EEC80BDF9D1A5EC81B0D0EC82EC83EC84EC85EC86F7B0EC87EC88EC89EC8AEC8BEC8CEC8DEC8EF7B1EC8FEC90EC91EC92EC93D0ACEC94B0B0EC95EC96EC97F7B2F7B3EC98F7B4EC99EC9AEC9BC7CAEC9CEC9DEC9EEC9FECA0ED40ED41BECFED42ED43F7B7ED44ED45ED46ED47ED48ED49ED4AF7B6ED4BB1DEED4CF7B5ED4DED4EF7B8ED4FF7B9ED50ED51ED52ED53ED54ED55ED56ED57ED58ED59ED5AED5BED5CED5DED5EED5FED60ED61ED62ED63ED64ED65ED66ED67ED68ED69ED6AED6BED6CED6DED6EED6FED70ED71ED72ED73ED74ED75ED76ED77ED78ED79ED7AED7BED7CED7DED7EED80ED81CEA4C8CDED82BAABE8B8E8B9E8BABEC2ED83ED84ED85ED86ED87D2F4ED88D4CFC9D8ED89ED8AED8BED8CED8DED8EED8FED90ED91ED92ED93ED94ED95ED96ED97ED98ED99ED9AED9BED9CED9DED9EED9FEDA0EE40EE41EE42EE43EE44EE45EE46EE47EE48EE49EE4AEE4BEE4CEE4DEE4EEE4FEE50EE51EE52EE53EE54EE55EE56EE57EE58EE59EE5AEE5BEE5CEE5DEE5EEE5FEE60EE61EE62EE63EE64EE65EE66EE67EE68EE69EE6AEE6BEE6CEE6DEE6EEE6FEE70EE71EE72EE73EE74EE75EE76EE77EE78EE79EE7AEE7BEE7CEE7DEE7EEE80EE81EE82EE83EE84EE85EE86EE87EE88EE89EE8AEE8BEE8CEE8DEE8EEE8FEE90EE91EE92EE93EE94EE95EE96EE97EE98EE99EE9AEE9BEE9CEE9DEE9EEE9FEEA0EF40EF41EF42EF43EF44EF45D2B3B6A5C7EAF1FCCFEECBB3D0EBE7EFCDE7B9CBB6D9F1FDB0E4CBCCF1FED4A4C2ADC1ECC6C4BEB1F2A1BCD5EF46F2A2F2A3EF47F2A4D2C3C6B5EF48CDC7F2A5EF49D3B1BFC5CCE2EF4AF2A6F2A7D1D5B6EEF2A8F2A9B5DFF2AAF2ABEF4BB2FCF2ACF2ADC8A7EF4CEF4DEF4EEF4FEF50EF51EF52EF53EF54EF55EF56EF57EF58EF59EF5AEF5BEF5CEF5DEF5EEF5FEF60EF61EF62EF63EF64EF65EF66EF67EF68EF69EF6AEF6BEF6CEF6DEF6EEF6FEF70EF71B7E7EF72EF73ECA9ECAAECABEF74ECACEF75EF76C6AEECADECAEEF77EF78EF79B7C9CAB3EF7AEF7BEF7CEF7DEF7EEF80EF81E2B8F7CFEF82EF83EF84EF85EF86EF87EF88EF89EF8AEF8BEF8CEF8DEF8EEF8FEF90EF91EF92EF93EF94EF95EF96EF97EF98EF99EF9AEF9BEF9CEF9DEF9EEF9FEFA0F040F041F042F043F044F7D0F045F046B2CDF047F048F049F04AF04BF04CF04DF04EF04FF050F051F052F053F054F055F056F057F058F059F05AF05BF05CF05DF05EF05FF060F061F062F063F7D1F064F065F066F067F068F069F06AF06BF06CF06DF06EF06FF070F071F072F073F074F075F076F077F078F079F07AF07BF07CF07DF07EF080F081F082F083F084F085F086F087F088F089F7D3F7D2F08AF08BF08CF08DF08EF08FF090F091F092F093F094F095F096E2BBF097BCA2F098E2BCE2BDE2BEE2BFE2C0E2C1B7B9D2FBBDA4CACEB1A5CBC7F099E2C2B6FCC8C4E2C3F09AF09BBDC8F09CB1FDE2C4F09DB6F6E2C5C4D9F09EF09FE2C6CFDAB9DDE2C7C0A1F0A0E2C8B2F6F140E2C9F141C1F3E2CAE2CBC2F8E2CCE2CDE2CECAD7D8B8D9E5CFE3F142F143F144F145F146F147F148F149F14AF14BF14CF0A5F14DF14EDCB0F14FF150F151F152F153F154F155F156F157F158F159F15AF15BF15CF15DF15EF15FF160F161F162F163F164F165F166F167F168F169F16AF16BF16CF16DF16EF16FF170F171F172F173F174F175F176F177F178F179F17AF17BF17CF17DF17EF180F181F182F183F184F185F186F187F188F189F18AF18BF18CF18DF18EF18FF190F191F192F193F194F195F196F197F198F199F19AF19BF19CF19DF19EF19FF1A0F240F241F242F243F244F245F246F247F248F249F24AF24BF24CF24DF24EF24FF250F251F252F253F254F255F256F257F258F259F25AF25BF25CF25DF25EF25FF260F261F262F263F264F265F266F267F268F269F26AF26BF26CF26DF26EF26FF270F271F272F273F274F275F276F277F278F279F27AF27BF27CF27DF27EF280F281F282F283F284F285F286F287F288F289F28AF28BF28CF28DF28EF28FF290F291F292F293F294F295F296F297F298F299F29AF29BF29CF29DF29EF29FF2A0F340F341F342F343F344F345F346F347F348F349F34AF34BF34CF34DF34EF34FF350F351C2EDD4A6CDD4D1B1B3DBC7FDF352B2B5C2BFE6E0CABBE6E1E6E2BED4E6E3D7A4CDD5E6E5BCDDE6E4E6E6E6E7C2EEF353BDBEE6E8C2E6BAA7E6E9F354E6EAB3D2D1E9F355F356BFA5E6EBC6EFE6ECE6EDF357F358E6EEC6ADE6EFF359C9A7E6F0E6F1E6F2E5B9E6F3E6F4C2E2E6F5E6F6D6E8E6F7F35AE6F8B9C7F35BF35CF35DF35EF35FF360F361F7BBF7BAF362F363F364F365F7BEF7BCBAA1F366F7BFF367F7C0F368F369F36AF7C2F7C1F7C4F36BF36CF7C3F36DF36EF36FF370F371F7C5F7C6F372F373F374F375F7C7F376CBE8F377F378F379F37AB8DFF37BF37CF37DF37EF380F381F7D4F382F7D5F383F384F385F386F7D6F387F388F389F38AF7D8F38BF7DAF38CF7D7F38DF38EF38FF390F391F392F393F394F395F7DBF396F7D9F397F398F399F39AF39BF39CF39DD7D7F39EF39FF3A0F440F7DCF441F442F443F444F445F446F7DDF447F448F449F7DEF44AF44BF44CF44DF44EF44FF450F451F452F453F454F7DFF455F456F457F7E0F458F459F45AF45BF45CF45DF45EF45FF460F461F462DBCBF463F464D8AAF465F466F467F468F469F46AF46BF46CE5F7B9EDF46DF46EF46FF470BFFDBBEAF7C9C6C7F7C8F471F7CAF7CCF7CBF472F473F474F7CDF475CEBAF476F7CEF477F478C4A7F479F47AF47BF47CF47DF47EF480F481F482F483F484F485F486F487F488F489F48AF48BF48CF48DF48EF48FF490F491F492F493F494F495F496F497F498F499F49AF49BF49CF49DF49EF49FF4A0F540F541F542F543F544F545F546F547F548F549F54AF54BF54CF54DF54EF54FF550F551F552F553F554F555F556F557F558F559F55AF55BF55CF55DF55EF55FF560F561F562F563F564F565F566F567F568F569F56AF56BF56CF56DF56EF56FF570F571F572F573F574F575F576F577F578F579F57AF57BF57CF57DF57EF580F581F582F583F584F585F586F587F588F589F58AF58BF58CF58DF58EF58FF590F591F592F593F594F595F596F597F598F599F59AF59BF59CF59DF59EF59FF5A0F640F641F642F643F644F645F646F647F648F649F64AF64BF64CF64DF64EF64FF650F651F652F653F654F655F656F657F658F659F65AF65BF65CF65DF65EF65FF660F661F662F663F664F665F666F667F668F669F66AF66BF66CF66DF66EF66FF670F671F672F673F674F675F676F677F678F679F67AF67BF67CF67DF67EF680F681F682F683F684F685F686F687F688F689F68AF68BF68CF68DF68EF68FF690F691F692F693F694F695F696F697F698F699F69AF69BF69CF69DF69EF69FF6A0F740F741F742F743F744F745F746F747F748F749F74AF74BF74CF74DF74EF74FF750F751F752F753F754F755F756F757F758F759F75AF75BF75CF75DF75EF75FF760F761F762F763F764F765F766F767F768F769F76AF76BF76CF76DF76EF76FF770F771F772F773F774F775F776F777F778F779F77AF77BF77CF77DF77EF780D3E3F781F782F6CFF783C2B3F6D0F784F785F6D1F6D2F6D3F6D4F786F787F6D6F788B1ABF6D7F789F6D8F6D9F6DAF78AF6DBF6DCF78BF78CF78DF78EF6DDF6DECFCAF78FF6DFF6E0F6E1F6E2F6E3F6E4C0F0F6E5F6E6F6E7F6E8F6E9F790F6EAF791F6EBF6ECF792F6EDF6EEF6EFF6F0F6F1F6F2F6F3F6F4BEA8F793F6F5F6F6F6F7F6F8F794F795F796F797F798C8FAF6F9F6FAF6FBF6FCF799F79AF6FDF6FEF7A1F7A2F7A3F7A4F7A5F79BF79CF7A6F7A7F7A8B1EEF7A9F7AAF7ABF79DF79EF7ACF7ADC1DBF7AEF79FF7A0F7AFF840F841F842F843F844F845F846F847F848F849F84AF84BF84CF84DF84EF84FF850F851F852F853F854F855F856F857F858F859F85AF85BF85CF85DF85EF85FF860F861F862F863F864F865F866F867F868F869F86AF86BF86CF86DF86EF86FF870F871F872F873F874F875F876F877F878F879F87AF87BF87CF87DF87EF880F881F882F883F884F885F886F887F888F889F88AF88BF88CF88DF88EF88FF890F891F892F893F894F895F896F897F898F899F89AF89BF89CF89DF89EF89FF8A0F940F941F942F943F944F945F946F947F948F949F94AF94BF94CF94DF94EF94FF950F951F952F953F954F955F956F957F958F959F95AF95BF95CF95DF95EF95FF960F961F962F963F964F965F966F967F968F969F96AF96BF96CF96DF96EF96FF970F971F972F973F974F975F976F977F978F979F97AF97BF97CF97DF97EF980F981F982F983F984F985F986F987F988F989F98AF98BF98CF98DF98EF98FF990F991F992F993F994F995F996F997F998F999F99AF99BF99CF99DF99EF99FF9A0FA40FA41FA42FA43FA44FA45FA46FA47FA48FA49FA4AFA4BFA4CFA4DFA4EFA4FFA50FA51FA52FA53FA54FA55FA56FA57FA58FA59FA5AFA5BFA5CFA5DFA5EFA5FFA60FA61FA62FA63FA64FA65FA66FA67FA68FA69FA6AFA6BFA6CFA6DFA6EFA6FFA70FA71FA72FA73FA74FA75FA76FA77FA78FA79FA7AFA7BFA7CFA7DFA7EFA80FA81FA82FA83FA84FA85FA86FA87FA88FA89FA8AFA8BFA8CFA8DFA8EFA8FFA90FA91FA92FA93FA94FA95FA96FA97FA98FA99FA9AFA9BFA9CFA9DFA9EFA9FFAA0FB40FB41FB42FB43FB44FB45FB46FB47FB48FB49FB4AFB4BFB4CFB4DFB4EFB4FFB50FB51FB52FB53FB54FB55FB56FB57FB58FB59FB5AFB5BC4F1F0AFBCA6F0B0C3F9FB5CC5B8D1BBFB5DF0B1F0B2F0B3F0B4F0B5D1BCFB5ED1ECFB5FF0B7F0B6D4A7FB60CDD2F0B8F0BAF0B9F0BBF0BCFB61FB62B8EBF0BDBAE8FB63F0BEF0BFBEE9F0C0B6ECF0C1F0C2F0C3F0C4C8B5F0C5F0C6FB64F0C7C5F4FB65F0C8FB66FB67FB68F0C9FB69F0CAF7BDFB6AF0CBF0CCF0CDFB6BF0CEFB6CFB6DFB6EFB6FF0CFBAD7FB70F0D0F0D1F0D2F0D3F0D4F0D5F0D6F0D8FB71FB72D3A5F0D7FB73F0D9FB74FB75FB76FB77FB78FB79FB7AFB7BFB7CFB7DF5BAC2B9FB7EFB80F7E4FB81FB82FB83FB84F7E5F7E6FB85FB86F7E7FB87FB88FB89FB8AFB8BFB8CF7E8C2B4FB8DFB8EFB8FFB90FB91FB92FB93FB94FB95F7EAFB96F7EBFB97FB98FB99FB9AFB9BFB9CC2F3FB9DFB9EFB9FFBA0FC40FC41FC42FC43FC44FC45FC46FC47FC48F4F0FC49FC4AFC4BF4EFFC4CFC4DC2E9FC4EF7E1F7E2FC4FFC50FC51FC52FC53BBC6FC54FC55FC56FC57D9E4FC58FC59FC5ACAF2C0E8F0A4FC5BBADAFC5CFC5DC7ADFC5EFC5FFC60C4ACFC61FC62F7ECF7EDF7EEFC63F7F0F7EFFC64F7F1FC65FC66F7F4FC67F7F3FC68F7F2F7F5FC69FC6AFC6BFC6CF7F6FC6DFC6EFC6FFC70FC71FC72FC73FC74FC75EDE9FC76EDEAEDEBFC77F6BCFC78FC79FC7AFC7BFC7CFC7DFC7EFC80FC81FC82FC83FC84F6BDFC85F6BEB6A6FC86D8BEFC87FC88B9C4FC89FC8AFC8BD8BBFC8CDCB1FC8DFC8EFC8FFC90FC91FC92CAF3FC93F7F7FC94FC95FC96FC97FC98FC99FC9AFC9BFC9CF7F8FC9DFC9EF7F9FC9FFCA0FD40FD41FD42FD43FD44F7FBFD45F7FAFD46B1C7FD47F7FCF7FDFD48FD49FD4AFD4BFD4CF7FEFD4DFD4EFD4FFD50FD51FD52FD53FD54FD55FD56FD57C6EBECB4FD58FD59FD5AFD5BFD5CFD5DFD5EFD5FFD60FD61FD62FD63FD64FD65FD66FD67FD68FD69FD6AFD6BFD6CFD6DFD6EFD6FFD70FD71FD72FD73FD74FD75FD76FD77FD78FD79FD7AFD7BFD7CFD7DFD7EFD80FD81FD82FD83FD84FD85B3DDF6B3FD86FD87F6B4C1E4F6B5F6B6F6B7F6B8F6B9F6BAC8A3F6BBFD88FD89FD8AFD8BFD8CFD8DFD8EFD8FFD90FD91FD92FD93C1FAB9A8EDE8FD94FD95FD96B9EAD9DFFD97FD98FD99FD9AFD9'; + + for (var i = 0; i < str.length; i++) { + var c = str.charAt(i), + code = str.charCodeAt(i); + if (c == " ") strOut += "+"; + else if (code >= 19968 && code <= 40869) { + var index = code - 19968; + strOut += "%" + z.substr(index * 4, 2) + "%" + z.substr(index * 4 + 2, 2); + } else { + strOut += "%" + str.charCodeAt(i).toString(16); + } + } + return strOut; + }, + /* 改变图片大小 */ + scale: function (img, w, h) { + var ow = img.width, + oh = img.height; + + if (ow >= oh) { + img.width = w * ow / oh; + img.height = h; + img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px'; + } else { + img.width = w; + img.height = h * oh / ow; + img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px'; + } + }, + getImageData: function(){ + var _this = this, + key = $G('searchTxt').value, + type = $G('searchType').value, + keepOriginName = editor.options.keepOriginName ? "1" : "0", + url = "http://image.baidu.com/i?ct=201326592&cl=2&lm=-1&st=-1&tn=baiduimagejson&istype=2&rn=32&fm=index&pv=&word=" + _this.encodeToGb2312(key) + type + "&keeporiginname=" + keepOriginName + "&" + +new Date; + + $G('searchListUl').innerHTML = lang.searchLoading; + ajax.request(url, { + 'dataType': 'jsonp', + 'charset': 'GB18030', + 'onsuccess':function(json){ + var list = []; + if(json && json.data) { + for(var i = 0; i < json.data.length; i++) { + if(json.data[i].objURL) { + list.push({ + title: json.data[i].fromPageTitleEnc, + src: json.data[i].objURL, + url: json.data[i].fromURL + }); + } + } + } + _this.setList(list); + }, + 'onerror':function(){ + $G('searchListUl').innerHTML = lang.searchRetry; + } + }); + }, + /* 添加图片到列表界面上 */ + setList: function (list) { + var i, item, p, img, link, _this = this, + listUl = $G('searchListUl'); + + listUl.innerHTML = ''; + if(list.length) { + for (i = 0; i < list.length; i++) { + item = document.createElement('li'); + p = document.createElement('p'); + img = document.createElement('img'); + link = document.createElement('a'); + + img.onload = function () { + _this.scale(this, 113, 113); + }; + img.width = 113; + img.setAttribute('src', list[i].src); + + link.href = list[i].url; + link.target = '_blank'; + link.title = list[i].title; + link.innerHTML = list[i].title; + + p.appendChild(img); + item.appendChild(p); + item.appendChild(link); + listUl.appendChild(item); + } + } else { + listUl.innerHTML = lang.searchRetry; + } + }, + getInsertList: function () { + var child, + src, + align = getAlign(), + list = [], + items = $G('searchListUl').children; + for(var i = 0; i < items.length; i++) { + child = items[i].firstChild && items[i].firstChild.firstChild; + if(child.tagName && child.tagName.toLowerCase() == 'img' && domUtils.hasClass(items[i], 'selected')) { + src = child.src; + list.push({ + src: src, + _src: src, + alt: src.substr(src.lastIndexOf('/') + 1), + floatStyle: align + }); + } + } + return list; + } + }; + +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/alignicon.jpg b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/alignicon.jpg new file mode 100644 index 000000000..754755b1b Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/alignicon.jpg differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/bg.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/bg.png new file mode 100644 index 000000000..580be0a01 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/bg.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/icons.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/icons.gif new file mode 100644 index 000000000..78459dea7 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/icons.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/icons.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/icons.png new file mode 100644 index 000000000..12e470016 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/icons.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/image.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/image.png new file mode 100644 index 000000000..19699f6a9 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/image.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/progress.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/progress.png new file mode 100644 index 000000000..717c4865c Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/progress.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/success.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/success.gif new file mode 100644 index 000000000..8d4f3112b Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/success.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/success.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/success.png new file mode 100644 index 000000000..94f968dc8 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/image/images/success.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/insertframe/insertframe.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/insertframe/insertframe.html new file mode 100644 index 000000000..7f1f3e9a1 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/insertframe/insertframe.html @@ -0,0 +1,98 @@ + + + + + + + + + +
        + + + + + + + + + + + + + + + + + + + +
        + + +
        px
        px
        + +
        +
        + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/internal.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/internal.js new file mode 100644 index 000000000..44dc17fbf --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/internal.js @@ -0,0 +1,81 @@ +(function () { + var parent = window.parent; + //dialog对象 + dialog = parent.$EDITORUI[window.frameElement.id.replace( /_iframe$/, '' )]; + //当前打开dialog的编辑器实例 + editor = dialog.editor; + + UE = parent.UE; + + domUtils = UE.dom.domUtils; + + utils = UE.utils; + + browser = UE.browser; + + ajax = UE.ajax; + + $G = function ( id ) { + return document.getElementById( id ) + }; + //focus元素 + $focus = function ( node ) { + setTimeout( function () { + if ( browser.ie ) { + var r = node.createTextRange(); + r.collapse( false ); + r.select(); + } else { + node.focus() + } + }, 0 ) + }; + utils.loadFile(document,{ + href:editor.options.themePath + editor.options.theme + "/dialogbase.css?cache="+Math.random(), + tag:"link", + type:"text/css", + rel:"stylesheet" + }); + lang = editor.getLang(dialog.className.split( "-" )[2]); + if(lang){ + domUtils.on(window,'load',function () { + + var langImgPath = editor.options.langPath + editor.options.lang + "/images/"; + //针对静态资源 + for ( var i in lang["static"] ) { + var dom = $G( i ); + if(!dom) continue; + var tagName = dom.tagName, + content = lang["static"][i]; + if(content.src){ + //clone + content = utils.extend({},content,false); + content.src = langImgPath + content.src; + } + if(content.style){ + content = utils.extend({},content,false); + content.style = content.style.replace(/url\s*\(/g,"url(" + langImgPath) + } + switch ( tagName.toLowerCase() ) { + case "var": + dom.parentNode.replaceChild( document.createTextNode( content ), dom ); + break; + case "select": + var ops = dom.options; + for ( var j = 0, oj; oj = ops[j]; ) { + oj.innerHTML = content.options[j++]; + } + for ( var p in content ) { + p != "options" && dom.setAttribute( p, content[p] ); + } + break; + default : + domUtils.setAttributes( dom, content); + } + } + } ); + } + + +})(); + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/link/link.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/link/link.html new file mode 100644 index 000000000..55ab4d1e2 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/link/link.html @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/map/map.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/map/map.html new file mode 100644 index 000000000..e763b8eb0 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/map/map.html @@ -0,0 +1,135 @@ + + + + + + + + + + +
        + + + + + + + + + +
        ::
        +
        + +
        + + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/map/show.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/map/show.html new file mode 100644 index 000000000..329cfebfb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/map/show.html @@ -0,0 +1,118 @@ + + + + + + + 百度地图API自定义地图 + + + + + + + +
        + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/music/music.css b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/music/music.css new file mode 100644 index 000000000..8fb7a94c3 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/music/music.css @@ -0,0 +1,30 @@ +.wrapper{margin: 5px 10px;} + +.searchBar{height:30px;padding:7px 0 3px;text-align:center;} +.searchBtn{font-size:13px;height:24px;} + +.resultBar{width:460px;margin:5px auto;border: 1px solid #CCC;border-radius: 5px;box-shadow: 2px 2px 5px #D3D6DA;overflow: hidden;} + +.listPanel{overflow: hidden;} +.panelon{display:block;} +.paneloff{display:none} + +.page{width:220px;margin:20px auto;overflow: hidden;} +.pageon{float:right;width:24px;line-height:24px;height:24px;margin-right: 5px;background: none;border: none;color: #000;font-weight: bold;text-align:center} +.pageoff{float:right;width:24px;line-height:24px;height:24px;cursor:pointer;background-color: #fff; + border: 1px solid #E7ECF0;color: #2D64B3;margin-right: 5px;text-decoration: none;text-align:center;} + +.m-box{width:460px;} +.m-m{float: left;line-height: 20px;height: 20px;} +.m-h{height:24px;line-height:24px;padding-left: 46px;background-color:#FAFAFA;border-bottom: 1px solid #DAD8D8;font-weight: bold;font-size: 12px;color: #333;} +.m-l{float:left;width:40px; } +.m-t{float:left;width:140px;} +.m-s{float:left;width:110px;} +.m-z{float:left;width:100px;} +.m-try-t{float: left;width: 60px;;} + +.m-try{float:left;width:20px;height:20px;background:url('http://static.tieba.baidu.com/tb/editor/images/try_music.gif') no-repeat ;} +.m-trying{float:left;width:20px;height:20px;background:url('http://static.tieba.baidu.com/tb/editor/images/stop_music.gif') no-repeat ;} + +.loading{width:95px;height:7px;font-size:7px;margin:60px auto;background:url(http://static.tieba.baidu.com/tb/editor/images/loading.gif) no-repeat} +.empty{width:300px;height:40px;padding:2px;margin:50px auto;line-height:40px; color:#006699;text-align:center;} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/music/music.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/music/music.html new file mode 100644 index 000000000..e7ef04f39 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/music/music.html @@ -0,0 +1,32 @@ + + + + + 插入音乐 + + + + +
        + +
        + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/music/music.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/music/music.js new file mode 100644 index 000000000..1c538bf66 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/music/music.js @@ -0,0 +1,192 @@ +function Music() { + this.init(); +} +(function () { + var pages = [], + panels = [], + selectedItem = null; + Music.prototype = { + total:70, + pageSize:10, + dataUrl:"http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.search.common", + playerUrl:"http://box.baidu.com/widget/flash/bdspacesong.swf", + + init:function () { + var me = this; + domUtils.on($G("J_searchName"), "keyup", function (event) { + var e = window.event || event; + if (e.keyCode == 13) { + me.dosearch(); + } + }); + domUtils.on($G("J_searchBtn"), "click", function () { + me.dosearch(); + }); + }, + callback:function (data) { + var me = this; + me.data = data.song_list; + setTimeout(function () { + $G('J_resultBar').innerHTML = me._renderTemplate(data.song_list); + }, 300); + }, + dosearch:function () { + var me = this; + selectedItem = null; + var key = $G('J_searchName').value; + if (utils.trim(key) == "")return false; + key = encodeURIComponent(key); + me._sent(key); + }, + doselect:function (i) { + var me = this; + if (typeof i == 'object') { + selectedItem = i; + } else if (typeof i == 'number') { + selectedItem = me.data[i]; + } + }, + onpageclick:function (id) { + var me = this; + for (var i = 0; i < pages.length; i++) { + $G(pages[i]).className = 'pageoff'; + $G(panels[i]).className = 'paneloff'; + } + $G('page' + id).className = 'pageon'; + $G('panel' + id).className = 'panelon'; + }, + listenTest:function (elem) { + var me = this, + view = $G('J_preview'), + is_play_action = (elem.className == 'm-try'), + old_trying = me._getTryingElem(); + + if (old_trying) { + old_trying.className = 'm-try'; + view.innerHTML = ''; + } + if (is_play_action) { + elem.className = 'm-trying'; + view.innerHTML = me._buildMusicHtml(me._getUrl(true)); + } + }, + _sent:function (param) { + var me = this; + $G('J_resultBar').innerHTML = '
        '; + + utils.loadFile(document, { + src:me.dataUrl + '&query=' + param + '&page_size=' + me.total + '&callback=music.callback&.r=' + Math.random(), + tag:"script", + type:"text/javascript", + defer:"defer" + }); + }, + _removeHtml:function (str) { + var reg = /<\s*\/?\s*[^>]*\s*>/gi; + return str.replace(reg, ""); + }, + _getUrl:function (isTryListen) { + var me = this; + var param = 'from=tiebasongwidget&url=&name=' + encodeURIComponent(me._removeHtml(selectedItem.title)) + '&artist=' + + encodeURIComponent(me._removeHtml(selectedItem.author)) + '&extra=' + + encodeURIComponent(me._removeHtml(selectedItem.album_title)) + + '&autoPlay='+isTryListen+'' + '&loop=true'; + return me.playerUrl + "?" + param; + }, + _getTryingElem:function () { + var s = $G('J_listPanel').getElementsByTagName('span'); + + for (var i = 0; i < s.length; i++) { + if (s[i].className == 'm-trying') + return s[i]; + } + return null; + }, + _buildMusicHtml:function (playerUrl) { + var html = ' 12) + return s.substring(0, 5) + '...'; + if (!s) s = " "; + return s; + }, + _rebuildData:function (data) { + var me = this, + newData = [], + d = me.pageSize, + itembox; + for (var i = 0; i < data.length; i++) { + if ((i + d) % d == 0) { + itembox = []; + newData.push(itembox) + } + itembox.push(data[i]); + } + return newData; + }, + _renderTemplate:function (data) { + var me = this; + if (data.length == 0)return '
        ' + lang.emptyTxt + '
        '; + data = me._rebuildData(data); + var s = [], p = [], t = []; + s.push('
        '); + p.push('
        '); + for (var i = 0, tmpList; tmpList = data[i++];) { + panels.push('panel' + i); + pages.push('page' + i); + if (i == 1) { + s.push('
        '); + if (data.length != 1) { + t.push('
        ' + (i ) + '
        '); + } + } else { + s.push('
        '); + t.push('
        ' + (i ) + '
        '); + } + s.push('
        '); + s.push('
        ' + lang.chapter + '' + lang.singer + + '' + lang.special + '' + lang.listenTest + '
        '); + for (var j = 0, tmpObj; tmpObj = tmpList[j++];) { + s.push(''); + } + s.push('
        '); + s.push('
        '); + } + t.reverse(); + p.push(t.join('')); + s.push('
        '); + p.push('
        '); + return s.join('') + p.join(''); + }, + exec:function () { + var me = this; + if (selectedItem == null) return; + $G('J_preview').innerHTML = ""; + editor.execCommand('music', { + url:me._getUrl(false), + width:400, + height:95 + }); + } + }; +})(); + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/preview/preview.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/preview/preview.html new file mode 100644 index 000000000..f6b433bcf --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/preview/preview.html @@ -0,0 +1,40 @@ + + + + + + + + + + +
        + +
        + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/addimg.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/addimg.png new file mode 100644 index 000000000..03a87135b Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/addimg.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/brush.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/brush.png new file mode 100644 index 000000000..efa6fdb01 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/brush.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/delimg.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/delimg.png new file mode 100644 index 000000000..5a892e40a Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/delimg.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/delimgH.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/delimgH.png new file mode 100644 index 000000000..2f0c5c9de Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/delimgH.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/empty.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/empty.png new file mode 100644 index 000000000..037519625 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/empty.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/emptyH.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/emptyH.png new file mode 100644 index 000000000..838ca7231 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/emptyH.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/eraser.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/eraser.png new file mode 100644 index 000000000..63e87cecb Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/eraser.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/redo.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/redo.png new file mode 100644 index 000000000..12cd9bbef Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/redo.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/redoH.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/redoH.png new file mode 100644 index 000000000..d9f33d38a Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/redoH.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/scale.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/scale.png new file mode 100644 index 000000000..935a3f3e1 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/scale.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/scaleH.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/scaleH.png new file mode 100644 index 000000000..72e64a9d0 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/scaleH.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/size.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/size.png new file mode 100644 index 000000000..836684505 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/size.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/undo.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/undo.png new file mode 100644 index 000000000..084c7cc73 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/undo.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/undoH.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/undoH.png new file mode 100644 index 000000000..fde7eb3c2 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/images/undoH.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/scrawl.css b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/scrawl.css new file mode 100644 index 000000000..b18430dc5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/scrawl.css @@ -0,0 +1,72 @@ +/*common +*/ +body{margin: 0;} +table{width:100%;} +table td{padding:2px 4px;vertical-align: middle;} +a{text-decoration: none;} +em{font-style: normal;} +.border_style1{border: 1px solid #ccc;border-radius: 5px;box-shadow:2px 2px 5px #d3d6da;} +/*module +*/ +.main{margin: 8px;overflow: hidden;} + +.hot{float:left;height:335px;} +.drawBoard{position: relative; cursor: crosshair;} +.brushBorad{position: absolute;left:0;top:0;z-index: 998;} +.picBoard{border: none;text-align: center;line-height: 300px;cursor: default;} +.operateBar{margin-top:10px;font-size:12px;text-align: center;} +.operateBar span{margin-left: 10px;} + +.drawToolbar{float:right;width:110px;height:300px;overflow: hidden;} +.colorBar{margin-top:10px;font-size: 12px;text-align: center;} +.colorBar a{display:block;width: 10px;height: 10px;border:1px solid #1006F1;border-radius: 3px; box-shadow:2px 2px 5px #d3d6da;opacity: 0.3} +.sectionBar{margin-top:15px;font-size: 12px;text-align: center;} +.sectionBar a{display:inline-block;width:10px;height:12px;color: #888;text-indent: -999px;opacity: 0.3} +.size1{background: url('images/size.png') 1px center no-repeat ;} +.size2{background: url('images/size.png') -10px center no-repeat;} +.size3{background: url('images/size.png') -22px center no-repeat;} +.size4{background: url('images/size.png') -35px center no-repeat;} + +.addImgH{position: relative;} +.addImgH_form{position: absolute;left: 18px;top: -1px;width: 75px;height: 21px;opacity: 0;cursor: pointer;} +.addImgH_form input{width: 100%;} +/*scrawl遮罩层 +*/ +.maskLayerNull{display: none;} +.maskLayer{position: absolute;top:0;left:0;width: 100%; height: 100%;opacity: 0.7; + background-color: #fff;text-align:center;font-weight:bold;line-height:300px;z-index: 1000;} +/*btn state +*/ +.previousStepH .icon{display: inline-block;width:16px;height:16px;background-image: url('images/undoH.png');cursor: pointer;} +.previousStepH .text{color:#888;cursor:pointer;} +.previousStep .icon{display: inline-block;width:16px;height:16px;background-image: url('images/undo.png');cursor:default;} +.previousStep .text{color:#ccc;cursor:default;} + +.nextStepH .icon{display: inline-block;width:16px;height:16px;background-image: url('images/redoH.png');cursor: pointer;} +.nextStepH .text{color:#888;cursor:pointer;} +.nextStep .icon{display: inline-block;width:16px;height:16px;background-image: url('images/redo.png');cursor:default;} +.nextStep .text{color:#ccc;cursor:default;} + +.clearBoardH .icon{display: inline-block;width:16px;height:16px;background-image: url('images/emptyH.png');cursor: pointer;} +.clearBoardH .text{color:#888;cursor:pointer;} +.clearBoard .icon{display: inline-block;width:16px;height:16px;background-image: url('images/empty.png');cursor:default;} +.clearBoard .text{color:#ccc;cursor:default;} + +.scaleBoardH .icon{display: inline-block;width:16px;height:16px;background-image: url('images/scaleH.png');cursor: pointer;} +.scaleBoardH .text{color:#888;cursor:pointer;} +.scaleBoard .icon{display: inline-block;width:16px;height:16px;background-image: url('images/scale.png');cursor:default;} +.scaleBoard .text{color:#ccc;cursor:default;} + +.removeImgH .icon{display: inline-block;width:16px;height:16px;background-image: url('images/delimgH.png');cursor: pointer;} +.removeImgH .text{color:#888;cursor:pointer;} +.removeImg .icon{display: inline-block;width:16px;height:16px;background-image: url('images/delimg.png');cursor:default;} +.removeImg .text{color:#ccc;cursor:default;} + +.addImgH .icon{vertical-align:top;display: inline-block;width:16px;height:16px;background-image: url('images/addimg.png')} +.addImgH .text{color:#888;cursor:pointer;} +/*icon +*/ +.brushIcon{display: inline-block;width:16px;height:16px;background-image: url('images/brush.png')} +.eraserIcon{display: inline-block;width:16px;height:16px;background-image: url('images/eraser.png')} + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/scrawl.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/scrawl.html new file mode 100644 index 000000000..9371abd7b --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/scrawl.html @@ -0,0 +1,95 @@ + + + + + + + + + + +
        +
        +
        + +
        +
        +
        + + + + + + + + + + + + + + + + +
        +
        +
        +
        +
        + + 1 + 3 + 5 + 7 +
        +
        + + 1 + 3 + 5 + 7 +
        +
        +
        + + +
        + +
        + +
        +
        +
        + + + + +
        +
        +
        +
        + + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/scrawl.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/scrawl.js new file mode 100644 index 000000000..e0c005e75 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/scrawl/scrawl.js @@ -0,0 +1,671 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 12-5-22 + * Time: 上午11:38 + * To change this template use File | Settings | File Templates. + */ +var scrawl = function (options) { + options && this.initOptions(options); +}; +(function () { + var canvas = $G("J_brushBoard"), + context = canvas.getContext('2d'), + drawStep = [], //undo redo存储 + drawStepIndex = 0; //undo redo指针 + + scrawl.prototype = { + isScrawl:false, //是否涂鸦 + brushWidth:-1, //画笔粗细 + brushColor:"", //画笔颜色 + + initOptions:function (options) { + var me = this; + me.originalState(options);//初始页面状态 + me._buildToolbarColor(options.colorList);//动态生成颜色选择集合 + + me._addBoardListener(options.saveNum);//添加画板处理 + me._addOPerateListener(options.saveNum);//添加undo redo clearBoard处理 + me._addColorBarListener();//添加颜色选择处理 + me._addBrushBarListener();//添加画笔大小处理 + me._addEraserBarListener();//添加橡皮大小处理 + me._addAddImgListener();//添加增添背景图片处理 + me._addRemoveImgListenter();//删除背景图片处理 + me._addScalePicListenter();//添加缩放处理 + me._addClearSelectionListenter();//添加清楚选中状态处理 + + me._originalColorSelect(options.drawBrushColor);//初始化颜色选中 + me._originalBrushSelect(options.drawBrushSize);//初始化画笔选中 + me._clearSelection();//清楚选中状态 + }, + + originalState:function (options) { + var me = this; + + me.brushWidth = options.drawBrushSize;//同步画笔粗细 + me.brushColor = options.drawBrushColor;//同步画笔颜色 + + context.lineWidth = me.brushWidth;//初始画笔大小 + context.strokeStyle = me.brushColor;//初始画笔颜色 + context.fillStyle = "transparent";//初始画布背景颜色 + context.lineCap = "round";//去除锯齿 + context.fill(); + }, + _buildToolbarColor:function (colorList) { + var tmp = null, arr = []; + arr.push(""); + for (var i = 0, color; color = colorList[i++];) { + if ((i - 1) % 5 == 0) { + if (i != 1) { + arr.push(""); + } + arr.push(""); + } + tmp = '#' + color; + arr.push(""); + } + arr.push("
        "); + $G("J_colorBar").innerHTML = arr.join(""); + }, + + _addBoardListener:function (saveNum) { + var me = this, + margin = 0, + startX = -1, + startY = -1, + isMouseDown = false, + isMouseMove = false, + isMouseUp = false, + buttonPress = 0, button, flag = ''; + + margin = parseInt(domUtils.getComputedStyle($G("J_wrap"), "margin-left")); + drawStep.push(context.getImageData(0, 0, context.canvas.width, context.canvas.height)); + drawStepIndex += 1; + + domUtils.on(canvas, ["mousedown", "mousemove", "mouseup", "mouseout"], function (e) { + button = browser.webkit ? e.which : buttonPress; + switch (e.type) { + case 'mousedown': + buttonPress = 1; + flag = 1; + isMouseDown = true; + isMouseUp = false; + isMouseMove = false; + me.isScrawl = true; + startX = e.clientX - margin;//10为外边距总和 + startY = e.clientY - margin; + context.beginPath(); + break; + case 'mousemove' : + if (!flag && button == 0) { + return; + } + if (!flag && button) { + startX = e.clientX - margin;//10为外边距总和 + startY = e.clientY - margin; + context.beginPath(); + flag = 1; + } + if (isMouseUp || !isMouseDown) { + return; + } + var endX = e.clientX - margin, + endY = e.clientY - margin; + + context.moveTo(startX, startY); + context.lineTo(endX, endY); + context.stroke(); + startX = endX; + startY = endY; + isMouseMove = true; + break; + case 'mouseup': + buttonPress = 0; + if (!isMouseDown)return; + if (!isMouseMove) { + context.arc(startX, startY, context.lineWidth, 0, Math.PI * 2, false); + context.fillStyle = context.strokeStyle; + context.fill(); + } + context.closePath(); + me._saveOPerate(saveNum); + isMouseDown = false; + isMouseMove = false; + isMouseUp = true; + startX = -1; + startY = -1; + break; + case 'mouseout': + flag = ''; + buttonPress = 0; + if (button == 1) return; + context.closePath(); + break; + } + }); + }, + _addOPerateListener:function (saveNum) { + var me = this; + domUtils.on($G("J_previousStep"), "click", function () { + if (drawStepIndex > 1) { + drawStepIndex -= 1; + context.clearRect(0, 0, context.canvas.width, context.canvas.height); + context.putImageData(drawStep[drawStepIndex - 1], 0, 0); + me.btn2Highlight("J_nextStep"); + drawStepIndex == 1 && me.btn2disable("J_previousStep"); + } + }); + domUtils.on($G("J_nextStep"), "click", function () { + if (drawStepIndex > 0 && drawStepIndex < drawStep.length) { + context.clearRect(0, 0, context.canvas.width, context.canvas.height); + context.putImageData(drawStep[drawStepIndex], 0, 0); + drawStepIndex += 1; + me.btn2Highlight("J_previousStep"); + drawStepIndex == drawStep.length && me.btn2disable("J_nextStep"); + } + }); + domUtils.on($G("J_clearBoard"), "click", function () { + context.clearRect(0, 0, context.canvas.width, context.canvas.height); + drawStep = []; + me._saveOPerate(saveNum); + drawStepIndex = 1; + me.isScrawl = false; + me.btn2disable("J_previousStep"); + me.btn2disable("J_nextStep"); + me.btn2disable("J_clearBoard"); + }); + }, + _addColorBarListener:function () { + var me = this; + domUtils.on($G("J_colorBar"), "click", function (e) { + var target = me.getTarget(e), + color = target.title; + if (!!color) { + me._addColorSelect(target); + + me.brushColor = color; + context.globalCompositeOperation = "source-over"; + context.lineWidth = me.brushWidth; + context.strokeStyle = color; + } + }); + }, + _addBrushBarListener:function () { + var me = this; + domUtils.on($G("J_brushBar"), "click", function (e) { + var target = me.getTarget(e), + size = browser.ie ? target.innerText : target.text; + if (!!size) { + me._addBESelect(target); + + context.globalCompositeOperation = "source-over"; + context.lineWidth = parseInt(size); + context.strokeStyle = me.brushColor; + me.brushWidth = context.lineWidth; + } + }); + }, + _addEraserBarListener:function () { + var me = this; + domUtils.on($G("J_eraserBar"), "click", function (e) { + var target = me.getTarget(e), + size = browser.ie ? target.innerText : target.text; + if (!!size) { + me._addBESelect(target); + + context.lineWidth = parseInt(size); + context.globalCompositeOperation = "destination-out"; + context.strokeStyle = "#FFF"; + } + }); + }, + _addAddImgListener:function () { + var file = $G("J_imgTxt"); + if (!window.FileReader) { + $G("J_addImg").style.display = 'none'; + $G("J_removeImg").style.display = 'none'; + $G("J_sacleBoard").style.display = 'none'; + } + domUtils.on(file, "change", function (e) { + var frm = file.parentNode; + addMaskLayer(lang.backgroundUploading); + + var target = e.target || e.srcElement, + reader = new FileReader(); + reader.onload = function(evt){ + var target = evt.target || evt.srcElement; + ue_callback(target.result, 'SUCCESS'); + }; + reader.readAsDataURL(target.files[0]); + frm.reset(); + }); + }, + _addRemoveImgListenter:function () { + var me = this; + domUtils.on($G("J_removeImg"), "click", function () { + $G("J_picBoard").innerHTML = ""; + me.btn2disable("J_removeImg"); + me.btn2disable("J_sacleBoard"); + }); + }, + _addScalePicListenter:function () { + domUtils.on($G("J_sacleBoard"), "click", function () { + var picBoard = $G("J_picBoard"), + scaleCon = $G("J_scaleCon"), + img = picBoard.children[0]; + + if (img) { + if (!scaleCon) { + picBoard.style.cssText = "position:relative;z-index:999;"+picBoard.style.cssText; + img.style.cssText = "position: absolute;top:" + (canvas.height - img.height) / 2 + "px;left:" + (canvas.width - img.width) / 2 + "px;"; + var scale = new ScaleBoy(); + picBoard.appendChild(scale.init()); + scale.startScale(img); + } else { + if (scaleCon.style.visibility == "visible") { + scaleCon.style.visibility = "hidden"; + picBoard.style.position = ""; + picBoard.style.zIndex = ""; + } else { + scaleCon.style.visibility = "visible"; + picBoard.style.cssText += "position:relative;z-index:999"; + } + } + } + }); + }, + _addClearSelectionListenter:function () { + var doc = document; + domUtils.on(doc, 'mousemove', function (e) { + if (browser.ie && browser.version < 11) + doc.selection.clear(); + else + window.getSelection().removeAllRanges(); + }); + }, + _clearSelection:function () { + var list = ["J_operateBar", "J_colorBar", "J_brushBar", "J_eraserBar", "J_picBoard"]; + for (var i = 0, group; group = list[i++];) { + domUtils.unSelectable($G(group)); + } + }, + + _saveOPerate:function (saveNum) { + var me = this; + if (drawStep.length <= saveNum) { + if(drawStepIndex"); + } + scale.innerHTML = arr.join(""); + return scale; + } + + var rect = [ + //[left, top, width, height] + [1, 1, -1, -1], + [0, 1, 0, -1], + [0, 1, 1, -1], + [1, 0, -1, 0], + [0, 0, 1, 0], + [1, 0, -1, 1], + [0, 0, 0, 1], + [0, 0, 1, 1] + ]; + ScaleBoy.prototype = { + init:function () { + _appendStyle(); + var me = this, + scale = me.dom = _getDom(); + + me.scaleMousemove.fp = me; + domUtils.on(scale, 'mousedown', function (e) { + var target = e.target || e.srcElement; + me.start = {x:e.clientX, y:e.clientY}; + if (target.className.indexOf('hand') != -1) { + me.dir = target.className.replace('hand', ''); + } + domUtils.on(document.body, 'mousemove', me.scaleMousemove); + e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true; + }); + domUtils.on(document.body, 'mouseup', function (e) { + if (me.start) { + domUtils.un(document.body, 'mousemove', me.scaleMousemove); + if (me.moved) { + me.updateScaledElement({position:{x:scale.style.left, y:scale.style.top}, size:{w:scale.style.width, h:scale.style.height}}); + } + delete me.start; + delete me.moved; + delete me.dir; + } + }); + return scale; + }, + startScale:function (objElement) { + var me = this, Idom = me.dom; + + Idom.style.cssText = 'visibility:visible;top:' + objElement.style.top + ';left:' + objElement.style.left + ';width:' + objElement.offsetWidth + 'px;height:' + objElement.offsetHeight + 'px;'; + me.scalingElement = objElement; + }, + updateScaledElement:function (objStyle) { + var cur = this.scalingElement, + pos = objStyle.position, + size = objStyle.size; + if (pos) { + typeof pos.x != 'undefined' && (cur.style.left = pos.x); + typeof pos.y != 'undefined' && (cur.style.top = pos.y); + } + if (size) { + size.w && (cur.style.width = size.w); + size.h && (cur.style.height = size.h); + } + }, + updateStyleByDir:function (dir, offset) { + var me = this, + dom = me.dom, tmp; + + rect['def'] = [1, 1, 0, 0]; + if (rect[dir][0] != 0) { + tmp = parseInt(dom.style.left) + offset.x; + dom.style.left = me._validScaledProp('left', tmp) + 'px'; + } + if (rect[dir][1] != 0) { + tmp = parseInt(dom.style.top) + offset.y; + dom.style.top = me._validScaledProp('top', tmp) + 'px'; + } + if (rect[dir][2] != 0) { + tmp = dom.clientWidth + rect[dir][2] * offset.x; + dom.style.width = me._validScaledProp('width', tmp) + 'px'; + } + if (rect[dir][3] != 0) { + tmp = dom.clientHeight + rect[dir][3] * offset.y; + dom.style.height = me._validScaledProp('height', tmp) + 'px'; + } + if (dir === 'def') { + me.updateScaledElement({position:{x:dom.style.left, y:dom.style.top}}); + } + }, + scaleMousemove:function (e) { + var me = arguments.callee.fp, + start = me.start, + dir = me.dir || 'def', + offset = {x:e.clientX - start.x, y:e.clientY - start.y}; + + me.updateStyleByDir(dir, offset); + arguments.callee.fp.start = {x:e.clientX, y:e.clientY}; + arguments.callee.fp.moved = 1; + }, + _validScaledProp:function (prop, value) { + var ele = this.dom, + wrap = $G("J_picBoard"); + + value = isNaN(value) ? 0 : value; + switch (prop) { + case 'left': + return value < 0 ? 0 : (value + ele.clientWidth) > wrap.clientWidth ? wrap.clientWidth - ele.clientWidth : value; + case 'top': + return value < 0 ? 0 : (value + ele.clientHeight) > wrap.clientHeight ? wrap.clientHeight - ele.clientHeight : value; + case 'width': + return value <= 0 ? 1 : (value + ele.offsetLeft) > wrap.clientWidth ? wrap.clientWidth - ele.offsetLeft : value; + case 'height': + return value <= 0 ? 1 : (value + ele.offsetTop) > wrap.clientHeight ? wrap.clientHeight - ele.offsetTop : value; + } + } + }; +})(); + +//后台回调 +function ue_callback(url, state) { + var doc = document, + picBorard = $G("J_picBoard"), + img = doc.createElement("img"); + + //图片缩放 + function scale(img, max, oWidth, oHeight) { + var width = 0, height = 0, percent, ow = img.width || oWidth, oh = img.height || oHeight; + if (ow > max || oh > max) { + if (ow >= oh) { + if (width = ow - max) { + percent = (width / ow).toFixed(2); + img.height = oh - oh * percent; + img.width = max; + } + } else { + if (height = oh - max) { + percent = (height / oh).toFixed(2); + img.width = ow - ow * percent; + img.height = max; + } + } + } + } + + //移除遮罩层 + removeMaskLayer(); + //状态响应 + if (state == "SUCCESS") { + picBorard.innerHTML = ""; + img.onload = function () { + scale(this, 300); + picBorard.appendChild(img); + + var obj = new scrawl(); + obj.btn2Highlight("J_removeImg"); + //trace 2457 + obj.btn2Highlight("J_sacleBoard"); + }; + img.src = url; + } else { + alert(state); + } +} +//去掉遮罩层 +function removeMaskLayer() { + var maskLayer = $G("J_maskLayer"); + maskLayer.className = "maskLayerNull"; + maskLayer.innerHTML = ""; + dialog.buttons[0].setDisabled(false); +} +//添加遮罩层 +function addMaskLayer(html) { + var maskLayer = $G("J_maskLayer"); + dialog.buttons[0].setDisabled(true); + maskLayer.className = "maskLayer"; + maskLayer.innerHTML = html; +} +//执行确认按钮方法 +function exec(scrawlObj) { + if (scrawlObj.isScrawl) { + addMaskLayer(lang.scrawlUpLoading); + var base64 = scrawlObj.getCanvasData(); + if (!!base64) { + var options = { + timeout:100000, + onsuccess:function (xhr) { + if (!scrawlObj.isCancelScrawl) { + var responseObj; + responseObj = eval("(" + xhr.responseText + ")"); + if (responseObj.state == "SUCCESS") { + var imgObj = {}, + url = editor.options.scrawlUrlPrefix + responseObj.url; + imgObj.src = url; + imgObj._src = url; + imgObj.alt = responseObj.original || ''; + imgObj.title = responseObj.title || ''; + editor.execCommand("insertImage", imgObj); + dialog.close(); + } else { + alert(responseObj.state); + } + + } + }, + onerror:function () { + alert(lang.imageError); + dialog.close(); + } + }; + options[editor.getOpt('scrawlFieldName')] = base64; + + var actionUrl = editor.getActionUrl(editor.getOpt('scrawlActionName')), + params = utils.serializeParam(editor.queryCommandValue('serverparam')) || '', + url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?':'&') + params); + ajax.request(url, options); + } + } else { + addMaskLayer(lang.noScarwl + "   "); + } +} + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/searchreplace/searchreplace.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/searchreplace/searchreplace.html new file mode 100644 index 000000000..b91f19014 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/searchreplace/searchreplace.html @@ -0,0 +1,102 @@ + + + + + + + + + +
        + +
        +
        + + + + + + + + + + + + + + + + + + + + + + +
        :
        + +
        + + +
        +   +
        + +
        +
        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + +
        :
        :
        + +
        + + + + +
        +   +
        + +
        +
        +
        +
        + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/searchreplace/searchreplace.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/searchreplace/searchreplace.js new file mode 100644 index 000000000..1b5285736 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/searchreplace/searchreplace.js @@ -0,0 +1,164 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 12-9-26 + * Time: 下午12:29 + * To change this template use File | Settings | File Templates. + */ + +//清空上次查选的痕迹 +editor.firstForSR = 0; +editor.currentRangeForSR = null; +//给tab注册切换事件 +/** + * tab点击处理事件 + * @param tabHeads + * @param tabBodys + * @param obj + */ +function clickHandler( tabHeads,tabBodys,obj ) { + //head样式更改 + for ( var k = 0, len = tabHeads.length; k < len; k++ ) { + tabHeads[k].className = ""; + } + obj.className = "focus"; + //body显隐 + var tabSrc = obj.getAttribute( "tabSrc" ); + for ( var j = 0, length = tabBodys.length; j < length; j++ ) { + var body = tabBodys[j], + id = body.getAttribute( "id" ); + if ( id != tabSrc ) { + body.style.zIndex = 1; + } else { + body.style.zIndex = 200; + } + } + +} + +/** + * TAB切换 + * @param tabParentId tab的父节点ID或者对象本身 + */ +function switchTab( tabParentId ) { + var tabElements = $G( tabParentId ).children, + tabHeads = tabElements[0].children, + tabBodys = tabElements[1].children; + + for ( var i = 0, length = tabHeads.length; i < length; i++ ) { + var head = tabHeads[i]; + if ( head.className === "focus" )clickHandler(tabHeads,tabBodys, head ); + head.onclick = function () { + clickHandler(tabHeads,tabBodys,this); + } + } +} +$G('searchtab').onmousedown = function(){ + $G('search-msg').innerHTML = ''; + $G('replace-msg').innerHTML = '' +} +//是否区分大小写 +function getMatchCase(id) { + return $G(id).checked ? true : false; +} +//查找 +$G("nextFindBtn").onclick = function (txt, dir, mcase) { + var findtxt = $G("findtxt").value, obj; + if (!findtxt) { + return false; + } + obj = { + searchStr:findtxt, + dir:1, + casesensitive:getMatchCase("matchCase") + }; + if (!frCommond(obj)) { + var bk = editor.selection.getRange().createBookmark(); + $G('search-msg').innerHTML = lang.getEnd; + editor.selection.getRange().moveToBookmark(bk).select(); + + + } +}; +$G("nextReplaceBtn").onclick = function (txt, dir, mcase) { + var findtxt = $G("findtxt1").value, obj; + if (!findtxt) { + return false; + } + obj = { + searchStr:findtxt, + dir:1, + casesensitive:getMatchCase("matchCase1") + }; + frCommond(obj); +}; +$G("preFindBtn").onclick = function (txt, dir, mcase) { + var findtxt = $G("findtxt").value, obj; + if (!findtxt) { + return false; + } + obj = { + searchStr:findtxt, + dir:-1, + casesensitive:getMatchCase("matchCase") + }; + if (!frCommond(obj)) { + $G('search-msg').innerHTML = lang.getStart; + } +}; +$G("preReplaceBtn").onclick = function (txt, dir, mcase) { + var findtxt = $G("findtxt1").value, obj; + if (!findtxt) { + return false; + } + obj = { + searchStr:findtxt, + dir:-1, + casesensitive:getMatchCase("matchCase1") + }; + frCommond(obj); +}; +//替换 +$G("repalceBtn").onclick = function () { + var findtxt = $G("findtxt1").value.replace(/^\s|\s$/g, ""), obj, + replacetxt = $G("replacetxt").value.replace(/^\s|\s$/g, ""); + if (!findtxt) { + return false; + } + if (findtxt == replacetxt || (!getMatchCase("matchCase1") && findtxt.toLowerCase() == replacetxt.toLowerCase())) { + return false; + } + obj = { + searchStr:findtxt, + dir:1, + casesensitive:getMatchCase("matchCase1"), + replaceStr:replacetxt + }; + frCommond(obj); +}; +//全部替换 +$G("repalceAllBtn").onclick = function () { + var findtxt = $G("findtxt1").value.replace(/^\s|\s$/g, ""), obj, + replacetxt = $G("replacetxt").value.replace(/^\s|\s$/g, ""); + if (!findtxt) { + return false; + } + if (findtxt == replacetxt || (!getMatchCase("matchCase1") && findtxt.toLowerCase() == replacetxt.toLowerCase())) { + return false; + } + obj = { + searchStr:findtxt, + casesensitive:getMatchCase("matchCase1"), + replaceStr:replacetxt, + all:true + }; + var num = frCommond(obj); + if (num) { + $G('replace-msg').innerHTML = lang.countMsg.replace("{#count}", num); + } +}; +//执行 +var frCommond = function (obj) { + return editor.execCommand("searchreplace", obj); +}; +switchTab("searchtab"); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/snapscreen/snapscreen.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/snapscreen/snapscreen.html new file mode 100644 index 000000000..cf8209ee7 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/snapscreen/snapscreen.html @@ -0,0 +1,58 @@ + + + + + + + + + +
        +

        +
        +
        +
        +
        +
        +
        + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/spechars/spechars.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/spechars/spechars.html new file mode 100644 index 000000000..0b5c416f8 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/spechars/spechars.html @@ -0,0 +1,21 @@ + + + + + + + + + +
        +
        +
        + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/spechars/spechars.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/spechars/spechars.js new file mode 100644 index 000000000..f4c155e15 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/spechars/spechars.js @@ -0,0 +1,57 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 12-9-26 + * Time: 下午1:09 + * To change this template use File | Settings | File Templates. + */ +var charsContent = [ + { name:"tsfh", title:lang.tsfh, content:toArray("、,。,·,ˉ,ˇ,¨,〃,々,—,~,‖,…,‘,’,“,”,〔,〕,〈,〉,《,》,「,」,『,』,〖,〗,【,】,±,×,÷,∶,∧,∨,∑,∏,∪,∩,∈,∷,√,⊥,∥,∠,⌒,⊙,∫,∮,≡,≌,≈,∽,∝,≠,≮,≯,≤,≥,∞,∵,∴,♂,♀,°,′,″,℃,$,¤,¢,£,‰,§,№,☆,★,○,●,◎,◇,◆,□,■,△,▲,※,→,←,↑,↓,〓,〡,〢,〣,〤,〥,〦,〧,〨,〩,㊣,㎎,㎏,㎜,㎝,㎞,㎡,㏄,㏎,㏑,㏒,㏕,︰,¬,¦,℡,ˊ,ˋ,˙,–,―,‥,‵,℅,℉,↖,↗,↘,↙,∕,∟,∣,≒,≦,≧,⊿,═,║,╒,╓,╔,╕,╖,╗,╘,╙,╚,╛,╜,╝,╞,╟,╠,╡,╢,╣,╤,╥,╦,╧,╨,╩,╪,╫,╬,╭,╮,╯,╰,╱,╲,╳,▁,▂,▃,▄,▅,▆,▇,�,█,▉,▊,▋,▌,▍,▎,▏,▓,▔,▕,▼,▽,◢,◣,◤,◥,☉,⊕,〒,〝,〞")}, + { name:"lmsz", title:lang.lmsz, content:toArray("ⅰ,ⅱ,ⅲ,ⅳ,ⅴ,ⅵ,ⅶ,ⅷ,ⅸ,ⅹ,Ⅰ,Ⅱ,Ⅲ,Ⅳ,Ⅴ,Ⅵ,Ⅶ,Ⅷ,Ⅸ,Ⅹ,Ⅺ,Ⅻ")}, + { name:"szfh", title:lang.szfh, content:toArray("⒈,⒉,⒊,⒋,⒌,⒍,⒎,⒏,⒐,⒑,⒒,⒓,⒔,⒕,⒖,⒗,⒘,⒙,⒚,⒛,⑴,⑵,⑶,⑷,⑸,⑹,⑺,⑻,⑼,⑽,⑾,⑿,⒀,⒁,⒂,⒃,⒄,⒅,⒆,⒇,①,②,③,④,⑤,⑥,⑦,⑧,⑨,⑩,㈠,㈡,㈢,㈣,㈤,㈥,㈦,㈧,㈨,㈩")}, + { name:"rwfh", title:lang.rwfh, content:toArray("ぁ,あ,ぃ,い,ぅ,う,ぇ,え,ぉ,お,か,が,き,ぎ,く,ぐ,け,げ,こ,ご,さ,ざ,し,じ,す,ず,せ,ぜ,そ,ぞ,た,だ,ち,ぢ,っ,つ,づ,て,で,と,ど,な,に,ぬ,ね,の,は,ば,ぱ,ひ,び,ぴ,ふ,ぶ,ぷ,へ,べ,ぺ,ほ,ぼ,ぽ,ま,み,む,め,も,ゃ,や,ゅ,ゆ,ょ,よ,ら,り,る,れ,ろ,ゎ,わ,ゐ,ゑ,を,ん,ァ,ア,ィ,イ,ゥ,ウ,ェ,エ,ォ,オ,カ,ガ,キ,ギ,ク,グ,ケ,ゲ,コ,ゴ,サ,ザ,シ,ジ,ス,ズ,セ,ゼ,ソ,ゾ,タ,ダ,チ,ヂ,ッ,ツ,ヅ,テ,デ,ト,ド,ナ,ニ,ヌ,ネ,ノ,ハ,バ,パ,ヒ,ビ,ピ,フ,ブ,プ,ヘ,ベ,ペ,ホ,ボ,ポ,マ,ミ,ム,メ,モ,ャ,ヤ,ュ,ユ,ョ,ヨ,ラ,リ,ル,レ,ロ,ヮ,ワ,ヰ,ヱ,ヲ,ン,ヴ,ヵ,ヶ")}, + { name:"xlzm", title:lang.xlzm, content:toArray("Α,Β,Γ,Δ,Ε,Ζ,Η,Θ,Ι,Κ,Λ,Μ,Ν,Ξ,Ο,Π,Ρ,Σ,Τ,Υ,Φ,Χ,Ψ,Ω,α,β,γ,δ,ε,ζ,η,θ,ι,κ,λ,μ,ν,ξ,ο,π,ρ,σ,τ,υ,φ,χ,ψ,ω")}, + { name:"ewzm", title:lang.ewzm, content:toArray("А,Б,В,Г,Д,Е,Ё,Ж,З,И,Й,К,Л,М,Н,О,П,Р,С,Т,У,Ф,Х,Ц,Ч,Ш,Щ,Ъ,Ы,Ь,Э,Ю,Я,а,б,в,г,д,е,ё,ж,з,и,й,к,л,м,н,о,п,р,с,т,у,ф,х,ц,ч,ш,щ,ъ,ы,ь,э,ю,я")}, + { name:"pyzm", title:lang.pyzm, content:toArray("ā,á,ǎ,à,ē,é,ě,è,ī,í,ǐ,ì,ō,ó,ǒ,ò,ū,ú,ǔ,ù,ǖ,ǘ,ǚ,ǜ,ü")}, + { name:"yyyb", title:lang.yyyb, content:toArray("i:,i,e,æ,ʌ,ə:,ə,u:,u,ɔ:,ɔ,a:,ei,ai,ɔi,əu,au,iə,εə,uə,p,t,k,b,d,g,f,s,ʃ,θ,h,v,z,ʒ,ð,tʃ,tr,ts,dʒ,dr,dz,m,n,ŋ,l,r,w,j,")}, + { name:"zyzf", title:lang.zyzf, content:toArray("ㄅ,ㄆ,ㄇ,ㄈ,ㄉ,ㄊ,ㄋ,ㄌ,ㄍ,ㄎ,ㄏ,ㄐ,ㄑ,ㄒ,ㄓ,ㄔ,ㄕ,ㄖ,ㄗ,ㄘ,ㄙ,ㄚ,ㄛ,ㄜ,ㄝ,ㄞ,ㄟ,ㄠ,ㄡ,ㄢ,ㄣ,ㄤ,ㄥ,ㄦ,ㄧ,ㄨ")} +]; +(function createTab(content) { + for (var i = 0, ci; ci = content[i++];) { + var span = document.createElement("span"); + span.setAttribute("tabSrc", ci.name); + span.innerHTML = ci.title; + if (i == 1)span.className = "focus"; + domUtils.on(span, "click", function () { + var tmps = $G("tabHeads").children; + for (var k = 0, sk; sk = tmps[k++];) { + sk.className = ""; + } + tmps = $G("tabBodys").children; + for (var k = 0, sk; sk = tmps[k++];) { + sk.style.display = "none"; + } + this.className = "focus"; + $G(this.getAttribute("tabSrc")).style.display = ""; + }); + $G("tabHeads").appendChild(span); + domUtils.insertAfter(span, document.createTextNode("\n")); + var div = document.createElement("div"); + div.id = ci.name; + div.style.display = (i == 1) ? "" : "none"; + var cons = ci.content; + for (var j = 0, con; con = cons[j++];) { + var charSpan = document.createElement("span"); + charSpan.innerHTML = con; + domUtils.on(charSpan, "click", function () { + editor.execCommand("insertHTML", this.innerHTML); + dialog.close(); + }); + div.appendChild(charSpan); + } + $G("tabBodys").appendChild(div); + } +})(charsContent); +function toArray(str) { + return str.split(","); +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/dragicon.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/dragicon.png new file mode 100644 index 000000000..f26203bf3 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/dragicon.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/edittable.css b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/edittable.css new file mode 100644 index 000000000..c6f9396c9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/edittable.css @@ -0,0 +1,84 @@ +body{ + overflow: hidden; + width: 540px; +} +.wrapper { + margin: 10px auto 0; + font-size: 12px; + overflow: hidden; + width: 520px; + height: 315px; +} + +.clear { + clear: both; +} + +.wrapper .left { + float: left; + margin-left: 10px;; +} + +.wrapper .right { + float: right; + border-left: 2px dotted #EDEDED; + padding-left: 15px; +} + +.section { + margin-bottom: 15px; + width: 240px; + overflow: hidden; +} + +.section h3 { + font-weight: bold; + padding: 5px 0; + margin-bottom: 10px; + border-bottom: 1px solid #EDEDED; + font-size: 12px; +} + +.section ul { + list-style: none; + overflow: hidden; + clear: both; + +} + +.section li { + float: left; + width: 120px;; +} + +.section .tone { + width: 80px;; +} + +.section .preview { + width: 220px; +} + +.section .preview table { + text-align: center; + vertical-align: middle; + color: #666; +} + +.section .preview caption { + font-weight: bold; +} + +.section .preview td { + border-width: 1px; + border-style: solid; + height: 22px; +} + +.section .preview th { + border-style: solid; + border-color: #DDD; + border-width: 2px 1px 1px 1px; + height: 22px; + background-color: #F7F7F7; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/edittable.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/edittable.html new file mode 100644 index 000000000..3c412fb82 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/edittable.html @@ -0,0 +1,64 @@ + + + + + + + + +
        +
        +
        +

        +
          +
        • + +
        • +
        • + +
        • +
        +
          +
        • + +
        • +
        • + +
        • +
        +
        +
        +
        +

        +
          +
        • + +
        • +
        • + +
        • +
        +
        +
        +
        +

        +
          +
        • + + +
        • +
        +
        +
        +
        +
        +
        +

        +
        +
        +
        +
        +
        + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/edittable.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/edittable.js new file mode 100644 index 000000000..11dbee7c5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/edittable.js @@ -0,0 +1,237 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 12-12-19 + * Time: 下午4:55 + * To change this template use File | Settings | File Templates. + */ +(function () { + var title = $G("J_title"), + titleCol = $G("J_titleCol"), + caption = $G("J_caption"), + sorttable = $G("J_sorttable"), + autoSizeContent = $G("J_autoSizeContent"), + autoSizePage = $G("J_autoSizePage"), + tone = $G("J_tone"), + me, + preview = $G("J_preview"); + + var editTable = function () { + me = this; + me.init(); + }; + editTable.prototype = { + init:function () { + var colorPiker = new UE.ui.ColorPicker({ + editor:editor + }), + colorPop = new UE.ui.Popup({ + editor:editor, + content:colorPiker + }); + + title.checked = editor.queryCommandState("inserttitle") == -1; + titleCol.checked = editor.queryCommandState("inserttitlecol") == -1; + caption.checked = editor.queryCommandState("insertcaption") == -1; + sorttable.checked = editor.queryCommandState("enablesort") == 1; + + var enablesortState = editor.queryCommandState("enablesort"), + disablesortState = editor.queryCommandState("disablesort"); + + sorttable.checked = !!(enablesortState < 0 && disablesortState >=0); + sorttable.disabled = !!(enablesortState < 0 && disablesortState < 0); + sorttable.title = enablesortState < 0 && disablesortState < 0 ? lang.errorMsg:''; + + me.createTable(title.checked, titleCol.checked, caption.checked); + me.setAutoSize(); + me.setColor(me.getColor()); + + domUtils.on(title, "click", me.titleHanler); + domUtils.on(titleCol, "click", me.titleColHanler); + domUtils.on(caption, "click", me.captionHanler); + domUtils.on(sorttable, "click", me.sorttableHanler); + domUtils.on(autoSizeContent, "click", me.autoSizeContentHanler); + domUtils.on(autoSizePage, "click", me.autoSizePageHanler); + + domUtils.on(tone, "click", function () { + colorPop.showAnchor(tone); + }); + domUtils.on(document, 'mousedown', function () { + colorPop.hide(); + }); + colorPiker.addListener("pickcolor", function () { + me.setColor(arguments[1]); + colorPop.hide(); + }); + colorPiker.addListener("picknocolor", function () { + me.setColor(""); + colorPop.hide(); + }); + }, + + createTable:function (hasTitle, hasTitleCol, hasCaption) { + var arr = [], + sortSpan = '^'; + arr.push(""); + if (hasCaption) { + arr.push("") + } + if (hasTitle) { + arr.push(""); + if(hasTitleCol) { arr.push(""); } + for (var j = 0; j < 5; j++) { + arr.push(""); + } + arr.push(""); + } + for (var i = 0; i < 6; i++) { + arr.push(""); + if(hasTitleCol) { arr.push("") } + for (var k = 0; k < 5; k++) { + arr.push("") + } + arr.push(""); + } + arr.push("
        " + lang.captionName + "
        " + lang.titleName + "" + lang.titleName + "
        " + lang.titleName + "" + lang.cellsName + "
        "); + preview.innerHTML = arr.join(""); + this.updateSortSpan(); + }, + titleHanler:function () { + var example = $G("J_example"), + frg=document.createDocumentFragment(), + color = domUtils.getComputedStyle(domUtils.getElementsByTagName(example, "td")[0], "border-color"), + colCount = example.rows[0].children.length; + + if (title.checked) { + example.insertRow(0); + for (var i = 0, node; i < colCount; i++) { + node = document.createElement("th"); + node.innerHTML = lang.titleName; + frg.appendChild(node); + } + example.rows[0].appendChild(frg); + + } else { + domUtils.remove(example.rows[0]); + } + me.setColor(color); + me.updateSortSpan(); + }, + titleColHanler:function () { + var example = $G("J_example"), + color = domUtils.getComputedStyle(domUtils.getElementsByTagName(example, "td")[0], "border-color"), + colArr = example.rows, + colCount = colArr.length; + + if (titleCol.checked) { + for (var i = 0, node; i < colCount; i++) { + node = document.createElement("th"); + node.innerHTML = lang.titleName; + colArr[i].insertBefore(node, colArr[i].children[0]); + } + } else { + for (var i = 0; i < colCount; i++) { + domUtils.remove(colArr[i].children[0]); + } + } + me.setColor(color); + me.updateSortSpan(); + }, + captionHanler:function () { + var example = $G("J_example"); + if (caption.checked) { + var row = document.createElement('caption'); + row.innerHTML = lang.captionName; + example.insertBefore(row, example.firstChild); + } else { + domUtils.remove(domUtils.getElementsByTagName(example, 'caption')[0]); + } + }, + sorttableHanler:function(){ + me.updateSortSpan(); + }, + autoSizeContentHanler:function () { + var example = $G("J_example"); + example.removeAttribute("width"); + }, + autoSizePageHanler:function () { + var example = $G("J_example"); + var tds = example.getElementsByTagName(example, "td"); + utils.each(tds, function (td) { + td.removeAttribute("width"); + }); + example.setAttribute('width', '100%'); + }, + updateSortSpan: function(){ + var example = $G("J_example"), + row = example.rows[0]; + + var spans = domUtils.getElementsByTagName(example,"span"); + utils.each(spans,function(span){ + span.parentNode.removeChild(span); + }); + if (sorttable.checked) { + utils.each(row.cells, function(cell, i){ + var span = document.createElement("span"); + span.innerHTML = "^"; + cell.appendChild(span); + }); + } + }, + getColor:function () { + var start = editor.selection.getStart(), color, + cell = domUtils.findParentByTagName(start, ["td", "th", "caption"], true); + color = cell && domUtils.getComputedStyle(cell, "border-color"); + if (!color) color = "#DDDDDD"; + return color; + }, + setColor:function (color) { + var example = $G("J_example"), + arr = domUtils.getElementsByTagName(example, "td").concat( + domUtils.getElementsByTagName(example, "th"), + domUtils.getElementsByTagName(example, "caption") + ); + + tone.value = color; + utils.each(arr, function (node) { + node.style.borderColor = color; + }); + + }, + setAutoSize:function () { + var me = this; + autoSizePage.checked = true; + me.autoSizePageHanler(); + } + }; + + new editTable; + + dialog.onok = function () { + editor.__hasEnterExecCommand = true; + + var checks = { + title:"inserttitle deletetitle", + titleCol:"inserttitlecol deletetitlecol", + caption:"insertcaption deletecaption", + sorttable:"enablesort disablesort" + }; + editor.fireEvent('saveScene'); + for(var i in checks){ + var cmds = checks[i].split(" "), + input = $G("J_" + i); + if(input["checked"]){ + editor.queryCommandState(cmds[0])!=-1 &&editor.execCommand(cmds[0]); + }else{ + editor.queryCommandState(cmds[1])!=-1 &&editor.execCommand(cmds[1]); + } + } + + editor.execCommand("edittable", tone.value); + autoSizeContent.checked ?editor.execCommand('adaptbytext') : ""; + autoSizePage.checked ? editor.execCommand("adaptbywindow") : ""; + editor.fireEvent('saveScene'); + + editor.__hasEnterExecCommand = false; + }; +})(); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/edittd.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/edittd.html new file mode 100644 index 000000000..49a52f719 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/edittd.html @@ -0,0 +1,61 @@ + + + + + + + + +
        + + +
        + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/edittip.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/edittip.html new file mode 100644 index 000000000..954f7bb66 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/table/edittip.html @@ -0,0 +1,33 @@ + + + + 表格删除提示 + + + + +
        +
        + +
        +
        + +
        +
        + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/config.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/config.js new file mode 100644 index 000000000..417b8f787 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/config.js @@ -0,0 +1,42 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 12-8-8 + * Time: 下午2:00 + * To change this template use File | Settings | File Templates. + */ +var templates = [ + { + "pre":"pre0.png", + 'title':lang.blank, + 'preHtml':'

         欢迎使用UEditor!

        ', + "html":'

        欢迎使用UEditor!

        ' + + }, + { + "pre":"pre1.png", + 'title':lang.blog, + 'preHtml':'

        深入理解Range

        UEditor二次开发

        什么是Range

        对于“插入”选项卡上的库,在设计时都充分考虑了其中的项与文档整体外观的协调性。


        Range能干什么

        在“开始”选项卡上,通过从快速样式库中为所选文本选择一种外观,您可以方便地更改文档中所选文本的格式。

        ', + "html":'

        [键入文档标题]

        [键入文档副标题]

        [标题 1]

        对于“插入”选项卡上的库,在设计时都充分考虑了其中的项与文档整体外观的协调性。 您可以使用这些库来插入表格、页眉、页脚、列表、封面以及其他文档构建基块。 您创建的图片、图表或关系图也将与当前的文档外观协调一致。

        [标题 2]

        在“开始”选项卡上,通过从快速样式库中为所选文本选择一种外观,您可以方便地更改文档中所选文本的格式。 您还可以使用“开始”选项卡上的其他控件来直接设置文本格式。大多数控件都允许您选择是使用当前主题外观,还是使用某种直接指定的格式。

        [标题 3]

        对于“插入”选项卡上的库,在设计时都充分考虑了其中的项与文档整体外观的协调性。 您可以使用这些库来插入表格、页眉、页脚、列表、封面以及其他文档构建基块。 您创建的图片、图表或关系图也将与当前的文档外观协调一致。


        ' + + }, + { + "pre":"pre2.png", + 'title':lang.resume, + 'preHtml':'

        WEB前端开发简历


        联系电话:[键入您的电话]

        电子邮件:[键入您的电子邮件地址]

        家庭住址:[键入您的地址]

        目标职位

        WEB前端研发工程师

        学历

        1. [起止时间] [学校名称] [所学专业] [所获学位]

        工作经验


        ', + "html":'

        [此处键入简历标题]


        【此处插入照片】


        联系电话:[键入您的电话]


        电子邮件:[键入您的电子邮件地址]


        家庭住址:[键入您的地址]


        目标职位

        [此处键入您的期望职位]

        学历

        1. [键入起止时间] [键入学校名称] [键入所学专业] [键入所获学位]

        2. [键入起止时间] [键入学校名称] [键入所学专业] [键入所获学位]

        工作经验

        1. [键入起止时间] [键入公司名称] [键入职位名称]

          1. [键入负责项目] [键入项目简介]

          2. [键入负责项目] [键入项目简介]

        2. [键入起止时间] [键入公司名称] [键入职位名称]

          1. [键入负责项目] [键入项目简介]

        掌握技能

         [这里可以键入您所掌握的技能]

        ' + + }, + { + "pre":"pre3.png", + 'title':lang.richText, + 'preHtml':'

        [此处键入文章标题]

        图文混排方法

        图片居左,文字围绕图片排版

        方法:在文字前面插入图片,设置居左对齐,然后即可在右边输入多行文


        还有没有什么其他的环绕方式呢?这里是居右环绕


        欢迎大家多多尝试,为UEditor提供更多高质量模板!

        ', + "html":'


        [此处键入文章标题]

        图文混排方法

        1. 图片居左,文字围绕图片排版

        方法:在文字前面插入图片,设置居左对齐,然后即可在右边输入多行文本


        2. 图片居右,文字围绕图片排版

        方法:在文字前面插入图片,设置居右对齐,然后即可在左边输入多行文本


        3. 图片居中环绕排版

        方法:亲,这个真心没有办法。。。



        还有没有什么其他的环绕方式呢?这里是居右环绕


        欢迎大家多多尝试,为UEditor提供更多高质量模板!


        占位


        占位


        占位


        占位


        占位



        ' + }, + { + "pre":"pre4.png", + 'title':lang.sciPapers, + 'preHtml':'

        [键入文章标题]

        摘要:这里可以输入很长很长很长很长很长很长很长很长很差的摘要

        标题 1

        这里可以输入很多内容,可以图文混排,可以有列表等。

        标题 2

        1. 列表 1

        2. 列表 2

          1. 多级列表 1

          2. 多级列表 2

        3. 列表 3

        标题 3

        来个文字图文混排的


        ', + 'html':'

        [键入文章标题]

        摘要:这里可以输入很长很长很长很长很长很长很长很长很差的摘要

        标题 1

        这里可以输入很多内容,可以图文混排,可以有列表等。

        标题 2

        来个列表瞅瞅:

        1. 列表 1

        2. 列表 2

          1. 多级列表 1

          2. 多级列表 2

        3. 列表 3

        标题 3

        来个文字图文混排的

        这里可以多行

        右边是图片

        绝对没有问题的,不信你也可以试试看


        ' + } +]; \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/bg.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/bg.gif new file mode 100644 index 000000000..8c1d10ad1 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/bg.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/pre0.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/pre0.png new file mode 100644 index 000000000..8f3c16ab1 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/pre0.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/pre1.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/pre1.png new file mode 100644 index 000000000..5a03f9699 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/pre1.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/pre2.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/pre2.png new file mode 100644 index 000000000..5a55672c1 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/pre2.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/pre3.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/pre3.png new file mode 100644 index 000000000..d852d29f1 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/pre3.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/pre4.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/pre4.png new file mode 100644 index 000000000..0d7bc72ab Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/images/pre4.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/template.css b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/template.css new file mode 100644 index 000000000..6c1608dfc --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/template.css @@ -0,0 +1,18 @@ +.wrap{ padding: 5px;font-size: 14px;} +.left{width:425px;float: left;} +.right{width:160px;border: 1px solid #ccc;float: right;padding: 5px;margin-right: 5px;} +.right .pre{height: 332px;overflow-y: auto;} +.right .preitem{border: white 1px solid;margin: 5px 0;padding: 2px 0;} +.right .preitem:hover{background-color: lemonChiffon;cursor: pointer;border: #ccc 1px solid;} +.right .preitem img{display: block;margin: 0 auto;width:100px;} +.clear{clear: both;} +.top{height:26px;line-height: 26px;padding: 5px;} +.bottom{height:320px;width:100%;margin: 0 auto;} +.transparent{ background: url("images/bg.gif") repeat;} +.bottom table tr td{border:1px dashed #ccc;} +#colorPicker{width: 17px;height: 17px;border: 1px solid #CCC;display: inline-block;border-radius: 3px;box-shadow: 2px 2px 5px #D3D6DA;} +.border_style1{padding:2px;border: 1px solid #ccc;border-radius: 5px;box-shadow:2px 2px 5px #d3d6da;} +p{margin: 5px 0} +table{clear:both;margin-bottom:10px;border-collapse:collapse;word-break:break-all;} +li{clear:both} +ol{padding-left:40px; } \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/template.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/template.html new file mode 100644 index 000000000..d9903a480 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/template.html @@ -0,0 +1,26 @@ + + + + + + + + + +
        +
        +
        + +
        +
        +
        +
        + +
        +
        +
        +
        + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/template.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/template.js new file mode 100644 index 000000000..80a334b36 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/template/template.js @@ -0,0 +1,53 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 12-8-8 + * Time: 下午2:09 + * To change this template use File | Settings | File Templates. + */ +(function () { + var me = editor, + preview = $G( "preview" ), + preitem = $G( "preitem" ), + tmps = templates, + currentTmp; + var initPre = function () { + var str = ""; + for ( var i = 0, tmp; tmp = tmps[i++]; ) { + str += '
        '; + } + preitem.innerHTML = str; + }; + var pre = function ( n ) { + var tmp = tmps[n - 1]; + currentTmp = tmp; + clearItem(); + domUtils.setStyles( preitem.childNodes[n - 1], { + "background-color":"lemonChiffon", + "border":"#ccc 1px solid" + } ); + preview.innerHTML = tmp.preHtml ? tmp.preHtml : ""; + }; + var clearItem = function () { + var items = preitem.children; + for ( var i = 0, item; item = items[i++]; ) { + domUtils.setStyles( item, { + "background-color":"", + "border":"white 1px solid" + } ); + } + }; + dialog.onok = function () { + if ( !$G( "issave" ).checked ){ + me.execCommand( "cleardoc" ); + } + var obj = { + html:currentTmp && currentTmp.html + }; + me.execCommand( "template", obj ); + }; + initPre(); + window.pre = pre; + pre(2) + +})(); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/bg.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/bg.png new file mode 100644 index 000000000..580be0a01 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/bg.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/center_focus.jpg b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/center_focus.jpg new file mode 100644 index 000000000..262b02916 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/center_focus.jpg differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/file-icons.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/file-icons.gif new file mode 100644 index 000000000..d8c02c27e Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/file-icons.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/file-icons.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/file-icons.png new file mode 100644 index 000000000..3ff82c8c4 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/file-icons.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/icons.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/icons.gif new file mode 100644 index 000000000..78459dea7 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/icons.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/icons.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/icons.png new file mode 100644 index 000000000..12e470016 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/icons.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/image.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/image.png new file mode 100644 index 000000000..19699f6a9 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/image.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/left_focus.jpg b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/left_focus.jpg new file mode 100644 index 000000000..7886d276d Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/left_focus.jpg differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/none_focus.jpg b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/none_focus.jpg new file mode 100644 index 000000000..7c768dcb4 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/none_focus.jpg differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/progress.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/progress.png new file mode 100644 index 000000000..717c4865c Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/progress.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/right_focus.jpg b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/right_focus.jpg new file mode 100644 index 000000000..173e10d2d Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/right_focus.jpg differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/success.gif b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/success.gif new file mode 100644 index 000000000..8d4f3112b Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/success.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/success.png b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/success.png new file mode 100644 index 000000000..94f968dc8 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/images/success.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/video.css b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/video.css new file mode 100644 index 000000000..5870e7a15 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/video.css @@ -0,0 +1,635 @@ +@charset "utf-8"; +.wrapper{ width: 570px;_width:575px;margin: 10px auto; zoom:1;position: relative} +.tabbody{height: 335px;} +.tabbody .panel { + position: absolute; + width: 0; + height: 0; + background: #fff; + overflow: hidden; + display: none; +} +.tabbody .panel.focus { + width: 100%; + height: 335px; + display: block; +} + +.tabbody .panel table td{vertical-align: middle;} +#videoUrl { + width: 490px; + height: 21px; + line-height: 21px; + margin: 8px 5px; + background: #FFF; + border: 1px solid #d7d7d7; +} +#videoSearchTxt{margin-left:15px;background: #FFF;width:200px;height:21px;line-height:21px;border: 1px solid #d7d7d7;} +#searchList{width: 570px;overflow: auto;zoom:1;height: 270px;} +#searchList div{float: left;width: 120px;height: 135px;margin: 5px 15px;} +#searchList img{margin: 2px 8px;cursor: pointer;border: 2px solid #fff} /*不用缩略图*/ +#searchList p{margin-left: 10px;} +#videoType{ + width: 65px; + height: 23px; + line-height: 22px; + border: 1px solid #d7d7d7; +} +#videoSearchBtn,#videoSearchReset{ + /*width: 80px;*/ + height: 25px; + line-height: 25px; + background: #eee; + border: 1px solid #d7d7d7; + cursor: pointer; + padding: 0 5px; +} + + + +#preview{position: relative;width: 420px;padding:0;overflow: hidden; margin-left: 10px; _margin-left:5px; height: 280px;background-color: #ddd;float: left} +#preview .previewMsg {position:absolute;top:0;margin:0;padding:0;height:280px;width:100%;background-color: #666;} +#preview .previewMsg span{display:block;margin: 125px auto 0 auto;text-align:center;font-size:18px;color:#fff;} +#preview .previewVideo {position:absolute;top:0;margin:0;padding:0;height:280px;width:100%;} +.edui-video-wrapper fieldset{ + border: 1px solid #ddd; + padding-left: 5px; + margin-bottom: 20px; + padding-bottom: 5px; + width: 115px; +} + +#videoInfo {width: 120px;float: left;margin-left: 10px;_margin-left:7px;} +fieldset{ + border: 1px solid #ddd; + padding-left: 5px; + margin-bottom: 20px; + padding-bottom: 5px; + width: 115px; +} +fieldset legend{font-weight: bold;} +fieldset p{line-height: 30px;} +fieldset input.txt{ + width: 65px; + height: 21px; + line-height: 21px; + margin: 8px 5px; + background: #FFF; + border: 1px solid #d7d7d7; +} +label.url{font-weight: bold;margin-left: 5px;color: #06c;} +#videoFloat div{cursor:pointer;opacity: 0.5;filter: alpha(opacity = 50);margin:9px;_margin:5px;width:38px;height:36px;float:left;} +#videoFloat .focus{opacity: 1;filter: alpha(opacity = 100)} +span.view{display: inline-block;width: 30px;float: right;cursor: pointer;color: blue} + + + + +/* upload video */ +.tabbody #upload.panel { + width: 0; + height: 0; + overflow: hidden; + position: absolute !important; + clip: rect(1px, 1px, 1px, 1px); + background: #fff; + display: block; +} +.tabbody #upload.panel.focus { + width: 100%; + height: 335px; + display: block; + clip: auto; +} +#upload_alignment div{cursor:pointer;opacity: 0.5;filter: alpha(opacity = 50);margin:9px;_margin:5px;width:38px;height:36px;float:left;} +#upload_alignment .focus{opacity: 1;filter: alpha(opacity = 100)} +#upload_left { width:427px; float:left; } +#upload_left .controller { height: 30px; clear: both; } +#uploadVideoInfo{margin-top:10px;float:right;padding-right:8px;} + +#upload .queueList { + margin: 0; +} + +#upload p { + margin: 0; +} + +.element-invisible { + width: 0 !important; + height: 0 !important; + border: 0; + padding: 0; + margin: 0; + overflow: hidden; + position: absolute !important; + clip: rect(1px, 1px, 1px, 1px); +} + +#upload .placeholder { + margin: 10px; + margin-right:0; + border: 2px dashed #e6e6e6; + *border: 0px dashed #e6e6e6; + height: 161px; + padding-top: 150px; + text-align: center; + width: 97%; + float: left; + background: url(./images/image.png) center 70px no-repeat; + color: #cccccc; + font-size: 18px; + position: relative; + top:0; + *margin-left: 0; + *left: 10px; +} + +#upload .placeholder .webuploader-pick { + font-size: 18px; + background: #00b7ee; + border-radius: 3px; + line-height: 44px; + padding: 0 30px; + *width: 120px; + color: #fff; + display: inline-block; + margin: 0 auto 20px auto; + cursor: pointer; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); +} + +#upload .placeholder .webuploader-pick-hover { + background: #00a2d4; +} + + +#filePickerContainer { + text-align: center; +} + +#upload .placeholder .flashTip { + color: #666666; + font-size: 12px; + position: absolute; + width: 100%; + text-align: center; + bottom: 20px; +} + +#upload .placeholder .flashTip a { + color: #0785d1; + text-decoration: none; +} + +#upload .placeholder .flashTip a:hover { + text-decoration: underline; +} + +#upload .placeholder.webuploader-dnd-over { + border-color: #999999; +} + +#upload .filelist { + list-style: none; + margin: 0; + padding: 0; + overflow-x: hidden; + overflow-y: auto; + position: relative; + height: 285px; +} + +#upload .filelist:after { + content: ''; + display: block; + width: 0; + height: 0; + overflow: hidden; + clear: both; +} + +#upload .filelist li { + width: 113px; + height: 113px; + background: url(./images/bg.png); + text-align: center; + margin: 15px 0 0 20px; + *margin: 15px 0 0 15px; + position: relative; + display: block; + float: left; + overflow: hidden; + font-size: 12px; +} + +#upload .filelist li p.log { + position: relative; + top: -45px; +} + +#upload .filelist li p.title { + position: absolute; + top: 0; + left: 0; + width: 100%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + top: 5px; + text-indent: 5px; + text-align: left; +} + +#upload .filelist li p.progress { + position: absolute; + width: 100%; + bottom: 0; + left: 0; + height: 8px; + overflow: hidden; + z-index: 50; + margin: 0; + border-radius: 0; + background: none; + -webkit-box-shadow: 0 0 0; +} + +#upload .filelist li p.progress span { + display: none; + overflow: hidden; + width: 0; + height: 100%; + background: #1483d8 url(./images/progress.png) repeat-x; + + -webit-transition: width 200ms linear; + -moz-transition: width 200ms linear; + -o-transition: width 200ms linear; + -ms-transition: width 200ms linear; + transition: width 200ms linear; + + -webkit-animation: progressmove 2s linear infinite; + -moz-animation: progressmove 2s linear infinite; + -o-animation: progressmove 2s linear infinite; + -ms-animation: progressmove 2s linear infinite; + animation: progressmove 2s linear infinite; + + -webkit-transform: translateZ(0); +} + +@-webkit-keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +@-moz-keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +@keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +#upload .filelist li p.imgWrap { + position: relative; + z-index: 2; + line-height: 113px; + vertical-align: middle; + overflow: hidden; + width: 113px; + height: 113px; + + -webkit-transform-origin: 50% 50%; + -moz-transform-origin: 50% 50%; + -o-transform-origin: 50% 50%; + -ms-transform-origin: 50% 50%; + transform-origin: 50% 50%; + + -webit-transition: 200ms ease-out; + -moz-transition: 200ms ease-out; + -o-transition: 200ms ease-out; + -ms-transition: 200ms ease-out; + transition: 200ms ease-out; +} +#upload .filelist li p.imgWrap.notimage { + margin-top: 0; + width: 111px; + height: 111px; + border: 1px #eeeeee solid; +} +#upload .filelist li p.imgWrap.notimage i.file-preview { + margin-top: 15px; +} + +#upload .filelist li img { + width: 100%; +} + +#upload .filelist li p.error { + background: #f43838; + color: #fff; + position: absolute; + bottom: 0; + left: 0; + height: 28px; + line-height: 28px; + width: 100%; + z-index: 100; + display:none; +} + +#upload .filelist li .success { + display: block; + position: absolute; + left: 0; + bottom: 0; + height: 40px; + width: 100%; + z-index: 200; + background: url(./images/success.png) no-repeat right bottom; + background-image: url(./images/success.gif) \9; +} + +#upload .filelist li.filePickerBlock { + width: 113px; + height: 113px; + background: url(./images/image.png) no-repeat center 12px; + border: 1px solid #eeeeee; + border-radius: 0; +} +#upload .filelist li.filePickerBlock div.webuploader-pick { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + opacity: 0; + background: none; + font-size: 0; +} + +#upload .filelist div.file-panel { + position: absolute; + height: 0; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#80000000', endColorstr='#80000000') \0; + background: rgba(0, 0, 0, 0.5); + width: 100%; + top: 0; + left: 0; + overflow: hidden; + z-index: 300; +} + +#upload .filelist div.file-panel span { + width: 24px; + height: 24px; + display: inline; + float: right; + text-indent: -9999px; + overflow: hidden; + background: url(./images/icons.png) no-repeat; + background: url(./images/icons.gif) no-repeat \9; + margin: 5px 1px 1px; + cursor: pointer; + -webkit-tap-highlight-color: rgba(0,0,0,0); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +#upload .filelist div.file-panel span.rotateLeft { + display:none; + background-position: 0 -24px; +} + +#upload .filelist div.file-panel span.rotateLeft:hover { + background-position: 0 0; +} + +#upload .filelist div.file-panel span.rotateRight { + display:none; + background-position: -24px -24px; +} + +#upload .filelist div.file-panel span.rotateRight:hover { + background-position: -24px 0; +} + +#upload .filelist div.file-panel span.cancel { + background-position: -48px -24px; +} + +#upload .filelist div.file-panel span.cancel:hover { + background-position: -48px 0; +} + +#upload .statusBar { + height: 45px; + border-bottom: 1px solid #dadada; + margin: 0 10px; + padding: 0; + line-height: 45px; + vertical-align: middle; + position: relative; +} + +#upload .statusBar .progress { + border: 1px solid #1483d8; + width: 198px; + background: #fff; + height: 18px; + position: absolute; + top: 12px; + display: none; + text-align: center; + line-height: 18px; + color: #6dbfff; + margin: 0 10px 0 0; +} +#upload .statusBar .progress span.percentage { + width: 0; + height: 100%; + left: 0; + top: 0; + background: #1483d8; + position: absolute; +} +#upload .statusBar .progress span.text { + position: relative; + z-index: 10; +} + +#upload .statusBar .info { + display: inline-block; + font-size: 14px; + color: #666666; +} + +#upload .statusBar .btns { + position: absolute; + top: 7px; + right: 0; + line-height: 30px; +} + +#filePickerBtn { + display: inline-block; + float: left; +} +#upload .statusBar .btns .webuploader-pick, +#upload .statusBar .btns .uploadBtn, +#upload .statusBar .btns .uploadBtn.state-uploading, +#upload .statusBar .btns .uploadBtn.state-paused { + background: #ffffff; + border: 1px solid #cfcfcf; + color: #565656; + padding: 0 18px; + display: inline-block; + border-radius: 3px; + margin-left: 10px; + cursor: pointer; + font-size: 14px; + float: left; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +#upload .statusBar .btns .webuploader-pick-hover, +#upload .statusBar .btns .uploadBtn:hover, +#upload .statusBar .btns .uploadBtn.state-uploading:hover, +#upload .statusBar .btns .uploadBtn.state-paused:hover { + background: #f0f0f0; +} + +#upload .statusBar .btns .uploadBtn, +#upload .statusBar .btns .uploadBtn.state-paused{ + background: #00b7ee; + color: #fff; + border-color: transparent; +} +#upload .statusBar .btns .uploadBtn:hover, +#upload .statusBar .btns .uploadBtn.state-paused:hover{ + background: #00a2d4; +} + +#upload .statusBar .btns .uploadBtn.disabled { + pointer-events: none; + filter:alpha(opacity=60); + -moz-opacity:0.6; + -khtml-opacity: 0.6; + opacity: 0.6; +} + + +/* 在线文件的文件预览图标 */ +i.file-preview { + display: block; + margin: 10px auto; + width: 70px; + height: 70px; + background-image: url("./images/file-icons.png"); + background-image: url("./images/file-icons.gif") \9; + background-position: -140px center; + background-repeat: no-repeat; +} +i.file-preview.file-type-dir{ + background-position: 0 center; +} +i.file-preview.file-type-file{ + background-position: -140px center; +} +i.file-preview.file-type-filelist{ + background-position: -210px center; +} +i.file-preview.file-type-zip, +i.file-preview.file-type-rar, +i.file-preview.file-type-7z, +i.file-preview.file-type-tar, +i.file-preview.file-type-gz, +i.file-preview.file-type-bz2{ + background-position: -280px center; +} +i.file-preview.file-type-xls, +i.file-preview.file-type-xlsx{ + background-position: -350px center; +} +i.file-preview.file-type-doc, +i.file-preview.file-type-docx{ + background-position: -420px center; +} +i.file-preview.file-type-ppt, +i.file-preview.file-type-pptx{ + background-position: -490px center; +} +i.file-preview.file-type-vsd{ + background-position: -560px center; +} +i.file-preview.file-type-pdf{ + background-position: -630px center; +} +i.file-preview.file-type-txt, +i.file-preview.file-type-md, +i.file-preview.file-type-json, +i.file-preview.file-type-htm, +i.file-preview.file-type-xml, +i.file-preview.file-type-html, +i.file-preview.file-type-js, +i.file-preview.file-type-css, +i.file-preview.file-type-php, +i.file-preview.file-type-jsp, +i.file-preview.file-type-asp{ + background-position: -700px center; +} +i.file-preview.file-type-apk{ + background-position: -770px center; +} +i.file-preview.file-type-exe{ + background-position: -840px center; +} +i.file-preview.file-type-ipa{ + background-position: -910px center; +} +i.file-preview.file-type-mp4, +i.file-preview.file-type-swf, +i.file-preview.file-type-mkv, +i.file-preview.file-type-avi, +i.file-preview.file-type-flv, +i.file-preview.file-type-mov, +i.file-preview.file-type-mpg, +i.file-preview.file-type-mpeg, +i.file-preview.file-type-ogv, +i.file-preview.file-type-webm, +i.file-preview.file-type-rm, +i.file-preview.file-type-rmvb{ + background-position: -980px center; +} +i.file-preview.file-type-ogg, +i.file-preview.file-type-wav, +i.file-preview.file-type-wmv, +i.file-preview.file-type-mid, +i.file-preview.file-type-mp3{ + background-position: -1050px center; +} +i.file-preview.file-type-jpg, +i.file-preview.file-type-jpeg, +i.file-preview.file-type-gif, +i.file-preview.file-type-bmp, +i.file-preview.file-type-png, +i.file-preview.file-type-psd{ + background-position: -140px center; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/video.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/video.html new file mode 100644 index 000000000..500788291 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/video.html @@ -0,0 +1,86 @@ + + + + + + + + + +
        +
        +
        + + +
        +
        +
        +
        +
        +
        +
        + + + + +
        +
        +
        + +
        +
        +
        +
        +
        +
        +
        +
        +
        + 0% + +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
          +
        • +
        +
        +
        +
        +
        + + + + +
        +
        +
        + +
        +
        +
        +
        +
        +
        +
        + + + + + + + + + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/video.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/video.js new file mode 100644 index 000000000..a8c34d974 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/video/video.js @@ -0,0 +1,791 @@ +/** + * Created by JetBrains PhpStorm. + * User: taoqili + * Date: 12-2-20 + * Time: 上午11:19 + * To change this template use File | Settings | File Templates. + */ + +(function(){ + + var video = {}, + uploadVideoList = [], + isModifyUploadVideo = false, + uploadFile; + + window.onload = function(){ + $focus($G("videoUrl")); + initTabs(); + initVideo(); + initUpload(); + }; + + /* 初始化tab标签 */ + function initTabs(){ + var tabs = $G('tabHeads').children; + for (var i = 0; i < tabs.length; i++) { + domUtils.on(tabs[i], "click", function (e) { + var j, bodyId, target = e.target || e.srcElement; + for (j = 0; j < tabs.length; j++) { + bodyId = tabs[j].getAttribute('data-content-id'); + if(tabs[j] == target){ + domUtils.addClass(tabs[j], 'focus'); + domUtils.addClass($G(bodyId), 'focus'); + }else { + domUtils.removeClasses(tabs[j], 'focus'); + domUtils.removeClasses($G(bodyId), 'focus'); + } + } + }); + } + } + + function initVideo(){ + createAlignButton( ["videoFloat", "upload_alignment"] ); + addUrlChangeListener($G("videoUrl")); + addOkListener(); + + //编辑视频时初始化相关信息 + (function(){ + var img = editor.selection.getRange().getClosedNode(),url; + if(img && img.className){ + var hasFakedClass = (img.className == "edui-faked-video"), + hasUploadClass = img.className.indexOf("edui-upload-video")!=-1; + if(hasFakedClass || hasUploadClass) { + $G("videoUrl").value = url = img.getAttribute("_url"); + $G("videoWidth").value = img.width; + $G("videoHeight").value = img.height; + var align = domUtils.getComputedStyle(img,"float"), + parentAlign = domUtils.getComputedStyle(img.parentNode,"text-align"); + updateAlignButton(parentAlign==="center"?"center":align); + } + if(hasUploadClass) { + isModifyUploadVideo = true; + } + } + createPreviewVideo(url); + })(); + } + + /** + * 监听确认和取消两个按钮事件,用户执行插入或者清空正在播放的视频实例操作 + */ + function addOkListener(){ + dialog.onok = function(){ + $G("preview").innerHTML = ""; + var currentTab = findFocus("tabHeads","tabSrc"); + switch(currentTab){ + case "video": + return insertSingle(); + break; + case "videoSearch": + return insertSearch("searchList"); + break; + case "upload": + return insertUpload(); + break; + } + }; + dialog.oncancel = function(){ + $G("preview").innerHTML = ""; + }; + } + + /** + * 依据传入的align值更新按钮信息 + * @param align + */ + function updateAlignButton( align ) { + var aligns = $G( "videoFloat" ).children; + for ( var i = 0, ci; ci = aligns[i++]; ) { + if ( ci.getAttribute( "name" ) == align ) { + if ( ci.className !="focus" ) { + ci.className = "focus"; + } + } else { + if ( ci.className =="focus" ) { + ci.className = ""; + } + } + } + } + + /** + * 将单个视频信息插入编辑器中 + */ + function insertSingle(){ + var width = $G("videoWidth"), + height = $G("videoHeight"), + url=$G('videoUrl').value, + align = findFocus("videoFloat","name"); + if(!url) return false; + if ( !checkNum( [width, height] ) ) return false; + editor.execCommand('insertvideo', { + url: convert_url(url), + width: width.value, + height: height.value, + align: align + }, isModifyUploadVideo ? 'upload':null); + } + + /** + * 将元素id下的所有代表视频的图片插入编辑器中 + * @param id + */ + function insertSearch(id){ + var imgs = domUtils.getElementsByTagName($G(id),"img"), + videoObjs=[]; + for(var i=0,img; img=imgs[i++];){ + if(img.getAttribute("selected")){ + videoObjs.push({ + url:img.getAttribute("ue_video_url"), + width:420, + height:280, + align:"none" + }); + } + } + editor.execCommand('insertvideo',videoObjs); + } + + /** + * 找到id下具有focus类的节点并返回该节点下的某个属性 + * @param id + * @param returnProperty + */ + function findFocus( id, returnProperty ) { + var tabs = $G( id ).children, + property; + for ( var i = 0, ci; ci = tabs[i++]; ) { + if ( ci.className=="focus" ) { + property = ci.getAttribute( returnProperty ); + break; + } + } + return property; + } + function convert_url(url){ + if ( !url ) return ''; + url = utils.trim(url) + .replace(/v\.youku\.com\/v_show\/id_([\w\-=]+)\.html/i, 'player.youku.com/player.php/sid/$1/v.swf') + .replace(/(www\.)?youtube\.com\/watch\?v=([\w\-]+)/i, "www.youtube.com/v/$2") + .replace(/youtu.be\/(\w+)$/i, "www.youtube.com/v/$1") + .replace(/v\.ku6\.com\/.+\/([\w\.]+)\.html.*$/i, "player.ku6.com/refer/$1/v.swf") + .replace(/www\.56\.com\/u\d+\/v_([\w\-]+)\.html/i, "player.56.com/v_$1.swf") + .replace(/www.56.com\/w\d+\/play_album\-aid\-\d+_vid\-([^.]+)\.html/i, "player.56.com/v_$1.swf") + .replace(/v\.pps\.tv\/play_([\w]+)\.html.*$/i, "player.pps.tv/player/sid/$1/v.swf") + .replace(/www\.letv\.com\/ptv\/vplay\/([\d]+)\.html.*$/i, "i7.imgs.letv.com/player/swfPlayer.swf?id=$1&autoplay=0") + .replace(/www\.tudou\.com\/programs\/view\/([\w\-]+)\/?/i, "www.tudou.com/v/$1") + .replace(/v\.qq\.com\/cover\/[\w]+\/[\w]+\/([\w]+)\.html/i, "static.video.qq.com/TPout.swf?vid=$1") + .replace(/v\.qq\.com\/.+[\?\&]vid=([^&]+).*$/i, "static.video.qq.com/TPout.swf?vid=$1") + .replace(/my\.tv\.sohu\.com\/[\w]+\/[\d]+\/([\d]+)\.shtml.*$/i, "share.vrs.sohu.com/my/v.swf&id=$1"); + + return url; + } + + /** + * 检测传入的所有input框中输入的长宽是否是正数 + * @param nodes input框集合, + */ + function checkNum( nodes ) { + for ( var i = 0, ci; ci = nodes[i++]; ) { + var value = ci.value; + if ( !isNumber( value ) && value) { + alert( lang.numError ); + ci.value = ""; + ci.focus(); + return false; + } + } + return true; + } + + /** + * 数字判断 + * @param value + */ + function isNumber( value ) { + return /(0|^[1-9]\d*$)/.test( value ); + } + + /** + * 创建图片浮动选择按钮 + * @param ids + */ + function createAlignButton( ids ) { + for ( var i = 0, ci; ci = ids[i++]; ) { + var floatContainer = $G( ci ), + nameMaps = {"none":lang['default'], "left":lang.floatLeft, "right":lang.floatRight, "center":lang.block}; + for ( var j in nameMaps ) { + var div = document.createElement( "div" ); + div.setAttribute( "name", j ); + if ( j == "none" ) div.className="focus"; + div.style.cssText = "background:url(images/" + j + "_focus.jpg);"; + div.setAttribute( "title", nameMaps[j] ); + floatContainer.appendChild( div ); + } + switchSelect( ci ); + } + } + + /** + * 选择切换 + * @param selectParentId + */ + function switchSelect( selectParentId ) { + var selects = $G( selectParentId ).children; + for ( var i = 0, ci; ci = selects[i++]; ) { + domUtils.on( ci, "click", function () { + for ( var j = 0, cj; cj = selects[j++]; ) { + cj.className = ""; + cj.removeAttribute && cj.removeAttribute( "class" ); + } + this.className = "focus"; + } ) + } + } + + /** + * 监听url改变事件 + * @param url + */ + function addUrlChangeListener(url){ + if (browser.ie) { + url.onpropertychange = function () { + createPreviewVideo( this.value ); + } + } else { + url.addEventListener( "input", function () { + createPreviewVideo( this.value ); + }, false ); + } + } + + /** + * 根据url生成视频预览 + * @param url + */ + function createPreviewVideo(url){ + if ( !url )return; + + var conUrl = convert_url(url); + + conUrl = utils.unhtmlForUrl(conUrl); + + $G("preview").innerHTML = '
        '+lang.urlError+'
        '+ + '' + + ''; + } + + + /* 插入上传视频 */ + function insertUpload(){ + var videoObjs=[], + uploadDir = editor.getOpt('videoUrlPrefix'), + width = parseInt($G('upload_width').value, 10) || 420, + height = parseInt($G('upload_height').value, 10) || 280, + align = findFocus("upload_alignment","name") || 'none'; + for(var key in uploadVideoList) { + var file = uploadVideoList[key]; + videoObjs.push({ + url: uploadDir + file.url, + width:width, + height:height, + align:align + }); + } + + var count = uploadFile.getQueueCount(); + if (count) { + $('.info', '#queueList').html('' + '还有2个未上传文件'.replace(/[\d]/, count) + ''); + return false; + } else { + editor.execCommand('insertvideo', videoObjs, 'upload'); + } + } + + /*初始化上传标签*/ + function initUpload(){ + uploadFile = new UploadFile('queueList'); + } + + + /* 上传附件 */ + function UploadFile(target) { + this.$wrap = target.constructor == String ? $('#' + target) : $(target); + this.init(); + } + UploadFile.prototype = { + init: function () { + this.fileList = []; + this.initContainer(); + this.initUploader(); + }, + initContainer: function () { + this.$queue = this.$wrap.find('.filelist'); + }, + /* 初始化容器 */ + initUploader: function () { + var _this = this, + $ = jQuery, // just in case. Make sure it's not an other libaray. + $wrap = _this.$wrap, + // 图片容器 + $queue = $wrap.find('.filelist'), + // 状态栏,包括进度和控制按钮 + $statusBar = $wrap.find('.statusBar'), + // 文件总体选择信息。 + $info = $statusBar.find('.info'), + // 上传按钮 + $upload = $wrap.find('.uploadBtn'), + // 上传按钮 + $filePickerBtn = $wrap.find('.filePickerBtn'), + // 上传按钮 + $filePickerBlock = $wrap.find('.filePickerBlock'), + // 没选择文件之前的内容。 + $placeHolder = $wrap.find('.placeholder'), + // 总体进度条 + $progress = $statusBar.find('.progress').hide(), + // 添加的文件数量 + fileCount = 0, + // 添加的文件总大小 + fileSize = 0, + // 优化retina, 在retina下这个值是2 + ratio = window.devicePixelRatio || 1, + // 缩略图大小 + thumbnailWidth = 113 * ratio, + thumbnailHeight = 113 * ratio, + // 可能有pedding, ready, uploading, confirm, done. + state = '', + // 所有文件的进度信息,key为file id + percentages = {}, + supportTransition = (function () { + var s = document.createElement('p').style, + r = 'transition' in s || + 'WebkitTransition' in s || + 'MozTransition' in s || + 'msTransition' in s || + 'OTransition' in s; + s = null; + return r; + })(), + // WebUploader实例 + uploader, + actionUrl = editor.getActionUrl(editor.getOpt('videoActionName')), + fileMaxSize = editor.getOpt('videoMaxSize'), + acceptExtensions = (editor.getOpt('videoAllowFiles') || []).join('').replace(/\./g, ',').replace(/^[,]/, '');; + + if (!WebUploader.Uploader.support()) { + $('#filePickerReady').after($('
        ').html(lang.errorNotSupport)).hide(); + return; + } else if (!editor.getOpt('videoActionName')) { + $('#filePickerReady').after($('
        ').html(lang.errorLoadConfig)).hide(); + return; + } + + uploader = _this.uploader = WebUploader.create({ + pick: { + id: '#filePickerReady', + label: lang.uploadSelectFile + }, + swf: '../../third-party/webuploader/Uploader.swf', + server: actionUrl, + fileVal: editor.getOpt('videoFieldName'), + duplicate: true, + fileSingleSizeLimit: fileMaxSize, + compress: false + }); + uploader.addButton({ + id: '#filePickerBlock' + }); + uploader.addButton({ + id: '#filePickerBtn', + label: lang.uploadAddFile + }); + + setState('pedding'); + + // 当有文件添加进来时执行,负责view的创建 + function addFile(file) { + var $li = $('
      5. ' + + '

        ' + file.name + '

        ' + + '

        ' + + '

        ' + + '
      6. '), + + $btns = $('
        ' + + '' + lang.uploadDelete + '' + + '' + lang.uploadTurnRight + '' + + '' + lang.uploadTurnLeft + '
        ').appendTo($li), + $prgress = $li.find('p.progress span'), + $wrap = $li.find('p.imgWrap'), + $info = $('

        ').hide().appendTo($li), + + showError = function (code) { + switch (code) { + case 'exceed_size': + text = lang.errorExceedSize; + break; + case 'interrupt': + text = lang.errorInterrupt; + break; + case 'http': + text = lang.errorHttp; + break; + case 'not_allow_type': + text = lang.errorFileType; + break; + default: + text = lang.errorUploadRetry; + break; + } + $info.text(text).show(); + }; + + if (file.getStatus() === 'invalid') { + showError(file.statusText); + } else { + $wrap.text(lang.uploadPreview); + if ('|png|jpg|jpeg|bmp|gif|'.indexOf('|'+file.ext.toLowerCase()+'|') == -1) { + $wrap.empty().addClass('notimage').append('' + + '' + file.name + ''); + } else { + if (browser.ie && browser.version <= 7) { + $wrap.text(lang.uploadNoPreview); + } else { + uploader.makeThumb(file, function (error, src) { + if (error || !src || (/^data:/.test(src) && browser.ie && browser.version <= 7)) { + $wrap.text(lang.uploadNoPreview); + } else { + var $img = $(''); + $wrap.empty().append($img); + $img.on('error', function () { + $wrap.text(lang.uploadNoPreview); + }); + } + }, thumbnailWidth, thumbnailHeight); + } + } + percentages[ file.id ] = [ file.size, 0 ]; + file.rotation = 0; + + /* 检查文件格式 */ + if (!file.ext || acceptExtensions.indexOf(file.ext.toLowerCase()) == -1) { + showError('not_allow_type'); + uploader.removeFile(file); + } + } + + file.on('statuschange', function (cur, prev) { + if (prev === 'progress') { + $prgress.hide().width(0); + } else if (prev === 'queued') { + $li.off('mouseenter mouseleave'); + $btns.remove(); + } + // 成功 + if (cur === 'error' || cur === 'invalid') { + showError(file.statusText); + percentages[ file.id ][ 1 ] = 1; + } else if (cur === 'interrupt') { + showError('interrupt'); + } else if (cur === 'queued') { + percentages[ file.id ][ 1 ] = 0; + } else if (cur === 'progress') { + $info.hide(); + $prgress.css('display', 'block'); + } else if (cur === 'complete') { + } + + $li.removeClass('state-' + prev).addClass('state-' + cur); + }); + + $li.on('mouseenter', function () { + $btns.stop().animate({height: 30}); + }); + $li.on('mouseleave', function () { + $btns.stop().animate({height: 0}); + }); + + $btns.on('click', 'span', function () { + var index = $(this).index(), + deg; + + switch (index) { + case 0: + uploader.removeFile(file); + return; + case 1: + file.rotation += 90; + break; + case 2: + file.rotation -= 90; + break; + } + + if (supportTransition) { + deg = 'rotate(' + file.rotation + 'deg)'; + $wrap.css({ + '-webkit-transform': deg, + '-mos-transform': deg, + '-o-transform': deg, + 'transform': deg + }); + } else { + $wrap.css('filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + (~~((file.rotation / 90) % 4 + 4) % 4) + ')'); + } + + }); + + $li.insertBefore($filePickerBlock); + } + + // 负责view的销毁 + function removeFile(file) { + var $li = $('#' + file.id); + delete percentages[ file.id ]; + updateTotalProgress(); + $li.off().find('.file-panel').off().end().remove(); + } + + function updateTotalProgress() { + var loaded = 0, + total = 0, + spans = $progress.children(), + percent; + + $.each(percentages, function (k, v) { + total += v[ 0 ]; + loaded += v[ 0 ] * v[ 1 ]; + }); + + percent = total ? loaded / total : 0; + + spans.eq(0).text(Math.round(percent * 100) + '%'); + spans.eq(1).css('width', Math.round(percent * 100) + '%'); + updateStatus(); + } + + function setState(val, files) { + + if (val != state) { + + var stats = uploader.getStats(); + + $upload.removeClass('state-' + state); + $upload.addClass('state-' + val); + + switch (val) { + + /* 未选择文件 */ + case 'pedding': + $queue.addClass('element-invisible'); + $statusBar.addClass('element-invisible'); + $placeHolder.removeClass('element-invisible'); + $progress.hide(); $info.hide(); + uploader.refresh(); + break; + + /* 可以开始上传 */ + case 'ready': + $placeHolder.addClass('element-invisible'); + $queue.removeClass('element-invisible'); + $statusBar.removeClass('element-invisible'); + $progress.hide(); $info.show(); + $upload.text(lang.uploadStart); + uploader.refresh(); + break; + + /* 上传中 */ + case 'uploading': + $progress.show(); $info.hide(); + $upload.text(lang.uploadPause); + break; + + /* 暂停上传 */ + case 'paused': + $progress.show(); $info.hide(); + $upload.text(lang.uploadContinue); + break; + + case 'confirm': + $progress.show(); $info.hide(); + $upload.text(lang.uploadStart); + + stats = uploader.getStats(); + if (stats.successNum && !stats.uploadFailNum) { + setState('finish'); + return; + } + break; + + case 'finish': + $progress.hide(); $info.show(); + if (stats.uploadFailNum) { + $upload.text(lang.uploadRetry); + } else { + $upload.text(lang.uploadStart); + } + break; + } + + state = val; + updateStatus(); + + } + + if (!_this.getQueueCount()) { + $upload.addClass('disabled') + } else { + $upload.removeClass('disabled') + } + + } + + function updateStatus() { + var text = '', stats; + + if (state === 'ready') { + text = lang.updateStatusReady.replace('_', fileCount).replace('_KB', WebUploader.formatSize(fileSize)); + } else if (state === 'confirm') { + stats = uploader.getStats(); + if (stats.uploadFailNum) { + text = lang.updateStatusConfirm.replace('_', stats.successNum).replace('_', stats.successNum); + } + } else { + stats = uploader.getStats(); + text = lang.updateStatusFinish.replace('_', fileCount). + replace('_KB', WebUploader.formatSize(fileSize)). + replace('_', stats.successNum); + + if (stats.uploadFailNum) { + text += lang.updateStatusError.replace('_', stats.uploadFailNum); + } + } + + $info.html(text); + } + + uploader.on('fileQueued', function (file) { + fileCount++; + fileSize += file.size; + + if (fileCount === 1) { + $placeHolder.addClass('element-invisible'); + $statusBar.show(); + } + + addFile(file); + }); + + uploader.on('fileDequeued', function (file) { + fileCount--; + fileSize -= file.size; + + removeFile(file); + updateTotalProgress(); + }); + + uploader.on('filesQueued', function (file) { + if (!uploader.isInProgress() && (state == 'pedding' || state == 'finish' || state == 'confirm' || state == 'ready')) { + setState('ready'); + } + updateTotalProgress(); + }); + + uploader.on('all', function (type, files) { + switch (type) { + case 'uploadFinished': + setState('confirm', files); + break; + case 'startUpload': + /* 添加额外的GET参数 */ + var params = utils.serializeParam(editor.queryCommandValue('serverparam')) || '', + url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?':'&') + 'encode=utf-8&' + params); + uploader.option('server', url); + setState('uploading', files); + break; + case 'stopUpload': + setState('paused', files); + break; + } + }); + + uploader.on('uploadBeforeSend', function (file, data, header) { + //这里可以通过data对象添加POST参数 + header['X_Requested_With'] = 'XMLHttpRequest'; + }); + + uploader.on('uploadProgress', function (file, percentage) { + var $li = $('#' + file.id), + $percent = $li.find('.progress span'); + + $percent.css('width', percentage * 100 + '%'); + percentages[ file.id ][ 1 ] = percentage; + updateTotalProgress(); + }); + + uploader.on('uploadSuccess', function (file, ret) { + var $file = $('#' + file.id); + try { + var responseText = (ret._raw || ret), + json = utils.str2json(responseText); + if (json.state == 'SUCCESS') { + uploadVideoList.push({ + 'url': json.url, + 'type': json.type, + 'original':json.original + }); + $file.append(''); + } else { + $file.find('.error').text(json.state).show(); + } + } catch (e) { + $file.find('.error').text(lang.errorServerUpload).show(); + } + }); + + uploader.on('uploadError', function (file, code) { + }); + uploader.on('error', function (code, file) { + if (code == 'Q_TYPE_DENIED' || code == 'F_EXCEED_SIZE') { + addFile(file); + } + }); + uploader.on('uploadComplete', function (file, ret) { + }); + + $upload.on('click', function () { + if ($(this).hasClass('disabled')) { + return false; + } + + if (state === 'ready') { + uploader.upload(); + } else if (state === 'paused') { + uploader.upload(); + } else if (state === 'uploading') { + uploader.stop(); + } + }); + + $upload.addClass('state-' + state); + updateTotalProgress(); + }, + getQueueCount: function () { + var file, i, status, readyFile = 0, files = this.uploader.getFiles(); + for (i = 0; file = files[i++]; ) { + status = file.getStatus(); + if (status == 'queued' || status == 'uploading' || status == 'progress') readyFile++; + } + return readyFile; + }, + refresh: function(){ + this.uploader.refresh(); + } + }; + +})(); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/webapp/webapp.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/webapp/webapp.html new file mode 100644 index 000000000..161437790 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/webapp/webapp.html @@ -0,0 +1,53 @@ + + + + + + + + + +
        +
        +
        + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/wordimage/fClipboard_ueditor.swf b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/wordimage/fClipboard_ueditor.swf new file mode 100644 index 000000000..ac5d27f81 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/wordimage/fClipboard_ueditor.swf differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/wordimage/imageUploader.swf b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/wordimage/imageUploader.swf new file mode 100644 index 000000000..2a554cadb Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/wordimage/imageUploader.swf differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/wordimage/tangram.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/wordimage/tangram.js new file mode 100644 index 000000000..2ebd8fd3d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/wordimage/tangram.js @@ -0,0 +1,1495 @@ +// Copyright (c) 2009, Baidu Inc. All rights reserved. +// +// Licensed under the BSD License +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http:// tangram.baidu.com/license.html +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + /** + * @namespace T Tangram七巧板 + * @name T + * @version 1.6.0 +*/ + +/** + * 声明baidu包 + * @author: allstar, erik, meizz, berg + */ +var T, + baidu = T = baidu || {version: "1.5.0"}; +baidu.guid = "$BAIDU$"; +baidu.$$ = window[baidu.guid] = window[baidu.guid] || {global:{}}; + +/** + * 使用flash资源封装的一些功能 + * @namespace baidu.flash + */ +baidu.flash = baidu.flash || {}; + +/** + * 操作dom的方法 + * @namespace baidu.dom + */ +baidu.dom = baidu.dom || {}; + + +/** + * 从文档中获取指定的DOM元素 + * @name baidu.dom.g + * @function + * @grammar baidu.dom.g(id) + * @param {string|HTMLElement} id 元素的id或DOM元素. + * @shortcut g,T.G + * @meta standard + * @see baidu.dom.q + * + * @return {HTMLElement|null} 获取的元素,查找不到时返回null,如果参数不合法,直接返回参数. + */ +baidu.dom.g = function(id) { + if (!id) return null; + if ('string' == typeof id || id instanceof String) { + return document.getElementById(id); + } else if (id.nodeName && (id.nodeType == 1 || id.nodeType == 9)) { + return id; + } + return null; +}; +baidu.g = baidu.G = baidu.dom.g; + + +/** + * 操作数组的方法 + * @namespace baidu.array + */ + +baidu.array = baidu.array || {}; + + +/** + * 遍历数组中所有元素 + * @name baidu.array.each + * @function + * @grammar baidu.array.each(source, iterator[, thisObject]) + * @param {Array} source 需要遍历的数组 + * @param {Function} iterator 对每个数组元素进行调用的函数,该函数有两个参数,第一个为数组元素,第二个为数组索引值,function (item, index)。 + * @param {Object} [thisObject] 函数调用时的this指针,如果没有此参数,默认是当前遍历的数组 + * @remark + * each方法不支持对Object的遍历,对Object的遍历使用baidu.object.each 。 + * @shortcut each + * @meta standard + * + * @returns {Array} 遍历的数组 + */ + +baidu.each = baidu.array.forEach = baidu.array.each = function (source, iterator, thisObject) { + var returnValue, item, i, len = source.length; + + if ('function' == typeof iterator) { + for (i = 0; i < len; i++) { + item = source[i]; + returnValue = iterator.call(thisObject || source, item, i); + + if (returnValue === false) { + break; + } + } + } + return source; +}; + +/** + * 对语言层面的封装,包括类型判断、模块扩展、继承基类以及对象自定义事件的支持。 + * @namespace baidu.lang + */ +baidu.lang = baidu.lang || {}; + + +/** + * 判断目标参数是否为function或Function实例 + * @name baidu.lang.isFunction + * @function + * @grammar baidu.lang.isFunction(source) + * @param {Any} source 目标参数 + * @version 1.2 + * @see baidu.lang.isString,baidu.lang.isObject,baidu.lang.isNumber,baidu.lang.isArray,baidu.lang.isElement,baidu.lang.isBoolean,baidu.lang.isDate + * @meta standard + * @returns {boolean} 类型判断结果 + */ +baidu.lang.isFunction = function (source) { + return '[object Function]' == Object.prototype.toString.call(source); +}; + +/** + * 判断目标参数是否string类型或String对象 + * @name baidu.lang.isString + * @function + * @grammar baidu.lang.isString(source) + * @param {Any} source 目标参数 + * @shortcut isString + * @meta standard + * @see baidu.lang.isObject,baidu.lang.isNumber,baidu.lang.isArray,baidu.lang.isElement,baidu.lang.isBoolean,baidu.lang.isDate + * + * @returns {boolean} 类型判断结果 + */ +baidu.lang.isString = function (source) { + return '[object String]' == Object.prototype.toString.call(source); +}; +baidu.isString = baidu.lang.isString; + + +/** + * 判断浏览器类型和特性的属性 + * @namespace baidu.browser + */ +baidu.browser = baidu.browser || {}; + + +/** + * 判断是否为opera浏览器 + * @property opera opera版本号 + * @grammar baidu.browser.opera + * @meta standard + * @see baidu.browser.ie,baidu.browser.firefox,baidu.browser.safari,baidu.browser.chrome + * @returns {Number} opera版本号 + */ + +/** + * opera 从10开始不是用opera后面的字符串进行版本的判断 + * 在Browser identification最后添加Version + 数字进行版本标识 + * opera后面的数字保持在9.80不变 + */ +baidu.browser.opera = /opera(\/| )(\d+(\.\d+)?)(.+?(version\/(\d+(\.\d+)?)))?/i.test(navigator.userAgent) ? + ( RegExp["\x246"] || RegExp["\x242"] ) : undefined; + + +/** + * 在目标元素的指定位置插入HTML代码 + * @name baidu.dom.insertHTML + * @function + * @grammar baidu.dom.insertHTML(element, position, html) + * @param {HTMLElement|string} element 目标元素或目标元素的id + * @param {string} position 插入html的位置信息,取值为beforeBegin,afterBegin,beforeEnd,afterEnd + * @param {string} html 要插入的html + * @remark + * + * 对于position参数,大小写不敏感
        + * 参数的意思:beforeBegin<span>afterBegin this is span! beforeEnd</span> afterEnd
        + * 此外,如果使用本函数插入带有script标签的HTML字符串,script标签对应的脚本将不会被执行。 + * + * @shortcut insertHTML + * @meta standard + * + * @returns {HTMLElement} 目标元素 + */ +baidu.dom.insertHTML = function (element, position, html) { + element = baidu.dom.g(element); + var range,begin; + if (element.insertAdjacentHTML && !baidu.browser.opera) { + element.insertAdjacentHTML(position, html); + } else { + range = element.ownerDocument.createRange(); + position = position.toUpperCase(); + if (position == 'AFTERBEGIN' || position == 'BEFOREEND') { + range.selectNodeContents(element); + range.collapse(position == 'AFTERBEGIN'); + } else { + begin = position == 'BEFOREBEGIN'; + range[begin ? 'setStartBefore' : 'setEndAfter'](element); + range.collapse(begin); + } + range.insertNode(range.createContextualFragment(html)); + } + return element; +}; + +baidu.insertHTML = baidu.dom.insertHTML; + +/** + * 操作flash对象的方法,包括创建flash对象、获取flash对象以及判断flash插件的版本号 + * @namespace baidu.swf + */ +baidu.swf = baidu.swf || {}; + + +/** + * 浏览器支持的flash插件版本 + * @property version 浏览器支持的flash插件版本 + * @grammar baidu.swf.version + * @return {String} 版本号 + * @meta standard + */ +baidu.swf.version = (function () { + var n = navigator; + if (n.plugins && n.mimeTypes.length) { + var plugin = n.plugins["Shockwave Flash"]; + if (plugin && plugin.description) { + return plugin.description + .replace(/([a-zA-Z]|\s)+/, "") + .replace(/(\s)+r/, ".") + ".0"; + } + } else if (window.ActiveXObject && !window.opera) { + for (var i = 12; i >= 2; i--) { + try { + var c = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.' + i); + if (c) { + var version = c.GetVariable("$version"); + return version.replace(/WIN/g,'').replace(/,/g,'.'); + } + } catch(e) {} + } + } +})(); + +/** + * 操作字符串的方法 + * @namespace baidu.string + */ +baidu.string = baidu.string || {}; + + +/** + * 对目标字符串进行html编码 + * @name baidu.string.encodeHTML + * @function + * @grammar baidu.string.encodeHTML(source) + * @param {string} source 目标字符串 + * @remark + * 编码字符有5个:&<>"' + * @shortcut encodeHTML + * @meta standard + * @see baidu.string.decodeHTML + * + * @returns {string} html编码后的字符串 + */ +baidu.string.encodeHTML = function (source) { + return String(source) + .replace(/&/g,'&') + .replace(//g,'>') + .replace(/"/g, """) + .replace(/'/g, "'"); +}; + +baidu.encodeHTML = baidu.string.encodeHTML; + +/** + * 创建flash对象的html字符串 + * @name baidu.swf.createHTML + * @function + * @grammar baidu.swf.createHTML(options) + * + * @param {Object} options 创建flash的选项参数 + * @param {string} options.id 要创建的flash的标识 + * @param {string} options.url flash文件的url + * @param {String} options.errorMessage 未安装flash player或flash player版本号过低时的提示 + * @param {string} options.ver 最低需要的flash player版本号 + * @param {string} options.width flash的宽度 + * @param {string} options.height flash的高度 + * @param {string} options.align flash的对齐方式,允许值:middle/left/right/top/bottom + * @param {string} options.base 设置用于解析swf文件中的所有相对路径语句的基本目录或URL + * @param {string} options.bgcolor swf文件的背景色 + * @param {string} options.salign 设置缩放的swf文件在由width和height设置定义的区域内的位置。允许值:l/r/t/b/tl/tr/bl/br + * @param {boolean} options.menu 是否显示右键菜单,允许值:true/false + * @param {boolean} options.loop 播放到最后一帧时是否重新播放,允许值: true/false + * @param {boolean} options.play flash是否在浏览器加载时就开始播放。允许值:true/false + * @param {string} options.quality 设置flash播放的画质,允许值:low/medium/high/autolow/autohigh/best + * @param {string} options.scale 设置flash内容如何缩放来适应设置的宽高。允许值:showall/noborder/exactfit + * @param {string} options.wmode 设置flash的显示模式。允许值:window/opaque/transparent + * @param {string} options.allowscriptaccess 设置flash与页面的通信权限。允许值:always/never/sameDomain + * @param {string} options.allownetworking 设置swf文件中允许使用的网络API。允许值:all/internal/none + * @param {boolean} options.allowfullscreen 是否允许flash全屏。允许值:true/false + * @param {boolean} options.seamlesstabbing 允许设置执行无缝跳格,从而使用户能跳出flash应用程序。该参数只能在安装Flash7及更高版本的Windows中使用。允许值:true/false + * @param {boolean} options.devicefont 设置静态文本对象是否以设备字体呈现。允许值:true/false + * @param {boolean} options.swliveconnect 第一次加载flash时浏览器是否应启动Java。允许值:true/false + * @param {Object} options.vars 要传递给flash的参数,支持JSON或string类型。 + * + * @see baidu.swf.create + * @meta standard + * @returns {string} flash对象的html字符串 + */ +baidu.swf.createHTML = function (options) { + options = options || {}; + var version = baidu.swf.version, + needVersion = options['ver'] || '6.0.0', + vUnit1, vUnit2, i, k, len, item, tmpOpt = {}, + encodeHTML = baidu.string.encodeHTML; + for (k in options) { + tmpOpt[k] = options[k]; + } + options = tmpOpt; + if (version) { + version = version.split('.'); + needVersion = needVersion.split('.'); + for (i = 0; i < 3; i++) { + vUnit1 = parseInt(version[i], 10); + vUnit2 = parseInt(needVersion[i], 10); + if (vUnit2 < vUnit1) { + break; + } else if (vUnit2 > vUnit1) { + return ''; + } + } + } else { + return ''; + } + + var vars = options['vars'], + objProperties = ['classid', 'codebase', 'id', 'width', 'height', 'align']; + options['align'] = options['align'] || 'middle'; + options['classid'] = 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000'; + options['codebase'] = 'http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0'; + options['movie'] = options['url'] || ''; + delete options['vars']; + delete options['url']; + if ('string' == typeof vars) { + options['flashvars'] = vars; + } else { + var fvars = []; + for (k in vars) { + item = vars[k]; + fvars.push(k + "=" + encodeURIComponent(item)); + } + options['flashvars'] = fvars.join('&'); + } + var str = [''); + var params = { + 'wmode' : 1, + 'scale' : 1, + 'quality' : 1, + 'play' : 1, + 'loop' : 1, + 'menu' : 1, + 'salign' : 1, + 'bgcolor' : 1, + 'base' : 1, + 'allowscriptaccess' : 1, + 'allownetworking' : 1, + 'allowfullscreen' : 1, + 'seamlesstabbing' : 1, + 'devicefont' : 1, + 'swliveconnect' : 1, + 'flashvars' : 1, + 'movie' : 1 + }; + + for (k in options) { + item = options[k]; + k = k.toLowerCase(); + if (params[k] && (item || item === false || item === 0)) { + str.push(''); + } + } + options['src'] = options['movie']; + options['name'] = options['id']; + delete options['id']; + delete options['movie']; + delete options['classid']; + delete options['codebase']; + options['type'] = 'application/x-shockwave-flash'; + options['pluginspage'] = 'http://www.macromedia.com/go/getflashplayer'; + str.push(''); + + return str.join(''); +}; + + +/** + * 在页面中创建一个flash对象 + * @name baidu.swf.create + * @function + * @grammar baidu.swf.create(options[, container]) + * + * @param {Object} options 创建flash的选项参数 + * @param {string} options.id 要创建的flash的标识 + * @param {string} options.url flash文件的url + * @param {String} options.errorMessage 未安装flash player或flash player版本号过低时的提示 + * @param {string} options.ver 最低需要的flash player版本号 + * @param {string} options.width flash的宽度 + * @param {string} options.height flash的高度 + * @param {string} options.align flash的对齐方式,允许值:middle/left/right/top/bottom + * @param {string} options.base 设置用于解析swf文件中的所有相对路径语句的基本目录或URL + * @param {string} options.bgcolor swf文件的背景色 + * @param {string} options.salign 设置缩放的swf文件在由width和height设置定义的区域内的位置。允许值:l/r/t/b/tl/tr/bl/br + * @param {boolean} options.menu 是否显示右键菜单,允许值:true/false + * @param {boolean} options.loop 播放到最后一帧时是否重新播放,允许值: true/false + * @param {boolean} options.play flash是否在浏览器加载时就开始播放。允许值:true/false + * @param {string} options.quality 设置flash播放的画质,允许值:low/medium/high/autolow/autohigh/best + * @param {string} options.scale 设置flash内容如何缩放来适应设置的宽高。允许值:showall/noborder/exactfit + * @param {string} options.wmode 设置flash的显示模式。允许值:window/opaque/transparent + * @param {string} options.allowscriptaccess 设置flash与页面的通信权限。允许值:always/never/sameDomain + * @param {string} options.allownetworking 设置swf文件中允许使用的网络API。允许值:all/internal/none + * @param {boolean} options.allowfullscreen 是否允许flash全屏。允许值:true/false + * @param {boolean} options.seamlesstabbing 允许设置执行无缝跳格,从而使用户能跳出flash应用程序。该参数只能在安装Flash7及更高版本的Windows中使用。允许值:true/false + * @param {boolean} options.devicefont 设置静态文本对象是否以设备字体呈现。允许值:true/false + * @param {boolean} options.swliveconnect 第一次加载flash时浏览器是否应启动Java。允许值:true/false + * @param {Object} options.vars 要传递给flash的参数,支持JSON或string类型。 + * + * @param {HTMLElement|string} [container] flash对象的父容器元素,不传递该参数时在当前代码位置创建flash对象。 + * @meta standard + * @see baidu.swf.createHTML,baidu.swf.getMovie + */ +baidu.swf.create = function (options, target) { + options = options || {}; + var html = baidu.swf.createHTML(options) + || options['errorMessage'] + || ''; + + if (target && 'string' == typeof target) { + target = document.getElementById(target); + } + baidu.dom.insertHTML( target || document.body ,'beforeEnd',html ); +}; +/** + * 判断是否为ie浏览器 + * @name baidu.browser.ie + * @field + * @grammar baidu.browser.ie + * @returns {Number} IE版本号 + */ +baidu.browser.ie = baidu.ie = /msie (\d+\.\d+)/i.test(navigator.userAgent) ? (document.documentMode || + RegExp['\x241']) : undefined; + +/** + * 移除数组中的项 + * @name baidu.array.remove + * @function + * @grammar baidu.array.remove(source, match) + * @param {Array} source 需要移除项的数组 + * @param {Any} match 要移除的项 + * @meta standard + * @see baidu.array.removeAt + * + * @returns {Array} 移除后的数组 + */ +baidu.array.remove = function (source, match) { + var len = source.length; + + while (len--) { + if (len in source && source[len] === match) { + source.splice(len, 1); + } + } + return source; +}; + +/** + * 判断目标参数是否Array对象 + * @name baidu.lang.isArray + * @function + * @grammar baidu.lang.isArray(source) + * @param {Any} source 目标参数 + * @meta standard + * @see baidu.lang.isString,baidu.lang.isObject,baidu.lang.isNumber,baidu.lang.isElement,baidu.lang.isBoolean,baidu.lang.isDate + * + * @returns {boolean} 类型判断结果 + */ +baidu.lang.isArray = function (source) { + return '[object Array]' == Object.prototype.toString.call(source); +}; + + + +/** + * 将一个变量转换成array + * @name baidu.lang.toArray + * @function + * @grammar baidu.lang.toArray(source) + * @param {mix} source 需要转换成array的变量 + * @version 1.3 + * @meta standard + * @returns {array} 转换后的array + */ +baidu.lang.toArray = function (source) { + if (source === null || source === undefined) + return []; + if (baidu.lang.isArray(source)) + return source; + if (typeof source.length !== 'number' || typeof source === 'string' || baidu.lang.isFunction(source)) { + return [source]; + } + if (source.item) { + var l = source.length, array = new Array(l); + while (l--) + array[l] = source[l]; + return array; + } + + return [].slice.call(source); +}; + +/** + * 获得flash对象的实例 + * @name baidu.swf.getMovie + * @function + * @grammar baidu.swf.getMovie(name) + * @param {string} name flash对象的名称 + * @see baidu.swf.create + * @meta standard + * @returns {HTMLElement} flash对象的实例 + */ +baidu.swf.getMovie = function (name) { + var movie = document[name], ret; + return baidu.browser.ie == 9 ? + movie && movie.length ? + (ret = baidu.array.remove(baidu.lang.toArray(movie),function(item){ + return item.tagName.toLowerCase() != "embed"; + })).length == 1 ? ret[0] : ret + : movie + : movie || window[name]; +}; + + +baidu.flash._Base = (function(){ + + var prefix = 'bd__flash__'; + + /** + * 创建一个随机的字符串 + * @private + * @return {String} + */ + function _createString(){ + return prefix + Math.floor(Math.random() * 2147483648).toString(36); + }; + + /** + * 检查flash状态 + * @private + * @param {Object} target flash对象 + * @return {Boolean} + */ + function _checkReady(target){ + if(typeof target !== 'undefined' && typeof target.flashInit !== 'undefined' && target.flashInit()){ + return true; + }else{ + return false; + } + }; + + /** + * 调用之前进行压栈的函数 + * @private + * @param {Array} callQueue 调用队列 + * @param {Object} target flash对象 + * @return {Null} + */ + function _callFn(callQueue, target){ + var result = null; + + callQueue = callQueue.reverse(); + baidu.each(callQueue, function(item){ + result = target.call(item.fnName, item.params); + item.callBack(result); + }); + }; + + /** + * 为传入的匿名函数创建函数名 + * @private + * @param {String|Function} fun 传入的匿名函数或者函数名 + * @return {String} + */ + function _createFunName(fun){ + var name = ''; + + if(baidu.lang.isFunction(fun)){ + name = _createString(); + window[name] = function(){ + fun.apply(window, arguments); + }; + + return name; + }else if(baidu.lang.isString){ + return fun; + } + }; + + /** + * 绘制flash + * @private + * @param {Object} options 创建参数 + * @return {Object} + */ + function _render(options){ + if(!options.id){ + options.id = _createString(); + } + + var container = options.container || ''; + delete(options.container); + + baidu.swf.create(options, container); + + return baidu.swf.getMovie(options.id); + }; + + return function(options, callBack){ + var me = this, + autoRender = (typeof options.autoRender !== 'undefined' ? options.autoRender : true), + createOptions = options.createOptions || {}, + target = null, + isReady = false, + callQueue = [], + timeHandle = null, + callBack = callBack || []; + + /** + * 将flash文件绘制到页面上 + * @public + * @return {Null} + */ + me.render = function(){ + target = _render(createOptions); + + if(callBack.length > 0){ + baidu.each(callBack, function(funName, index){ + callBack[index] = _createFunName(options[funName] || new Function()); + }); + } + me.call('setJSFuncName', [callBack]); + }; + + /** + * 返回flash状态 + * @return {Boolean} + */ + me.isReady = function(){ + return isReady; + }; + + /** + * 调用flash接口的统一入口 + * @param {String} fnName 调用的函数名 + * @param {Array} params 传入的参数组成的数组,若不许要参数,需传入空数组 + * @param {Function} [callBack] 异步调用后将返回值作为参数的调用回调函数,如无返回值,可以不传入此参数 + * @return {Null} + */ + me.call = function(fnName, params, callBack){ + if(!fnName) return null; + callBack = callBack || new Function(); + + var result = null; + + if(isReady){ + result = target.call(fnName, params); + callBack(result); + }else{ + callQueue.push({ + fnName: fnName, + params: params, + callBack: callBack + }); + + (!timeHandle) && (timeHandle = setInterval(_check, 200)); + } + }; + + /** + * 为传入的匿名函数创建函数名 + * @public + * @param {String|Function} fun 传入的匿名函数或者函数名 + * @return {String} + */ + me.createFunName = function(fun){ + return _createFunName(fun); + }; + + /** + * 检查flash是否ready, 并进行调用 + * @private + * @return {Null} + */ + function _check(){ + if(_checkReady(target)){ + clearInterval(timeHandle); + timeHandle = null; + _call(); + + isReady = true; + } + }; + + /** + * 调用之前进行压栈的函数 + * @private + * @return {Null} + */ + function _call(){ + _callFn(callQueue, target); + callQueue = []; + } + + autoRender && me.render(); + }; +})(); + + + +/** + * 创建flash based imageUploader + * @class + * @grammar baidu.flash.imageUploader(options) + * @param {Object} createOptions 创建flash时需要的参数,请参照baidu.swf.create文档 + * @config {Object} vars 创建imageUploader时所需要的参数 + * @config {Number} vars.gridWidth 每一个预览图片所占的宽度,应该为flash寛的整除 + * @config {Number} vars.gridHeight 每一个预览图片所占的高度,应该为flash高的整除 + * @config {Number} vars.picWidth 单张预览图片的宽度 + * @config {Number} vars.picHeight 单张预览图片的高度 + * @config {String} vars.uploadDataFieldName POST请求中图片数据的key,默认值'picdata' + * @config {String} vars.picDescFieldName POST请求中图片描述的key,默认值'picDesc' + * @config {Number} vars.maxSize 文件的最大体积,单位'MB' + * @config {Number} vars.compressSize 上传前如果图片体积超过该值,会先压缩 + * @config {Number} vars.maxNum:32 最大上传多少个文件 + * @config {Number} vars.compressLength 能接受的最大边长,超过该值会等比压缩 + * @config {String} vars.url 上传的url地址 + * @config {Number} vars.mode mode == 0时,是使用滚动条,mode == 1时,拉伸flash, 默认值为0 + * @see baidu.swf.createHTML + * @param {String} backgroundUrl 背景图片路径 + * @param {String} listBacgroundkUrl 布局控件背景 + * @param {String} buttonUrl 按钮图片不背景 + * @param {String|Function} selectFileCallback 选择文件的回调 + * @param {String|Function} exceedFileCallback文件超出限制的最大体积时的回调 + * @param {String|Function} deleteFileCallback 删除文件的回调 + * @param {String|Function} startUploadCallback 开始上传某个文件时的回调 + * @param {String|Function} uploadCompleteCallback 某个文件上传完成的回调 + * @param {String|Function} uploadErrorCallback 某个文件上传失败的回调 + * @param {String|Function} allCompleteCallback 全部上传完成时的回调 + * @param {String|Function} changeFlashHeight 改变Flash的高度,mode==1的时候才有用 + */ +baidu.flash.imageUploader = baidu.flash.imageUploader || function(options){ + + var me = this, + options = options || {}, + _flash = new baidu.flash._Base(options, [ + 'selectFileCallback', + 'exceedFileCallback', + 'deleteFileCallback', + 'startUploadCallback', + 'uploadCompleteCallback', + 'uploadErrorCallback', + 'allCompleteCallback', + 'changeFlashHeight' + ]); + /** + * 开始或回复上传图片 + * @public + * @return {Null} + */ + me.upload = function(){ + _flash.call('upload'); + }; + + /** + * 暂停上传图片 + * @public + * @return {Null} + */ + me.pause = function(){ + _flash.call('pause'); + }; + me.addCustomizedParams = function(index,obj){ + _flash.call('addCustomizedParams',[index,obj]); + } +}; + +/** + * 操作原生对象的方法 + * @namespace baidu.object + */ +baidu.object = baidu.object || {}; + + +/** + * 将源对象的所有属性拷贝到目标对象中 + * @author erik + * @name baidu.object.extend + * @function + * @grammar baidu.object.extend(target, source) + * @param {Object} target 目标对象 + * @param {Object} source 源对象 + * @see baidu.array.merge + * @remark + * +1.目标对象中,与源对象key相同的成员将会被覆盖。
        +2.源对象的prototype成员不会拷贝。 + + * @shortcut extend + * @meta standard + * + * @returns {Object} 目标对象 + */ +baidu.extend = +baidu.object.extend = function (target, source) { + for (var p in source) { + if (source.hasOwnProperty(p)) { + target[p] = source[p]; + } + } + + return target; +}; + + + + + +/** + * 创建flash based fileUploader + * @class + * @grammar baidu.flash.fileUploader(options) + * @param {Object} options + * @config {Object} createOptions 创建flash时需要的参数,请参照baidu.swf.create文档 + * @config {String} createOptions.width + * @config {String} createOptions.height + * @config {Number} maxNum 最大可选文件数 + * @config {Function|String} selectFile + * @config {Function|String} exceedMaxSize + * @config {Function|String} deleteFile + * @config {Function|String} uploadStart + * @config {Function|String} uploadComplete + * @config {Function|String} uploadError + * @config {Function|String} uploadProgress + */ +baidu.flash.fileUploader = baidu.flash.fileUploader || function(options){ + var me = this, + options = options || {}; + + options.createOptions = baidu.extend({ + wmod: 'transparent' + },options.createOptions || {}); + + var _flash = new baidu.flash._Base(options, [ + 'selectFile', + 'exceedMaxSize', + 'deleteFile', + 'uploadStart', + 'uploadComplete', + 'uploadError', + 'uploadProgress' + ]); + + _flash.call('setMaxNum', options.maxNum ? [options.maxNum] : [1]); + + /** + * 设置当鼠标移动到flash上时,是否变成手型 + * @public + * @param {Boolean} isCursor + * @return {Null} + */ + me.setHandCursor = function(isCursor){ + _flash.call('setHandCursor', [isCursor || false]); + }; + + /** + * 设置鼠标相应函数名 + * @param {String|Function} fun + */ + me.setMSFunName = function(fun){ + _flash.call('setMSFunName',[_flash.createFunName(fun)]); + }; + + /** + * 执行上传操作 + * @param {String} url 上传的url + * @param {String} fieldName 上传的表单字段名 + * @param {Object} postData 键值对,上传的POST数据 + * @param {Number|Array|null|-1} [index]上传的文件序列 + * Int值上传该文件 + * Array一次串行上传该序列文件 + * -1/null上传所有文件 + * @return {Null} + */ + me.upload = function(url, fieldName, postData, index){ + + if(typeof url !== 'string' || typeof fieldName !== 'string') return null; + if(typeof index === 'undefined') index = -1; + + _flash.call('upload', [url, fieldName, postData, index]); + }; + + /** + * 取消上传操作 + * @public + * @param {Number|-1} index + */ + me.cancel = function(index){ + if(typeof index === 'undefined') index = -1; + _flash.call('cancel', [index]); + }; + + /** + * 删除文件 + * @public + * @param {Number|Array} [index] 要删除的index,不传则全部删除 + * @param {Function} callBack + * */ + me.deleteFile = function(index, callBack){ + + var callBackAll = function(list){ + callBack && callBack(list); + }; + + if(typeof index === 'undefined'){ + _flash.call('deleteFilesAll', [], callBackAll); + return; + }; + + if(typeof index === 'Number') index = [index]; + index.sort(function(a,b){ + return b-a; + }); + baidu.each(index, function(item){ + _flash.call('deleteFileBy', item, callBackAll); + }); + }; + + /** + * 添加文件类型,支持macType + * @public + * @param {Object|Array[Object]} type {description:String, extention:String} + * @return {Null}; + */ + me.addFileType = function(type){ + var type = type || [[]]; + + if(type instanceof Array) type = [type]; + else type = [[type]]; + _flash.call('addFileTypes', type); + }; + + /** + * 设置文件类型,支持macType + * @public + * @param {Object|Array[Object]} type {description:String, extention:String} + * @return {Null}; + */ + me.setFileType = function(type){ + var type = type || [[]]; + + if(type instanceof Array) type = [type]; + else type = [[type]]; + _flash.call('setFileTypes', type); + }; + + /** + * 设置可选文件的数量限制 + * @public + * @param {Number} num + * @return {Null} + */ + me.setMaxNum = function(num){ + _flash.call('setMaxNum', [num]); + }; + + /** + * 设置可选文件大小限制,以兆M为单位 + * @public + * @param {Number} num,0为无限制 + * @return {Null} + */ + me.setMaxSize = function(num){ + _flash.call('setMaxSize', [num]); + }; + + /** + * @public + */ + me.getFileAll = function(callBack){ + _flash.call('getFileAll', [], callBack); + }; + + /** + * @public + * @param {Number} index + * @param {Function} [callBack] + */ + me.getFileByIndex = function(index, callBack){ + _flash.call('getFileByIndex', [], callBack); + }; + + /** + * @public + * @param {Number} index + * @param {function} [callBack] + */ + me.getStatusByIndex = function(index, callBack){ + _flash.call('getStatusByIndex', [], callBack); + }; +}; + +/** + * 使用动态script标签请求服务器资源,包括由服务器端的回调和浏览器端的回调 + * @namespace baidu.sio + */ +baidu.sio = baidu.sio || {}; + +/** + * + * @param {HTMLElement} src script节点 + * @param {String} url script节点的地址 + * @param {String} [charset] 编码 + */ +baidu.sio._createScriptTag = function(scr, url, charset){ + scr.setAttribute('type', 'text/javascript'); + charset && scr.setAttribute('charset', charset); + scr.setAttribute('src', url); + document.getElementsByTagName('head')[0].appendChild(scr); +}; + +/** + * 删除script的属性,再删除script标签,以解决修复内存泄漏的问题 + * + * @param {HTMLElement} src script节点 + */ +baidu.sio._removeScriptTag = function(scr){ + if (scr.clearAttributes) { + scr.clearAttributes(); + } else { + for (var attr in scr) { + if (scr.hasOwnProperty(attr)) { + delete scr[attr]; + } + } + } + if(scr && scr.parentNode){ + scr.parentNode.removeChild(scr); + } + scr = null; +}; + + +/** + * 通过script标签加载数据,加载完成由浏览器端触发回调 + * @name baidu.sio.callByBrowser + * @function + * @grammar baidu.sio.callByBrowser(url, opt_callback, opt_options) + * @param {string} url 加载数据的url + * @param {Function|string} opt_callback 数据加载结束时调用的函数或函数名 + * @param {Object} opt_options 其他可选项 + * @config {String} [charset] script的字符集 + * @config {Integer} [timeOut] 超时时间,超过这个时间将不再响应本请求,并触发onfailure函数 + * @config {Function} [onfailure] timeOut设定后才生效,到达超时时间时触发本函数 + * @remark + * 1、与callByServer不同,callback参数只支持Function类型,不支持string。 + * 2、如果请求了一个不存在的页面,callback函数在IE/opera下也会被调用,因此使用者需要在onsuccess函数中判断数据是否正确加载。 + * @meta standard + * @see baidu.sio.callByServer + */ +baidu.sio.callByBrowser = function (url, opt_callback, opt_options) { + var scr = document.createElement("SCRIPT"), + scriptLoaded = 0, + options = opt_options || {}, + charset = options['charset'], + callback = opt_callback || function(){}, + timeOut = options['timeOut'] || 0, + timer; + scr.onload = scr.onreadystatechange = function () { + if (scriptLoaded) { + return; + } + + var readyState = scr.readyState; + if ('undefined' == typeof readyState + || readyState == "loaded" + || readyState == "complete") { + scriptLoaded = 1; + try { + callback(); + clearTimeout(timer); + } finally { + scr.onload = scr.onreadystatechange = null; + baidu.sio._removeScriptTag(scr); + } + } + }; + + if( timeOut ){ + timer = setTimeout(function(){ + scr.onload = scr.onreadystatechange = null; + baidu.sio._removeScriptTag(scr); + options.onfailure && options.onfailure(); + }, timeOut); + } + + baidu.sio._createScriptTag(scr, url, charset); +}; + +/** + * 通过script标签加载数据,加载完成由服务器端触发回调 + * @name baidu.sio.callByServer + * @function + * @grammar baidu.sio.callByServer(url, callback[, opt_options]) + * @param {string} url 加载数据的url. + * @param {Function|string} callback 服务器端调用的函数或函数名。如果没有指定本参数,将在URL中寻找options['queryField']做为callback的方法名. + * @param {Object} opt_options 加载数据时的选项. + * @config {string} [charset] script的字符集 + * @config {string} [queryField] 服务器端callback请求字段名,默认为callback + * @config {Integer} [timeOut] 超时时间(单位:ms),超过这个时间将不再响应本请求,并触发onfailure函数 + * @config {Function} [onfailure] timeOut设定后才生效,到达超时时间时触发本函数 + * @remark + * 如果url中已经包含key为“options['queryField']”的query项,将会被替换成callback中参数传递或自动生成的函数名。 + * @meta standard + * @see baidu.sio.callByBrowser + */ +baidu.sio.callByServer = /**@function*/function(url, callback, opt_options) { + var scr = document.createElement('SCRIPT'), + prefix = 'bd__cbs__', + callbackName, + callbackImpl, + options = opt_options || {}, + charset = options['charset'], + queryField = options['queryField'] || 'callback', + timeOut = options['timeOut'] || 0, + timer, + reg = new RegExp('(\\?|&)' + queryField + '=([^&]*)'), + matches; + + if (baidu.lang.isFunction(callback)) { + callbackName = prefix + Math.floor(Math.random() * 2147483648).toString(36); + window[callbackName] = getCallBack(0); + } else if(baidu.lang.isString(callback)){ + callbackName = callback; + } else { + if (matches = reg.exec(url)) { + callbackName = matches[2]; + } + } + + if( timeOut ){ + timer = setTimeout(getCallBack(1), timeOut); + } + url = url.replace(reg, '\x241' + queryField + '=' + callbackName); + + if (url.search(reg) < 0) { + url += (url.indexOf('?') < 0 ? '?' : '&') + queryField + '=' + callbackName; + } + baidu.sio._createScriptTag(scr, url, charset); + + /* + * 返回一个函数,用于立即(挂在window上)或者超时(挂在setTimeout中)时执行 + */ + function getCallBack(onTimeOut){ + /*global callbackName, callback, scr, options;*/ + return function(){ + try { + if( onTimeOut ){ + options.onfailure && options.onfailure(); + }else{ + callback.apply(window, arguments); + clearTimeout(timer); + } + window[callbackName] = null; + delete window[callbackName]; + } catch (exception) { + } finally { + baidu.sio._removeScriptTag(scr); + } + } + } +}; + +/** + * 通过请求一个图片的方式令服务器存储一条日志 + * @function + * @grammar baidu.sio.log(url) + * @param {string} url 要发送的地址. + * @author: int08h,leeight + */ +baidu.sio.log = function(url) { + var img = new Image(), + key = 'tangram_sio_log_' + Math.floor(Math.random() * + 2147483648).toString(36); + window[key] = img; + + img.onload = img.onerror = img.onabort = function() { + img.onload = img.onerror = img.onabort = null; + + window[key] = null; + img = null; + }; + img.src = url; +}; + + + +/* + * Tangram + * Copyright 2009 Baidu Inc. All rights reserved. + * + * path: baidu/json.js + * author: erik + * version: 1.1.0 + * date: 2009/12/02 + */ + + +/** + * 操作json对象的方法 + * @namespace baidu.json + */ +baidu.json = baidu.json || {}; +/* + * Tangram + * Copyright 2009 Baidu Inc. All rights reserved. + * + * path: baidu/json/parse.js + * author: erik, berg + * version: 1.2 + * date: 2009/11/23 + */ + + + +/** + * 将字符串解析成json对象。注:不会自动祛除空格 + * @name baidu.json.parse + * @function + * @grammar baidu.json.parse(data) + * @param {string} source 需要解析的字符串 + * @remark + * 该方法的实现与ecma-262第五版中规定的JSON.parse不同,暂时只支持传入一个参数。后续会进行功能丰富。 + * @meta standard + * @see baidu.json.stringify,baidu.json.decode + * + * @returns {JSON} 解析结果json对象 + */ +baidu.json.parse = function (data) { + //2010/12/09:更新至不使用原生parse,不检测用户输入是否正确 + return (new Function("return (" + data + ")"))(); +}; +/* + * Tangram + * Copyright 2009 Baidu Inc. All rights reserved. + * + * path: baidu/json/decode.js + * author: erik, cat + * version: 1.3.4 + * date: 2010/12/23 + */ + + + +/** + * 将字符串解析成json对象,为过时接口,今后会被baidu.json.parse代替 + * @name baidu.json.decode + * @function + * @grammar baidu.json.decode(source) + * @param {string} source 需要解析的字符串 + * @meta out + * @see baidu.json.encode,baidu.json.parse + * + * @returns {JSON} 解析结果json对象 + */ +baidu.json.decode = baidu.json.parse; +/* + * Tangram + * Copyright 2009 Baidu Inc. All rights reserved. + * + * path: baidu/json/stringify.js + * author: erik + * version: 1.1.0 + * date: 2010/01/11 + */ + + + +/** + * 将json对象序列化 + * @name baidu.json.stringify + * @function + * @grammar baidu.json.stringify(value) + * @param {JSON} value 需要序列化的json对象 + * @remark + * 该方法的实现与ecma-262第五版中规定的JSON.stringify不同,暂时只支持传入一个参数。后续会进行功能丰富。 + * @meta standard + * @see baidu.json.parse,baidu.json.encode + * + * @returns {string} 序列化后的字符串 + */ +baidu.json.stringify = (function () { + /** + * 字符串处理时需要转义的字符表 + * @private + */ + var escapeMap = { + "\b": '\\b', + "\t": '\\t', + "\n": '\\n', + "\f": '\\f', + "\r": '\\r', + '"' : '\\"', + "\\": '\\\\' + }; + + /** + * 字符串序列化 + * @private + */ + function encodeString(source) { + if (/["\\\x00-\x1f]/.test(source)) { + source = source.replace( + /["\\\x00-\x1f]/g, + function (match) { + var c = escapeMap[match]; + if (c) { + return c; + } + c = match.charCodeAt(); + return "\\u00" + + Math.floor(c / 16).toString(16) + + (c % 16).toString(16); + }); + } + return '"' + source + '"'; + } + + /** + * 数组序列化 + * @private + */ + function encodeArray(source) { + var result = ["["], + l = source.length, + preComma, i, item; + + for (i = 0; i < l; i++) { + item = source[i]; + + switch (typeof item) { + case "undefined": + case "function": + case "unknown": + break; + default: + if(preComma) { + result.push(','); + } + result.push(baidu.json.stringify(item)); + preComma = 1; + } + } + result.push("]"); + return result.join(""); + } + + /** + * 处理日期序列化时的补零 + * @private + */ + function pad(source) { + return source < 10 ? '0' + source : source; + } + + /** + * 日期序列化 + * @private + */ + function encodeDate(source){ + return '"' + source.getFullYear() + "-" + + pad(source.getMonth() + 1) + "-" + + pad(source.getDate()) + "T" + + pad(source.getHours()) + ":" + + pad(source.getMinutes()) + ":" + + pad(source.getSeconds()) + '"'; + } + + return function (value) { + switch (typeof value) { + case 'undefined': + return 'undefined'; + + case 'number': + return isFinite(value) ? String(value) : "null"; + + case 'string': + return encodeString(value); + + case 'boolean': + return String(value); + + default: + if (value === null) { + return 'null'; + } else if (value instanceof Array) { + return encodeArray(value); + } else if (value instanceof Date) { + return encodeDate(value); + } else { + var result = ['{'], + encode = baidu.json.stringify, + preComma, + item; + + for (var key in value) { + if (Object.prototype.hasOwnProperty.call(value, key)) { + item = value[key]; + switch (typeof item) { + case 'undefined': + case 'unknown': + case 'function': + break; + default: + if (preComma) { + result.push(','); + } + preComma = 1; + result.push(encode(key) + ':' + encode(item)); + } + } + } + result.push('}'); + return result.join(''); + } + } + }; +})(); +/* + * Tangram + * Copyright 2009 Baidu Inc. All rights reserved. + * + * path: baidu/json/encode.js + * author: erik, cat + * version: 1.3.4 + * date: 2010/12/23 + */ + + + +/** + * 将json对象序列化,为过时接口,今后会被baidu.json.stringify代替 + * @name baidu.json.encode + * @function + * @grammar baidu.json.encode(value) + * @param {JSON} value 需要序列化的json对象 + * @meta out + * @see baidu.json.decode,baidu.json.stringify + * + * @returns {string} 序列化后的字符串 + */ +baidu.json.encode = baidu.json.stringify; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/wordimage/wordimage.html b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/wordimage/wordimage.html new file mode 100644 index 000000000..6cf606741 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/wordimage/wordimage.html @@ -0,0 +1,111 @@ + + + + + + + + + +
        +
        + +
        +
        +
        +
        +
        + +
        + : +
        +
        +
        + + + + + + \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/dialogs/wordimage/wordimage.js b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/wordimage/wordimage.js new file mode 100644 index 000000000..98f3a2264 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/dialogs/wordimage/wordimage.js @@ -0,0 +1,157 @@ +/** + * Created by JetBrains PhpStorm. + * User: taoqili + * Date: 12-1-30 + * Time: 下午12:50 + * To change this template use File | Settings | File Templates. + */ + + + +var wordImage = {}; +//(function(){ +var g = baidu.g, + flashObj,flashContainer; + +wordImage.init = function(opt, callbacks) { + showLocalPath("localPath"); + //createCopyButton("clipboard","localPath"); + createFlashUploader(opt, callbacks); + addUploadListener(); + addOkListener(); +}; + +function hideFlash(){ + flashObj = null; + flashContainer.innerHTML = ""; +} +function addOkListener() { + dialog.onok = function() { + if (!imageUrls.length) return; + var urlPrefix = editor.getOpt('imageUrlPrefix'), + images = domUtils.getElementsByTagName(editor.document,"img"); + editor.fireEvent('saveScene'); + for (var i = 0,img; img = images[i++];) { + var src = img.getAttribute("word_img"); + if (!src) continue; + for (var j = 0,url; url = imageUrls[j++];) { + if (src.indexOf(url.original.replace(" ","")) != -1) { + img.src = urlPrefix + url.url; + img.setAttribute("_src", urlPrefix + url.url); //同时修改"_src"属性 + img.setAttribute("title",url.title); + domUtils.removeAttributes(img, ["word_img","style","width","height"]); + editor.fireEvent("selectionchange"); + break; + } + } + } + editor.fireEvent('saveScene'); + hideFlash(); + }; + dialog.oncancel = function(){ + hideFlash(); + } +} + +/** + * 绑定开始上传事件 + */ +function addUploadListener() { + g("upload").onclick = function () { + flashObj.upload(); + this.style.display = "none"; + }; +} + +function showLocalPath(id) { + //单张编辑 + var img = editor.selection.getRange().getClosedNode(); + var images = editor.execCommand('wordimage'); + if(images.length==1 || img && img.tagName == 'IMG'){ + g(id).value = images[0]; + return; + } + var path = images[0]; + var leftSlashIndex = path.lastIndexOf("/")||0, //不同版本的doc和浏览器都可能影响到这个符号,故直接判断两种 + rightSlashIndex = path.lastIndexOf("\\")||0, + separater = leftSlashIndex > rightSlashIndex ? "/":"\\" ; + + path = path.substring(0, path.lastIndexOf(separater)+1); + g(id).value = path; +} + +function createFlashUploader(opt, callbacks) { + //由于lang.flashI18n是静态属性,不可以直接进行修改,否则会影响到后续内容 + var i18n = utils.extend({},lang.flashI18n); + //处理图片资源地址的编码,补全等问题 + for(var i in i18n){ + if(!(i in {"lang":1,"uploadingTF":1,"imageTF":1,"textEncoding":1}) && i18n[i]){ + i18n[i] = encodeURIComponent(editor.options.langPath + editor.options.lang + "/images/" + i18n[i]); + } + } + opt = utils.extend(opt,i18n,false); + var option = { + createOptions:{ + id:'flash', + url:opt.flashUrl, + width:opt.width, + height:opt.height, + errorMessage:lang.flashError, + wmode:browser.safari ? 'transparent' : 'window', + ver:'10.0.0', + vars:opt, + container:opt.container + } + }; + + option = extendProperty(callbacks, option); + flashObj = new baidu.flash.imageUploader(option); + flashContainer = $G(opt.container); +} + +function extendProperty(fromObj, toObj) { + for (var i in fromObj) { + if (!toObj[i]) { + toObj[i] = fromObj[i]; + } + } + return toObj; +} + +//})(); + +function getPasteData(id) { + baidu.g("msg").innerHTML = lang.copySuccess + "
        "; + setTimeout(function() { + baidu.g("msg").innerHTML = ""; + }, 5000); + return baidu.g(id).value; +} + +function createCopyButton(id, dataFrom) { + baidu.swf.create({ + id:"copyFlash", + url:"fClipboard_ueditor.swf", + width:"58", + height:"25", + errorMessage:"", + bgColor:"#CBCBCB", + wmode:"transparent", + ver:"10.0.0", + vars:{ + tid:dataFrom + } + }, id + ); + + var clipboard = baidu.swf.getMovie("copyFlash"); + var clipinterval = setInterval(function() { + if (clipboard && clipboard.flashInit) { + clearInterval(clipinterval); + clipboard.setHandCursor(true); + clipboard.setContentFuncName("getPasteData"); + //clipboard.setMEFuncName("mouseEventHandler"); + } + }, 500); +} +createCopyButton("clipboard", "localPath"); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/config.json b/nezha-fronted/static/ueditor-1.4.3.3/jsp/config.json new file mode 100644 index 000000000..53b6c9770 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/config.json @@ -0,0 +1,94 @@ +/* 前后端通信相关的配置,注释只允许使用多行方式 */ +{ + /* 上传图片配置项 */ + "imageActionName": "uploadimage", /* 执行上传图片的action名称 */ + "imageFieldName": "upfile", /* 提交的图片表单名称 */ + "imageMaxSize": 2048000, /* 上传大小限制,单位B */ + "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */ + "imageCompressEnable": true, /* 是否压缩图片,默认是true */ + "imageCompressBorder": 1600, /* 图片压缩最长边限制 */ + "imageInsertAlign": "none", /* 插入的图片浮动方式 */ + "imageUrlPrefix": "", /* 图片访问路径前缀 */ + "imagePathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */ + /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */ + /* {time} 会替换成时间戳 */ + /* {yyyy} 会替换成四位年份 */ + /* {yy} 会替换成两位年份 */ + /* {mm} 会替换成两位月份 */ + /* {dd} 会替换成两位日期 */ + /* {hh} 会替换成两位小时 */ + /* {ii} 会替换成两位分钟 */ + /* {ss} 会替换成两位秒 */ + /* 非法字符 \ : * ? " < > | */ + /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */ + + /* 涂鸦图片上传配置项 */ + "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */ + "scrawlFieldName": "upfile", /* 提交的图片表单名称 */ + "scrawlPathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "scrawlMaxSize": 2048000, /* 上传大小限制,单位B */ + "scrawlUrlPrefix": "", /* 图片访问路径前缀 */ + "scrawlInsertAlign": "none", + + /* 截图工具上传 */ + "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */ + "snapscreenPathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "snapscreenUrlPrefix": "", /* 图片访问路径前缀 */ + "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */ + + /* 抓取远程图片配置 */ + "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"], + "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */ + "catcherFieldName": "source", /* 提交的图片列表表单名称 */ + "catcherPathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "catcherUrlPrefix": "", /* 图片访问路径前缀 */ + "catcherMaxSize": 2048000, /* 上传大小限制,单位B */ + "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */ + + /* 上传视频配置 */ + "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */ + "videoFieldName": "upfile", /* 提交的视频表单名称 */ + "videoPathFormat": "/ueditor/jsp/upload/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "videoUrlPrefix": "", /* 视频访问路径前缀 */ + "videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */ + "videoAllowFiles": [ + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */ + + /* 上传文件配置 */ + "fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */ + "fileFieldName": "upfile", /* 提交的文件表单名称 */ + "filePathFormat": "/ueditor/jsp/upload/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "fileUrlPrefix": "", /* 文件访问路径前缀 */ + "fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */ + "fileAllowFiles": [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ], /* 上传文件格式显示 */ + + /* 列出指定目录下的图片 */ + "imageManagerActionName": "listimage", /* 执行图片管理的action名称 */ + "imageManagerListPath": "/ueditor/jsp/upload/image/", /* 指定要列出图片的目录 */ + "imageManagerListSize": 20, /* 每次列出文件数量 */ + "imageManagerUrlPrefix": "", /* 图片访问路径前缀 */ + "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */ + "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */ + + /* 列出指定目录下的文件 */ + "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */ + "fileManagerListPath": "/ueditor/jsp/upload/file/", /* 指定要列出文件的目录 */ + "fileManagerUrlPrefix": "", /* 文件访问路径前缀 */ + "fileManagerListSize": 20, /* 每次列出文件数量 */ + "fileManagerAllowFiles": [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ] /* 列出的文件类型 */ + +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/controller.jsp b/nezha-fronted/static/ueditor-1.4.3.3/jsp/controller.jsp new file mode 100644 index 000000000..6a3ef2f19 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/controller.jsp @@ -0,0 +1,14 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + import="com.baidu.ueditor.ActionEnter" + pageEncoding="UTF-8"%> +<%@ page trimDirectiveWhitespaces="true" %> +<% + + request.setCharacterEncoding( "utf-8" ); + response.setHeader("Content-Type" , "text/html"); + + String rootPath = application.getRealPath( "/" ); + + out.write( new ActionEnter( request, rootPath ).exec() ); + +%> \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/lib/commons-codec-1.9.jar b/nezha-fronted/static/ueditor-1.4.3.3/jsp/lib/commons-codec-1.9.jar new file mode 100644 index 000000000..ef35f1c50 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/jsp/lib/commons-codec-1.9.jar differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/lib/commons-fileupload-1.3.1.jar b/nezha-fronted/static/ueditor-1.4.3.3/jsp/lib/commons-fileupload-1.3.1.jar new file mode 100644 index 000000000..af0cda226 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/jsp/lib/commons-fileupload-1.3.1.jar differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/lib/commons-io-2.4.jar b/nezha-fronted/static/ueditor-1.4.3.3/jsp/lib/commons-io-2.4.jar new file mode 100644 index 000000000..90035a4fe Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/jsp/lib/commons-io-2.4.jar differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/lib/json.jar b/nezha-fronted/static/ueditor-1.4.3.3/jsp/lib/json.jar new file mode 100644 index 000000000..ed0bc93a7 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/jsp/lib/json.jar differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/lib/ueditor-1.1.2.jar b/nezha-fronted/static/ueditor-1.4.3.3/jsp/lib/ueditor-1.1.2.jar new file mode 100644 index 000000000..4819fe011 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/jsp/lib/ueditor-1.1.2.jar differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/ActionEnter.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/ActionEnter.java new file mode 100644 index 000000000..33a3dc7b5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/ActionEnter.java @@ -0,0 +1,127 @@ +package com.baidu.ueditor; + +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import com.baidu.ueditor.define.ActionMap; +import com.baidu.ueditor.define.AppInfo; +import com.baidu.ueditor.define.BaseState; +import com.baidu.ueditor.define.State; +import com.baidu.ueditor.hunter.FileManager; +import com.baidu.ueditor.hunter.ImageHunter; +import com.baidu.ueditor.upload.Uploader; + +public class ActionEnter { + + private HttpServletRequest request = null; + + private String rootPath = null; + private String contextPath = null; + + private String actionType = null; + + private ConfigManager configManager = null; + + public ActionEnter ( HttpServletRequest request, String rootPath ) { + + this.request = request; + this.rootPath = rootPath; + this.actionType = request.getParameter( "action" ); + this.contextPath = request.getContextPath(); + this.configManager = ConfigManager.getInstance( this.rootPath, this.contextPath, request.getRequestURI() ); + + } + + public String exec () { + + String callbackName = this.request.getParameter("callback"); + + if ( callbackName != null ) { + + if ( !validCallbackName( callbackName ) ) { + return new BaseState( false, AppInfo.ILLEGAL ).toJSONString(); + } + + return callbackName+"("+this.invoke()+");"; + + } else { + return this.invoke(); + } + + } + + public String invoke() { + + if ( actionType == null || !ActionMap.mapping.containsKey( actionType ) ) { + return new BaseState( false, AppInfo.INVALID_ACTION ).toJSONString(); + } + + if ( this.configManager == null || !this.configManager.valid() ) { + return new BaseState( false, AppInfo.CONFIG_ERROR ).toJSONString(); + } + + State state = null; + + int actionCode = ActionMap.getType( this.actionType ); + + Map conf = null; + + switch ( actionCode ) { + + case ActionMap.CONFIG: + return this.configManager.getAllConfig().toString(); + + case ActionMap.UPLOAD_IMAGE: + case ActionMap.UPLOAD_SCRAWL: + case ActionMap.UPLOAD_VIDEO: + case ActionMap.UPLOAD_FILE: + conf = this.configManager.getConfig( actionCode ); + state = new Uploader( request, conf ).doExec(); + break; + + case ActionMap.CATCH_IMAGE: + conf = configManager.getConfig( actionCode ); + String[] list = this.request.getParameterValues( (String)conf.get( "fieldName" ) ); + state = new ImageHunter( conf ).capture( list ); + break; + + case ActionMap.LIST_IMAGE: + case ActionMap.LIST_FILE: + conf = configManager.getConfig( actionCode ); + int start = this.getStartIndex(); + state = new FileManager( conf ).listFile( start ); + break; + + } + + return state.toJSONString(); + + } + + public int getStartIndex () { + + String start = this.request.getParameter( "start" ); + + try { + return Integer.parseInt( start ); + } catch ( Exception e ) { + return 0; + } + + } + + /** + * callback参数验证 + */ + public boolean validCallbackName ( String name ) { + + if ( name.matches( "^[a-zA-Z_]+[\\w0-9_]*$" ) ) { + return true; + } + + return false; + + } + +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/ConfigManager.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/ConfigManager.java new file mode 100644 index 000000000..5551ee909 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/ConfigManager.java @@ -0,0 +1,222 @@ +package com.baidu.ueditor; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONObject; + +import com.baidu.ueditor.define.ActionMap; + +/** + * 配置管理器 + * @author hancong03@baidu.com + * + */ +public final class ConfigManager { + + private final String rootPath; + private final String originalPath; + private final String contextPath; + private static final String configFileName = "config.json"; + private String parentPath = null; + private JSONObject jsonConfig = null; + // 涂鸦上传filename定义 + private final static String SCRAWL_FILE_NAME = "scrawl"; + // 远程图片抓取filename定义 + private final static String REMOTE_FILE_NAME = "remote"; + + /* + * 通过一个给定的路径构建一个配置管理器, 该管理器要求地址路径所在目录下必须存在config.properties文件 + */ + private ConfigManager ( String rootPath, String contextPath, String uri ) throws FileNotFoundException, IOException { + + rootPath = rootPath.replace( "\\", "/" ); + + this.rootPath = rootPath; + this.contextPath = contextPath; + + if ( contextPath.length() > 0 ) { + this.originalPath = this.rootPath + uri.substring( contextPath.length() ); + } else { + this.originalPath = this.rootPath + uri; + } + + this.initEnv(); + + } + + /** + * 配置管理器构造工厂 + * @param rootPath 服务器根路径 + * @param contextPath 服务器所在项目路径 + * @param uri 当前访问的uri + * @return 配置管理器实例或者null + */ + public static ConfigManager getInstance ( String rootPath, String contextPath, String uri ) { + + try { + return new ConfigManager(rootPath, contextPath, uri); + } catch ( Exception e ) { + return null; + } + + } + + // 验证配置文件加载是否正确 + public boolean valid () { + return this.jsonConfig != null; + } + + public JSONObject getAllConfig () { + + return this.jsonConfig; + + } + + public Map getConfig ( int type ) { + + Map conf = new HashMap(); + String savePath = null; + + switch ( type ) { + + case ActionMap.UPLOAD_FILE: + conf.put( "isBase64", "false" ); + conf.put( "maxSize", this.jsonConfig.getLong( "fileMaxSize" ) ); + conf.put( "allowFiles", this.getArray( "fileAllowFiles" ) ); + conf.put( "fieldName", this.jsonConfig.getString( "fileFieldName" ) ); + savePath = this.jsonConfig.getString( "filePathFormat" ); + break; + + case ActionMap.UPLOAD_IMAGE: + conf.put( "isBase64", "false" ); + conf.put( "maxSize", this.jsonConfig.getLong( "imageMaxSize" ) ); + conf.put( "allowFiles", this.getArray( "imageAllowFiles" ) ); + conf.put( "fieldName", this.jsonConfig.getString( "imageFieldName" ) ); + savePath = this.jsonConfig.getString( "imagePathFormat" ); + break; + + case ActionMap.UPLOAD_VIDEO: + conf.put( "maxSize", this.jsonConfig.getLong( "videoMaxSize" ) ); + conf.put( "allowFiles", this.getArray( "videoAllowFiles" ) ); + conf.put( "fieldName", this.jsonConfig.getString( "videoFieldName" ) ); + savePath = this.jsonConfig.getString( "videoPathFormat" ); + break; + + case ActionMap.UPLOAD_SCRAWL: + conf.put( "filename", ConfigManager.SCRAWL_FILE_NAME ); + conf.put( "maxSize", this.jsonConfig.getLong( "scrawlMaxSize" ) ); + conf.put( "fieldName", this.jsonConfig.getString( "scrawlFieldName" ) ); + conf.put( "isBase64", "true" ); + savePath = this.jsonConfig.getString( "scrawlPathFormat" ); + break; + + case ActionMap.CATCH_IMAGE: + conf.put( "filename", ConfigManager.REMOTE_FILE_NAME ); + conf.put( "filter", this.getArray( "catcherLocalDomain" ) ); + conf.put( "maxSize", this.jsonConfig.getLong( "catcherMaxSize" ) ); + conf.put( "allowFiles", this.getArray( "catcherAllowFiles" ) ); + conf.put( "fieldName", this.jsonConfig.getString( "catcherFieldName" ) + "[]" ); + savePath = this.jsonConfig.getString( "catcherPathFormat" ); + break; + + case ActionMap.LIST_IMAGE: + conf.put( "allowFiles", this.getArray( "imageManagerAllowFiles" ) ); + conf.put( "dir", this.jsonConfig.getString( "imageManagerListPath" ) ); + conf.put( "count", this.jsonConfig.getInt( "imageManagerListSize" ) ); + break; + + case ActionMap.LIST_FILE: + conf.put( "allowFiles", this.getArray( "fileManagerAllowFiles" ) ); + conf.put( "dir", this.jsonConfig.getString( "fileManagerListPath" ) ); + conf.put( "count", this.jsonConfig.getInt( "fileManagerListSize" ) ); + break; + + } + + conf.put( "savePath", savePath ); + conf.put( "rootPath", this.rootPath ); + + return conf; + + } + + private void initEnv () throws FileNotFoundException, IOException { + + File file = new File( this.originalPath ); + + if ( !file.isAbsolute() ) { + file = new File( file.getAbsolutePath() ); + } + + this.parentPath = file.getParent(); + + String configContent = this.readFile( this.getConfigPath() ); + + try{ + JSONObject jsonConfig = new JSONObject( configContent ); + this.jsonConfig = jsonConfig; + } catch ( Exception e ) { + this.jsonConfig = null; + } + + } + + private String getConfigPath () { + return this.parentPath + File.separator + ConfigManager.configFileName; + } + + private String[] getArray ( String key ) { + + JSONArray jsonArray = this.jsonConfig.getJSONArray( key ); + String[] result = new String[ jsonArray.length() ]; + + for ( int i = 0, len = jsonArray.length(); i < len; i++ ) { + result[i] = jsonArray.getString( i ); + } + + return result; + + } + + private String readFile ( String path ) throws IOException { + + StringBuilder builder = new StringBuilder(); + + try { + + InputStreamReader reader = new InputStreamReader( new FileInputStream( path ), "UTF-8" ); + BufferedReader bfReader = new BufferedReader( reader ); + + String tmpContent = null; + + while ( ( tmpContent = bfReader.readLine() ) != null ) { + builder.append( tmpContent ); + } + + bfReader.close(); + + } catch ( UnsupportedEncodingException e ) { + // 忽略 + } + + return this.filter( builder.toString() ); + + } + + // 过滤输入字符串, 剔除多行注释以及替换掉反斜杠 + private String filter ( String input ) { + + return input.replaceAll( "/\\*[\\s\\S]*?\\*/", "" ); + + } + +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/Encoder.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/Encoder.java new file mode 100644 index 000000000..00bce19b3 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/Encoder.java @@ -0,0 +1,24 @@ +package com.baidu.ueditor; + +public class Encoder { + + public static String toUnicode ( String input ) { + + StringBuilder builder = new StringBuilder(); + char[] chars = input.toCharArray(); + + for ( char ch : chars ) { + + if ( ch < 256 ) { + builder.append( ch ); + } else { + builder.append( "\\u" + Integer.toHexString( ch& 0xffff ) ); + } + + } + + return builder.toString(); + + } + +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/PathFormat.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/PathFormat.java new file mode 100644 index 000000000..080ea48fa --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/PathFormat.java @@ -0,0 +1,157 @@ +package com.baidu.ueditor; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PathFormat { + + private static final String TIME = "time"; + private static final String FULL_YEAR = "yyyy"; + private static final String YEAR = "yy"; + private static final String MONTH = "mm"; + private static final String DAY = "dd"; + private static final String HOUR = "hh"; + private static final String MINUTE = "ii"; + private static final String SECOND = "ss"; + private static final String RAND = "rand"; + + private static Date currentDate = null; + + public static String parse ( String input ) { + + Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE ); + Matcher matcher = pattern.matcher(input); + + PathFormat.currentDate = new Date(); + + StringBuffer sb = new StringBuffer(); + + while ( matcher.find() ) { + + matcher.appendReplacement(sb, PathFormat.getString( matcher.group( 1 ) ) ); + + } + + matcher.appendTail(sb); + + return sb.toString(); + } + + /** + * 格式化路径, 把windows路径替换成标准路径 + * @param input 待格式化的路径 + * @return 格式化后的路径 + */ + public static String format ( String input ) { + + return input.replace( "\\", "/" ); + + } + + public static String parse ( String input, String filename ) { + + Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE ); + Matcher matcher = pattern.matcher(input); + String matchStr = null; + + PathFormat.currentDate = new Date(); + + StringBuffer sb = new StringBuffer(); + + while ( matcher.find() ) { + + matchStr = matcher.group( 1 ); + if ( matchStr.indexOf( "filename" ) != -1 ) { + filename = filename.replace( "$", "\\$" ).replaceAll( "[\\/:*?\"<>|]", "" ); + matcher.appendReplacement(sb, filename ); + } else { + matcher.appendReplacement(sb, PathFormat.getString( matchStr ) ); + } + + } + + matcher.appendTail(sb); + + return sb.toString(); + } + + private static String getString ( String pattern ) { + + pattern = pattern.toLowerCase(); + + // time 处理 + if ( pattern.indexOf( PathFormat.TIME ) != -1 ) { + return PathFormat.getTimestamp(); + } else if ( pattern.indexOf( PathFormat.FULL_YEAR ) != -1 ) { + return PathFormat.getFullYear(); + } else if ( pattern.indexOf( PathFormat.YEAR ) != -1 ) { + return PathFormat.getYear(); + } else if ( pattern.indexOf( PathFormat.MONTH ) != -1 ) { + return PathFormat.getMonth(); + } else if ( pattern.indexOf( PathFormat.DAY ) != -1 ) { + return PathFormat.getDay(); + } else if ( pattern.indexOf( PathFormat.HOUR ) != -1 ) { + return PathFormat.getHour(); + } else if ( pattern.indexOf( PathFormat.MINUTE ) != -1 ) { + return PathFormat.getMinute(); + } else if ( pattern.indexOf( PathFormat.SECOND ) != -1 ) { + return PathFormat.getSecond(); + } else if ( pattern.indexOf( PathFormat.RAND ) != -1 ) { + return PathFormat.getRandom( pattern ); + } + + return pattern; + + } + + private static String getTimestamp () { + return System.currentTimeMillis() + ""; + } + + private static String getFullYear () { + return new SimpleDateFormat( "yyyy" ).format( PathFormat.currentDate ); + } + + private static String getYear () { + return new SimpleDateFormat( "yy" ).format( PathFormat.currentDate ); + } + + private static String getMonth () { + return new SimpleDateFormat( "MM" ).format( PathFormat.currentDate ); + } + + private static String getDay () { + return new SimpleDateFormat( "dd" ).format( PathFormat.currentDate ); + } + + private static String getHour () { + return new SimpleDateFormat( "HH" ).format( PathFormat.currentDate ); + } + + private static String getMinute () { + return new SimpleDateFormat( "mm" ).format( PathFormat.currentDate ); + } + + private static String getSecond () { + return new SimpleDateFormat( "ss" ).format( PathFormat.currentDate ); + } + + private static String getRandom ( String pattern ) { + + int length = 0; + pattern = pattern.split( ":" )[ 1 ].trim(); + + length = Integer.parseInt( pattern ); + + return ( Math.random() + "" ).replace( ".", "" ).substring( 0, length ); + + } + + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/ActionMap.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/ActionMap.java new file mode 100644 index 000000000..88f4f3248 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/ActionMap.java @@ -0,0 +1,42 @@ +package com.baidu.ueditor.define; + +import java.util.Map; +import java.util.HashMap; + +/** + * 定义请求action类型 + * @author hancong03@baidu.com + * + */ +@SuppressWarnings("serial") +public final class ActionMap { + + public static final Map mapping; + // 获取配置请求 + public static final int CONFIG = 0; + public static final int UPLOAD_IMAGE = 1; + public static final int UPLOAD_SCRAWL = 2; + public static final int UPLOAD_VIDEO = 3; + public static final int UPLOAD_FILE = 4; + public static final int CATCH_IMAGE = 5; + public static final int LIST_FILE = 6; + public static final int LIST_IMAGE = 7; + + static { + mapping = new HashMap(){{ + put( "config", ActionMap.CONFIG ); + put( "uploadimage", ActionMap.UPLOAD_IMAGE ); + put( "uploadscrawl", ActionMap.UPLOAD_SCRAWL ); + put( "uploadvideo", ActionMap.UPLOAD_VIDEO ); + put( "uploadfile", ActionMap.UPLOAD_FILE ); + put( "catchimage", ActionMap.CATCH_IMAGE ); + put( "listfile", ActionMap.LIST_FILE ); + put( "listimage", ActionMap.LIST_IMAGE ); + }}; + } + + public static int getType ( String key ) { + return ActionMap.mapping.get( key ); + } + +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/ActionState.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/ActionState.java new file mode 100644 index 000000000..b0fad34fd --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/ActionState.java @@ -0,0 +1,5 @@ +package com.baidu.ueditor.define; + +public enum ActionState { + UNKNOW_ERROR +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/AppInfo.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/AppInfo.java new file mode 100644 index 000000000..b869f2aad --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/AppInfo.java @@ -0,0 +1,77 @@ +package com.baidu.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +public final class AppInfo { + + public static final int SUCCESS = 0; + public static final int MAX_SIZE = 1; + public static final int PERMISSION_DENIED = 2; + public static final int FAILED_CREATE_FILE = 3; + public static final int IO_ERROR = 4; + public static final int NOT_MULTIPART_CONTENT = 5; + public static final int PARSE_REQUEST_ERROR = 6; + public static final int NOTFOUND_UPLOAD_DATA = 7; + public static final int NOT_ALLOW_FILE_TYPE = 8; + + public static final int INVALID_ACTION = 101; + public static final int CONFIG_ERROR = 102; + + public static final int PREVENT_HOST = 201; + public static final int CONNECTION_ERROR = 202; + public static final int REMOTE_FAIL = 203; + + public static final int NOT_DIRECTORY = 301; + public static final int NOT_EXIST = 302; + + public static final int ILLEGAL = 401; + + public static Map info = new HashMap(){{ + + put( AppInfo.SUCCESS, "SUCCESS" ); + + // 无效的Action + put( AppInfo.INVALID_ACTION, "\u65E0\u6548\u7684Action" ); + // 配置文件初始化失败 + put( AppInfo.CONFIG_ERROR, "\u914D\u7F6E\u6587\u4EF6\u521D\u59CB\u5316\u5931\u8D25" ); + // 抓取远程图片失败 + put( AppInfo.REMOTE_FAIL, "\u6293\u53D6\u8FDC\u7A0B\u56FE\u7247\u5931\u8D25" ); + + // 被阻止的远程主机 + put( AppInfo.PREVENT_HOST, "\u88AB\u963B\u6B62\u7684\u8FDC\u7A0B\u4E3B\u673A" ); + // 远程连接出错 + put( AppInfo.CONNECTION_ERROR, "\u8FDC\u7A0B\u8FDE\u63A5\u51FA\u9519" ); + + // "文件大小超出限制" + put( AppInfo.MAX_SIZE, "\u6587\u4ef6\u5927\u5c0f\u8d85\u51fa\u9650\u5236" ); + // 权限不足, 多指写权限 + put( AppInfo.PERMISSION_DENIED, "\u6743\u9650\u4E0D\u8DB3" ); + // 创建文件失败 + put( AppInfo.FAILED_CREATE_FILE, "\u521B\u5EFA\u6587\u4EF6\u5931\u8D25" ); + // IO错误 + put( AppInfo.IO_ERROR, "IO\u9519\u8BEF" ); + // 上传表单不是multipart/form-data类型 + put( AppInfo.NOT_MULTIPART_CONTENT, "\u4E0A\u4F20\u8868\u5355\u4E0D\u662Fmultipart/form-data\u7C7B\u578B" ); + // 解析上传表单错误 + put( AppInfo.PARSE_REQUEST_ERROR, "\u89E3\u6790\u4E0A\u4F20\u8868\u5355\u9519\u8BEF" ); + // 未找到上传数据 + put( AppInfo.NOTFOUND_UPLOAD_DATA, "\u672A\u627E\u5230\u4E0A\u4F20\u6570\u636E" ); + // 不允许的文件类型 + put( AppInfo.NOT_ALLOW_FILE_TYPE, "\u4E0D\u5141\u8BB8\u7684\u6587\u4EF6\u7C7B\u578B" ); + + // 指定路径不是目录 + put( AppInfo.NOT_DIRECTORY, "\u6307\u5B9A\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55" ); + // 指定路径并不存在 + put( AppInfo.NOT_EXIST, "\u6307\u5B9A\u8DEF\u5F84\u5E76\u4E0D\u5B58\u5728" ); + + // callback参数名不合法 + put( AppInfo.ILLEGAL, "Callback\u53C2\u6570\u540D\u4E0D\u5408\u6CD5" ); + + }}; + + public static String getStateInfo ( int key ) { + return AppInfo.info.get( key ); + } + +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/BaseState.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/BaseState.java new file mode 100644 index 000000000..dcc881b12 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/BaseState.java @@ -0,0 +1,90 @@ +package com.baidu.ueditor.define; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import com.baidu.ueditor.Encoder; + +public class BaseState implements State { + + private boolean state = false; + private String info = null; + + private Map infoMap = new HashMap(); + + public BaseState () { + this.state = true; + } + + public BaseState ( boolean state ) { + this.setState( state ); + } + + public BaseState ( boolean state, String info ) { + this.setState( state ); + this.info = info; + } + + public BaseState ( boolean state, int infoCode ) { + this.setState( state ); + this.info = AppInfo.getStateInfo( infoCode ); + } + + public boolean isSuccess () { + return this.state; + } + + public void setState ( boolean state ) { + this.state = state; + } + + public void setInfo ( String info ) { + this.info = info; + } + + public void setInfo ( int infoCode ) { + this.info = AppInfo.getStateInfo( infoCode ); + } + + @Override + public String toJSONString() { + return this.toString(); + } + + public String toString () { + + String key = null; + String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info; + + StringBuilder builder = new StringBuilder(); + + builder.append( "{\"state\": \"" + stateVal + "\"" ); + + Iterator iterator = this.infoMap.keySet().iterator(); + + while ( iterator.hasNext() ) { + + key = iterator.next(); + + builder.append( ",\"" + key + "\": \"" + this.infoMap.get(key) + "\"" ); + + } + + builder.append( "}" ); + + return Encoder.toUnicode( builder.toString() ); + + } + + @Override + public void putInfo(String name, String val) { + this.infoMap.put(name, val); + } + + @Override + public void putInfo(String name, long val) { + this.putInfo(name, val+""); + } + +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/FileType.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/FileType.java new file mode 100644 index 000000000..9195b85b3 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/FileType.java @@ -0,0 +1,31 @@ +package com.baidu.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +public class FileType { + + public static final String JPG = "JPG"; + + private static final Map types = new HashMap(){{ + + put( FileType.JPG, ".jpg" ); + + }}; + + public static String getSuffix ( String key ) { + return FileType.types.get( key ); + } + + /** + * 根据给定的文件名,获取其后缀信息 + * @param filename + * @return + */ + public static String getSuffixByFilename ( String filename ) { + + return filename.substring( filename.lastIndexOf( "." ) ).toLowerCase(); + + } + +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/MIMEType.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/MIMEType.java new file mode 100644 index 000000000..77c6cddf1 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/MIMEType.java @@ -0,0 +1,20 @@ +package com.baidu.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +public class MIMEType { + + public static final Map types = new HashMap(){{ + put( "image/gif", ".gif" ); + put( "image/jpeg", ".jpg" ); + put( "image/jpg", ".jpg" ); + put( "image/png", ".png" ); + put( "image/bmp", ".bmp" ); + }}; + + public static String getSuffix ( String mime ) { + return MIMEType.types.get( mime ); + } + +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/MultiState.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/MultiState.java new file mode 100644 index 000000000..26caefb71 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/MultiState.java @@ -0,0 +1,112 @@ +package com.baidu.ueditor.define; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import com.baidu.ueditor.Encoder; + +/** + * 多状态集合状态 + * 其包含了多个状态的集合, 其本身自己也是一个状态 + * @author hancong03@baidu.com + * + */ +public class MultiState implements State { + + private boolean state = false; + private String info = null; + private Map intMap = new HashMap(); + private Map infoMap = new HashMap(); + private List stateList = new ArrayList(); + + public MultiState ( boolean state ) { + this.state = state; + } + + public MultiState ( boolean state, String info ) { + this.state = state; + this.info = info; + } + + public MultiState ( boolean state, int infoKey ) { + this.state = state; + this.info = AppInfo.getStateInfo( infoKey ); + } + + @Override + public boolean isSuccess() { + return this.state; + } + + public void addState ( State state ) { + stateList.add( state.toJSONString() ); + } + + /** + * 该方法调用无效果 + */ + @Override + public void putInfo(String name, String val) { + this.infoMap.put(name, val); + } + + @Override + public String toJSONString() { + + String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info; + + StringBuilder builder = new StringBuilder(); + + builder.append( "{\"state\": \"" + stateVal + "\"" ); + + // 数字转换 + Iterator iterator = this.intMap.keySet().iterator(); + + while ( iterator.hasNext() ) { + + stateVal = iterator.next(); + + builder.append( ",\""+ stateVal +"\": " + this.intMap.get( stateVal ) ); + + } + + iterator = this.infoMap.keySet().iterator(); + + while ( iterator.hasNext() ) { + + stateVal = iterator.next(); + + builder.append( ",\""+ stateVal +"\": \"" + this.infoMap.get( stateVal ) + "\"" ); + + } + + builder.append( ", list: [" ); + + + iterator = this.stateList.iterator(); + + while ( iterator.hasNext() ) { + + builder.append( iterator.next() + "," ); + + } + + if ( this.stateList.size() > 0 ) { + builder.deleteCharAt( builder.length() - 1 ); + } + + builder.append( " ]}" ); + + return Encoder.toUnicode( builder.toString() ); + + } + + @Override + public void putInfo(String name, long val) { + this.intMap.put( name, val ); + } + +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/State.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/State.java new file mode 100644 index 000000000..8f2227490 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/define/State.java @@ -0,0 +1,18 @@ +package com.baidu.ueditor.define; + +/** + * 处理状态接口 + * @author hancong03@baidu.com + * + */ +public interface State { + + public boolean isSuccess (); + + public void putInfo( String name, String val ); + + public void putInfo ( String name, long val ); + + public String toJSONString (); + +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/hunter/FileManager.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/hunter/FileManager.java new file mode 100644 index 000000000..5a8c1a053 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/hunter/FileManager.java @@ -0,0 +1,112 @@ +package com.baidu.ueditor.hunter; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; + +import org.apache.commons.io.FileUtils; + +import com.baidu.ueditor.PathFormat; +import com.baidu.ueditor.define.AppInfo; +import com.baidu.ueditor.define.BaseState; +import com.baidu.ueditor.define.MultiState; +import com.baidu.ueditor.define.State; + +public class FileManager { + + private String dir = null; + private String rootPath = null; + private String[] allowFiles = null; + private int count = 0; + + public FileManager ( Map conf ) { + + this.rootPath = (String)conf.get( "rootPath" ); + this.dir = this.rootPath + (String)conf.get( "dir" ); + this.allowFiles = this.getAllowFiles( conf.get("allowFiles") ); + this.count = (Integer)conf.get( "count" ); + + } + + public State listFile ( int index ) { + + File dir = new File( this.dir ); + State state = null; + + if ( !dir.exists() ) { + return new BaseState( false, AppInfo.NOT_EXIST ); + } + + if ( !dir.isDirectory() ) { + return new BaseState( false, AppInfo.NOT_DIRECTORY ); + } + + Collection list = FileUtils.listFiles( dir, this.allowFiles, true ); + + if ( index < 0 || index > list.size() ) { + state = new MultiState( true ); + } else { + Object[] fileList = Arrays.copyOfRange( list.toArray(), index, index + this.count ); + state = this.getState( fileList ); + } + + state.putInfo( "start", index ); + state.putInfo( "total", list.size() ); + + return state; + + } + + private State getState ( Object[] files ) { + + MultiState state = new MultiState( true ); + BaseState fileState = null; + + File file = null; + + for ( Object obj : files ) { + if ( obj == null ) { + break; + } + file = (File)obj; + fileState = new BaseState( true ); + fileState.putInfo( "url", PathFormat.format( this.getPath( file ) ) ); + state.addState( fileState ); + } + + return state; + + } + + private String getPath ( File file ) { + + String path = file.getAbsolutePath(); + + return path.replace( this.rootPath, "/" ); + + } + + private String[] getAllowFiles ( Object fileExt ) { + + String[] exts = null; + String ext = null; + + if ( fileExt == null ) { + return new String[ 0 ]; + } + + exts = (String[])fileExt; + + for ( int i = 0, len = exts.length; i < len; i++ ) { + + ext = exts[ i ]; + exts[ i ] = ext.replace( ".", "" ); + + } + + return exts; + + } + +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/hunter/ImageHunter.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/hunter/ImageHunter.java new file mode 100644 index 000000000..265bfed49 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/hunter/ImageHunter.java @@ -0,0 +1,144 @@ +package com.baidu.ueditor.hunter; + +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import com.baidu.ueditor.PathFormat; +import com.baidu.ueditor.define.AppInfo; +import com.baidu.ueditor.define.BaseState; +import com.baidu.ueditor.define.MIMEType; +import com.baidu.ueditor.define.MultiState; +import com.baidu.ueditor.define.State; +import com.baidu.ueditor.upload.StorageManager; + +/** + * 图片抓取器 + * @author hancong03@baidu.com + * + */ +public class ImageHunter { + + private String filename = null; + private String savePath = null; + private String rootPath = null; + private List allowTypes = null; + private long maxSize = -1; + + private List filters = null; + + public ImageHunter ( Map conf ) { + + this.filename = (String)conf.get( "filename" ); + this.savePath = (String)conf.get( "savePath" ); + this.rootPath = (String)conf.get( "rootPath" ); + this.maxSize = (Long)conf.get( "maxSize" ); + this.allowTypes = Arrays.asList( (String[])conf.get( "allowFiles" ) ); + this.filters = Arrays.asList( (String[])conf.get( "filter" ) ); + + } + + public State capture ( String[] list ) { + + MultiState state = new MultiState( true ); + + for ( String source : list ) { + state.addState( captureRemoteData( source ) ); + } + + return state; + + } + + public State captureRemoteData ( String urlStr ) { + + HttpURLConnection connection = null; + URL url = null; + String suffix = null; + + try { + url = new URL( urlStr ); + + if ( !validHost( url.getHost() ) ) { + return new BaseState( false, AppInfo.PREVENT_HOST ); + } + + connection = (HttpURLConnection) url.openConnection(); + + connection.setInstanceFollowRedirects( true ); + connection.setUseCaches( true ); + + if ( !validContentState( connection.getResponseCode() ) ) { + return new BaseState( false, AppInfo.CONNECTION_ERROR ); + } + + suffix = MIMEType.getSuffix( connection.getContentType() ); + + if ( !validFileType( suffix ) ) { + return new BaseState( false, AppInfo.NOT_ALLOW_FILE_TYPE ); + } + + if ( !validFileSize( connection.getContentLength() ) ) { + return new BaseState( false, AppInfo.MAX_SIZE ); + } + + String savePath = this.getPath( this.savePath, this.filename, suffix ); + String physicalPath = this.rootPath + savePath; + + State state = StorageManager.saveFileByInputStream( connection.getInputStream(), physicalPath ); + + if ( state.isSuccess() ) { + state.putInfo( "url", PathFormat.format( savePath ) ); + state.putInfo( "source", urlStr ); + } + + return state; + + } catch ( Exception e ) { + return new BaseState( false, AppInfo.REMOTE_FAIL ); + } + + } + + private String getPath ( String savePath, String filename, String suffix ) { + + return PathFormat.parse( savePath + suffix, filename ); + + } + + private boolean validHost ( String hostname ) { + try { + InetAddress ip = InetAddress.getByName(hostname); + + if (ip.isSiteLocalAddress()) { + return false; + } + } catch (UnknownHostException e) { + return false; + } + + return !filters.contains( hostname ); + + } + + private boolean validContentState ( int code ) { + + return HttpURLConnection.HTTP_OK == code; + + } + + private boolean validFileType ( String type ) { + + return this.allowTypes.contains( type ); + + } + + private boolean validFileSize ( int size ) { + return size < this.maxSize; + } + +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/upload/Base64Uploader.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/upload/Base64Uploader.java new file mode 100644 index 000000000..2f81076ae --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/upload/Base64Uploader.java @@ -0,0 +1,52 @@ +package com.baidu.ueditor.upload; + +import com.baidu.ueditor.PathFormat; +import com.baidu.ueditor.define.AppInfo; +import com.baidu.ueditor.define.BaseState; +import com.baidu.ueditor.define.FileType; +import com.baidu.ueditor.define.State; + +import java.util.Map; + +import org.apache.commons.codec.binary.Base64; + +public final class Base64Uploader { + + public static State save(String content, Map conf) { + + byte[] data = decode(content); + + long maxSize = ((Long) conf.get("maxSize")).longValue(); + + if (!validSize(data, maxSize)) { + return new BaseState(false, AppInfo.MAX_SIZE); + } + + String suffix = FileType.getSuffix("JPG"); + + String savePath = PathFormat.parse((String) conf.get("savePath"), + (String) conf.get("filename")); + + savePath = savePath + suffix; + String physicalPath = (String) conf.get("rootPath") + savePath; + + State storageState = StorageManager.saveBinaryFile(data, physicalPath); + + if (storageState.isSuccess()) { + storageState.putInfo("url", PathFormat.format(savePath)); + storageState.putInfo("type", suffix); + storageState.putInfo("original", ""); + } + + return storageState; + } + + private static byte[] decode(String content) { + return Base64.decodeBase64(content); + } + + private static boolean validSize(byte[] data, long length) { + return data.length <= length; + } + +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/upload/BinaryUploader.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/upload/BinaryUploader.java new file mode 100644 index 000000000..c69f9ddd7 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/upload/BinaryUploader.java @@ -0,0 +1,98 @@ +package com.baidu.ueditor.upload; + +import com.baidu.ueditor.PathFormat; +import com.baidu.ueditor.define.AppInfo; +import com.baidu.ueditor.define.BaseState; +import com.baidu.ueditor.define.FileType; +import com.baidu.ueditor.define.State; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.fileupload.FileItemIterator; +import org.apache.commons.fileupload.FileItemStream; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; + +public class BinaryUploader { + + public static final State save(HttpServletRequest request, + Map conf) { + FileItemStream fileStream = null; + boolean isAjaxUpload = request.getHeader( "X_Requested_With" ) != null; + + if (!ServletFileUpload.isMultipartContent(request)) { + return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT); + } + + ServletFileUpload upload = new ServletFileUpload( + new DiskFileItemFactory()); + + if ( isAjaxUpload ) { + upload.setHeaderEncoding( "UTF-8" ); + } + + try { + FileItemIterator iterator = upload.getItemIterator(request); + + while (iterator.hasNext()) { + fileStream = iterator.next(); + + if (!fileStream.isFormField()) + break; + fileStream = null; + } + + if (fileStream == null) { + return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA); + } + + String savePath = (String) conf.get("savePath"); + String originFileName = fileStream.getName(); + String suffix = FileType.getSuffixByFilename(originFileName); + + originFileName = originFileName.substring(0, + originFileName.length() - suffix.length()); + savePath = savePath + suffix; + + long maxSize = ((Long) conf.get("maxSize")).longValue(); + + if (!validType(suffix, (String[]) conf.get("allowFiles"))) { + return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE); + } + + savePath = PathFormat.parse(savePath, originFileName); + + String physicalPath = (String) conf.get("rootPath") + savePath; + + InputStream is = fileStream.openStream(); + State storageState = StorageManager.saveFileByInputStream(is, + physicalPath, maxSize); + is.close(); + + if (storageState.isSuccess()) { + storageState.putInfo("url", PathFormat.format(savePath)); + storageState.putInfo("type", suffix); + storageState.putInfo("original", originFileName + suffix); + } + + return storageState; + } catch (FileUploadException e) { + return new BaseState(false, AppInfo.PARSE_REQUEST_ERROR); + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + } + + private static boolean validType(String type, String[] allowTypes) { + List list = Arrays.asList(allowTypes); + + return list.contains(type); + } +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/upload/StorageManager.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/upload/StorageManager.java new file mode 100644 index 000000000..33911c648 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/upload/StorageManager.java @@ -0,0 +1,155 @@ +package com.baidu.ueditor.upload; + +import com.baidu.ueditor.define.AppInfo; +import com.baidu.ueditor.define.BaseState; +import com.baidu.ueditor.define.State; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.FileUtils; + +public class StorageManager { + public static final int BUFFER_SIZE = 8192; + + public StorageManager() { + } + + public static State saveBinaryFile(byte[] data, String path) { + File file = new File(path); + + State state = valid(file); + + if (!state.isSuccess()) { + return state; + } + + try { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(file)); + bos.write(data); + bos.flush(); + bos.close(); + } catch (IOException ioe) { + return new BaseState(false, AppInfo.IO_ERROR); + } + + state = new BaseState(true, file.getAbsolutePath()); + state.putInfo( "size", data.length ); + state.putInfo( "title", file.getName() ); + return state; + } + + public static State saveFileByInputStream(InputStream is, String path, + long maxSize) { + State state = null; + + File tmpFile = getTmpFile(); + + byte[] dataBuf = new byte[ 2048 ]; + BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE); + + try { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE); + + int count = 0; + while ((count = bis.read(dataBuf)) != -1) { + bos.write(dataBuf, 0, count); + } + bos.flush(); + bos.close(); + + if (tmpFile.length() > maxSize) { + tmpFile.delete(); + return new BaseState(false, AppInfo.MAX_SIZE); + } + + state = saveTmpFile(tmpFile, path); + + if (!state.isSuccess()) { + tmpFile.delete(); + } + + return state; + + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + } + + public static State saveFileByInputStream(InputStream is, String path) { + State state = null; + + File tmpFile = getTmpFile(); + + byte[] dataBuf = new byte[ 2048 ]; + BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE); + + try { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE); + + int count = 0; + while ((count = bis.read(dataBuf)) != -1) { + bos.write(dataBuf, 0, count); + } + bos.flush(); + bos.close(); + + state = saveTmpFile(tmpFile, path); + + if (!state.isSuccess()) { + tmpFile.delete(); + } + + return state; + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + } + + private static File getTmpFile() { + File tmpDir = FileUtils.getTempDirectory(); + String tmpFileName = (Math.random() * 10000 + "").replace(".", ""); + return new File(tmpDir, tmpFileName); + } + + private static State saveTmpFile(File tmpFile, String path) { + State state = null; + File targetFile = new File(path); + + if (targetFile.canWrite()) { + return new BaseState(false, AppInfo.PERMISSION_DENIED); + } + try { + FileUtils.moveFile(tmpFile, targetFile); + } catch (IOException e) { + return new BaseState(false, AppInfo.IO_ERROR); + } + + state = new BaseState(true); + state.putInfo( "size", targetFile.length() ); + state.putInfo( "title", targetFile.getName() ); + + return state; + } + + private static State valid(File file) { + File parentPath = file.getParentFile(); + + if ((!parentPath.exists()) && (!parentPath.mkdirs())) { + return new BaseState(false, AppInfo.FAILED_CREATE_FILE); + } + + if (!parentPath.canWrite()) { + return new BaseState(false, AppInfo.PERMISSION_DENIED); + } + + return new BaseState(true); + } +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/upload/Uploader.java b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/upload/Uploader.java new file mode 100644 index 000000000..2312d1bcb --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/jsp/src/com/baidu/ueditor/upload/Uploader.java @@ -0,0 +1,29 @@ +package com.baidu.ueditor.upload; + +import com.baidu.ueditor.define.State; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; + +public class Uploader { + private HttpServletRequest request = null; + private Map conf = null; + + public Uploader(HttpServletRequest request, Map conf) { + this.request = request; + this.conf = conf; + } + + public final State doExec() { + String filedName = (String) this.conf.get("fieldName"); + State state = null; + + if ("true".equals(this.conf.get("isBase64"))) { + state = Base64Uploader.save(this.request.getParameter(filedName), + this.conf); + } else { + state = BinaryUploader.save(this.request, this.conf); + } + + return state; + } +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/en.js b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/en.js new file mode 100644 index 000000000..c7e22f5b4 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/en.js @@ -0,0 +1,684 @@ +/** + * Created with JetBrains PhpStorm. + * User: taoqili + * Date: 12-6-12 + * Time: 下午6:57 + * To change this template use File | Settings | File Templates. + */ +UE.I18N['en'] = { + 'labelMap':{ + 'anchor':'Anchor', 'undo':'Undo', 'redo':'Redo', 'bold':'Bold', 'indent':'Indent', 'snapscreen':'SnapScreen', + 'italic':'Italic', 'underline':'Underline', 'strikethrough':'Strikethrough', 'subscript':'SubScript','fontborder':'text border', + 'superscript':'SuperScript', 'formatmatch':'Format Match', 'source':'Source', 'blockquote':'BlockQuote', + 'pasteplain':'PastePlain', 'selectall':'SelectAll', 'print':'Print', 'preview':'Preview', + 'horizontal':'Horizontal', 'removeformat':'RemoveFormat', 'time':'Time', 'date':'Date', + 'unlink':'Unlink', 'insertrow':'InsertRow', 'insertcol':'InsertCol', 'mergeright':'MergeRight', 'mergedown':'MergeDown', + 'deleterow':'DeleteRow', 'deletecol':'DeleteCol', 'splittorows':'SplitToRows','insertcode':'insert code', + 'splittocols':'SplitToCols', 'splittocells':'SplitToCells','deletecaption':'DeleteCaption','inserttitle':'InsertTitle', + 'mergecells':'MergeCells', 'deletetable':'DeleteTable', 'cleardoc':'Clear', 'insertparagraphbeforetable':"InsertParagraphBeforeTable", + 'fontfamily':'FontFamily', 'fontsize':'FontSize', 'paragraph':'Paragraph','simpleupload':'Single Image','insertimage':'Multi Image','edittable':'Edit Table', 'edittd':'Edit Td','link':'Link', + 'emotion':'Emotion', 'spechars':'Spechars', 'searchreplace':'SearchReplace', 'map':'BaiduMap', 'gmap':'GoogleMap', + 'insertvideo':'Video', 'help':'Help', 'justifyleft':'JustifyLeft', 'justifyright':'JustifyRight', 'justifycenter':'JustifyCenter', + 'justifyjustify':'Justify', 'forecolor':'FontColor', 'backcolor':'BackColor', 'insertorderedlist':'OL', + 'insertunorderedlist':'UL', 'fullscreen':'FullScreen', 'directionalityltr':'EnterFromLeft', 'directionalityrtl':'EnterFromRight', + 'rowspacingtop':'RowSpacingTop', 'rowspacingbottom':'RowSpacingBottom', 'pagebreak':'PageBreak', 'insertframe':'Iframe', 'imagenone':'Default', + 'imageleft':'ImageLeft', 'imageright':'ImageRight', 'attachment':'Attachment', 'imagecenter':'ImageCenter', 'wordimage':'WordImage', + 'lineheight':'LineHeight','edittip':'EditTip','customstyle':'CustomStyle', 'scrawl':'Scrawl', 'autotypeset':'AutoTypeset', + 'webapp':'WebAPP', 'touppercase':'UpperCase', 'tolowercase':'LowerCase','template':'Template','background':'Background','inserttable':'InsertTable', + 'music':'Music', 'charts': 'charts','drafts': 'Load from Drafts' + }, + 'insertorderedlist':{ + 'num':'1,2,3...', + 'num1':'1),2),3)...', + 'num2':'(1),(2),(3)...', + 'cn':'一,二,三....', + 'cn1':'一),二),三)....', + 'cn2':'(一),(二),(三)....', + 'decimal':'1,2,3...', + 'lower-alpha':'a,b,c...', + 'lower-roman':'i,ii,iii...', + 'upper-alpha':'A,B,C...', + 'upper-roman':'I,II,III...' + }, + 'insertunorderedlist':{ + 'circle':'○ Circle', + 'disc':'● Circle dot', + 'square':'■ Rectangle ', + 'dash' :'- Dash', + 'dot' : '。dot' + }, + 'paragraph':{'p':'Paragraph', 'h1':'Title 1', 'h2':'Title 2', 'h3':'Title 3', 'h4':'Title 4', 'h5':'Title 5', 'h6':'Title 6'}, + 'fontfamily':{ + 'songti':'Sim Sun', + 'kaiti':'Sim Kai', + 'heiti':'Sim Hei', + 'lishu':'Sim Li', + 'yahei': 'Microsoft YaHei', + 'andaleMono':'Andale Mono', + 'arial': 'Arial', + 'arialBlack':'Arial Black', + 'comicSansMs':'Comic Sans MS', + 'impact':'Impact', + 'timesNewRoman':'Times New Roman' + }, + 'customstyle':{ + 'tc':'Title center', + 'tl':'Title left', + 'im':'Important', + 'hi':'Highlight' + }, + 'autoupload': { + 'exceedSizeError': 'File Size Exceed', + 'exceedTypeError': 'File Type Not Allow', + 'jsonEncodeError': 'Server Return Format Error', + 'loading':"loading...", + 'loadError':"load error", + 'errorLoadConfig': 'Server config not loaded, upload can not work.', + }, + 'simpleupload':{ + 'exceedSizeError': 'File Size Exceed', + 'exceedTypeError': 'File Type Not Allow', + 'jsonEncodeError': 'Server Return Format Error', + 'loading':"loading...", + 'loadError':"load error", + 'errorLoadConfig': 'Server config not loaded, upload can not work.', + }, + 'elementPathTip':"Path", + 'wordCountTip':"Word Count", + 'wordCountMsg':'{#count} characters entered,{#leave} left. ', + 'wordOverFlowMsg':'The number of characters has exceeded allowable maximum values, the server may refuse to save!', + 'ok':"OK", + 'cancel':"Cancel", + 'closeDialog':"closeDialog", + 'tableDrag':"You must import the file uiUtils.js before drag! ", + 'autofloatMsg':"The plugin AutoFloat depends on EditorUI!", + 'loadconfigError': 'Get server config error.', + 'loadconfigFormatError': 'Server config format error.', + 'loadconfigHttpError': 'Get server config http error.', + 'snapScreen_plugin':{ + 'browserMsg':"Only IE supported!", + 'callBackErrorMsg':"The callback data is wrong,please check the config!", + 'uploadErrorMsg':"Upload error,please check your server environment! " + }, + 'insertcode':{ + 'as3':'ActionScript 3', + 'bash':'Bash/Shell', + 'cpp':'C/C++', + 'css':'CSS', + 'cf':'ColdFusion', + 'c#':'C#', + 'delphi':'Delphi', + 'diff':'Diff', + 'erlang':'Erlang', + 'groovy':'Groovy', + 'html':'HTML', + 'java':'Java', + 'jfx':'JavaFX', + 'js':'JavaScript', + 'pl':'Perl', + 'php':'PHP', + 'plain':'Plain Text', + 'ps':'PowerShell', + 'python':'Python', + 'ruby':'Ruby', + 'scala':'Scala', + 'sql':'SQL', + 'vb':'Visual Basic', + 'xml':'XML' + }, + 'confirmClear':"Do you confirm to clear the Document?", + 'contextMenu':{ + 'delete':"Delete", + 'selectall':"Select all", + 'deletecode':"Delete Code", + 'cleardoc':"Clear Document", + 'confirmclear':"Do you confirm to clear the Document?", + 'unlink':"Unlink", + 'paragraph':"Paragraph", + 'edittable':"Table property", + 'aligncell':'Align cell', + 'aligntable':'Table alignment', + 'tableleft':'Left float', + 'tablecenter':'Center', + 'tableright':'Right float', + 'aligntd':'Cell alignment', + 'edittd':"Cell property", + 'setbordervisible':'set table edge visible', + 'table':"Table", + 'justifyleft':'Justify Left', + 'justifyright':'Justify Right', + 'justifycenter':'Justify Center', + 'justifyjustify':'Default', + 'deletetable':"Delete table", + 'insertparagraphbefore':"InsertedBeforeLine", + 'insertparagraphafter':'InsertedAfterLine', + 'inserttable':'Insert table', + 'insertcaption':'Insert caption', + 'deletecaption':'Delete Caption', + 'inserttitle':'Insert Title', + 'deletetitle':'Delete Title', + 'inserttitlecol':'Insert Title Col', + 'deletetitlecol':'Delete Title Col', + 'averageDiseRow':'AverageDise Row', + 'averageDisCol':'AverageDis Col', + 'deleterow':"Delete row", + 'deletecol':"Delete col", + 'insertrow':"Insert row", + 'insertcol':"Insert col", + 'insertrownext':'Insert Row Next', + 'insertcolnext':'Insert Col Next', + 'mergeright':"Merge right", + 'mergeleft':"Merge left", + 'mergedown':"Merge down", + 'mergecells':"Merge cells", + 'splittocells':"Split to cells", + 'splittocols':"Split to Cols", + 'splittorows':"Split to Rows", + 'tablesort':'Table sorting', + 'enablesort':'Sorting Enable', + 'disablesort':'Sorting Disable', + 'reversecurrent':'Reverse current', + 'orderbyasc':'Order By ASCII', + 'reversebyasc':'Reverse By ASCII', + 'orderbynum':'Order By Num', + 'reversebynum':'Reverse By Num', + 'borderbk':'Border shading', + 'setcolor':'interlaced color', + 'unsetcolor':'Cancel interlacedcolor', + 'setbackground':'Background interlaced', + 'unsetbackground':'Cancel Bk interlaced', + 'redandblue':'Blue and red', + 'threecolorgradient':'Three-color gradient', + 'copy':"Copy(Ctrl + c)", + 'copymsg':"Browser does not support. Please use 'Ctrl + c' instead!", + 'paste':"Paste(Ctrl + v)", + 'pastemsg':"Browser does not support. Please use 'Ctrl + v' instead!" + }, + 'copymsg': "Browser does not support. Please use 'Ctrl + c' instead!", + 'pastemsg': "Browser does not support. Please use 'Ctrl + v' instead!", + 'anthorMsg':"Link", + 'clearColor':'Clear', + 'standardColor':'Standard color', + 'themeColor':'Theme color', + 'property':'Property', + 'default':'Default', + 'modify':'Modify', + 'justifyleft':'Justify Left', + 'justifyright':'Justify Right', + 'justifycenter':'Justify Center', + 'justify':'Default', + 'clear':'Clear', + 'anchorMsg':'Anchor', + 'delete':'Delete', + 'clickToUpload':"Click to upload", + 'unset':'Language hasn\'t been set!', + 't_row':'row', + 't_col':'col', + 'pasteOpt':'Paste Option', + 'pasteSourceFormat':"Keep Source Formatting", + 'tagFormat':'Keep tag', + 'pasteTextFormat':'Keep Text only', + 'more':'More', + 'autoTypeSet':{ + 'mergeLine':"Merge empty line", + 'delLine':"Del empty line", + 'removeFormat':"Remove format", + 'indent':"Indent", + 'alignment':"Alignment", + 'imageFloat':"Image float", + 'removeFontsize':"Remove font size", + 'removeFontFamily':"Remove fontFamily", + 'removeHtml':"Remove redundant HTML code", + 'pasteFilter':"Paste filter", + 'run':"Done", + 'symbol':'Symbol Conversion', + 'bdc2sb':'Full-width to Half-width', + 'tobdc':'Half-width to Full-width' + }, + + 'background':{ + 'static':{ + 'lang_background_normal':'Normal', + 'lang_background_local':'Online', + 'lang_background_set':'Background Set', + 'lang_background_none':'No Background', + 'lang_background_colored':'Colored Background', + 'lang_background_color':'Color Set', + 'lang_background_netimg':'Net-Image', + 'lang_background_align':'Align Type', + 'lang_background_position':'Position', + 'repeatType':{'options':["Center", "Repeat-x", "Repeat-y", "Tile","Custom"]} + }, + 'noUploadImage':"No pictures has been uploaded!", + 'toggleSelect':'Change the active state by click!\n Image Size: ' + }, + //===============dialog i18N======================= + 'insertimage':{ + 'static':{ + 'lang_tab_remote':"Insert", + 'lang_tab_upload':"Local", + 'lang_tab_online':"Manager", + 'lang_tab_search':"Search", + 'lang_input_url':"Address:", + 'lang_input_size':"Size:", + 'lang_input_width':"Width", + 'lang_input_height':"Height", + 'lang_input_border':"Border:", + 'lang_input_vhspace':"Margins:", + 'lang_input_title':"Title:", + 'lang_input_align':'Image Float Style:', + 'lang_imgLoading':"Loading...", + 'lang_start_upload':"Start Upload", + 'lock':{'title':"Lock rate"}, + 'searchType':{'title':"ImageType", 'options':["News", "Wallpaper", "emotions", "photo"]}, + 'searchTxt':{'value':"Enter the search keyword!"}, + 'searchBtn':{'value':"Search"}, + 'searchReset':{'value':"Clear"}, + 'noneAlign':{'title':'None Float'}, + 'leftAlign':{'title':'Left Float'}, + 'rightAlign':{'title':'Right Float'}, + 'centerAlign':{'title':'Center In A Line'} + }, + 'uploadSelectFile':'Select File', + 'uploadAddFile':'Add File', + 'uploadStart':'Start Upload', + 'uploadPause':'Pause Upload', + 'uploadContinue':'Continue Upload', + 'uploadRetry':'Retry Upload', + 'uploadDelete':'Delete', + 'uploadTurnLeft':'Turn Left', + 'uploadTurnRight':'Turn Right', + 'uploadPreview':'Doing Preview', + 'uploadNoPreview':'Can Not Preview', + 'updateStatusReady': 'Selected _ pictures, total _KB.', + 'updateStatusConfirm': '_ uploaded successfully and _ upload failed', + 'updateStatusFinish': 'Total _ pictures (_KB), _ uploaded successfully', + 'updateStatusError': ' and _ upload failed', + 'errorNotSupport': 'WebUploader does not support the browser you are using. Please upgrade your browser or flash player', + 'errorLoadConfig': 'Server config not loaded, upload can not work.', + 'errorExceedSize':'File Size Exceed', + 'errorFileType':'File Type Not Allow', + 'errorInterrupt':'File Upload Interrupted', + 'errorUploadRetry':'Upload Error, Please Retry.', + 'errorHttp':'Http Error', + 'errorServerUpload':'Server Result Error.', + 'remoteLockError':"Cannot Lock the Proportion between width and height", + 'numError':"Please enter the correct Num. e.g 123,400", + 'imageUrlError':"The image format may be wrong!", + 'imageLoadError':"Error,please check the network or URL!", + 'searchRemind':"Enter the search keyword!", + 'searchLoading':"Image is loading,please wait...", + 'searchRetry':" Sorry,can't find the image,please try again!" + }, + 'attachment':{ + 'static':{ + 'lang_tab_upload': 'Upload', + 'lang_tab_online': 'Online', + 'lang_start_upload':"Start upload", + 'lang_drop_remind':"You can drop files here, a single maximum of 300 files" + }, + 'uploadSelectFile':'Select File', + 'uploadAddFile':'Add File', + 'uploadStart':'Start Upload', + 'uploadPause':'Pause Upload', + 'uploadContinue':'Continue Upload', + 'uploadRetry':'Retry Upload', + 'uploadDelete':'Delete', + 'uploadTurnLeft':'Turn Left', + 'uploadTurnRight':'Turn Right', + 'uploadPreview':'Doing Preview', + 'updateStatusReady': 'Selected _ files, total _KB.', + 'updateStatusConfirm': '_ uploaded successfully and _ upload failed', + 'updateStatusFinish': 'Total _ files (_KB), _ uploaded successfully', + 'updateStatusError': ' and _ upload failed', + 'errorNotSupport': 'WebUploader does not support the browser you are using. Please upgrade your browser or flash player', + 'errorLoadConfig': 'Server config not loaded, upload can not work.', + 'errorExceedSize':'File Size Exceed', + 'errorFileType':'File Type Not Allow', + 'errorInterrupt':'File Upload Interrupted', + 'errorUploadRetry':'Upload Error, Please Retry.', + 'errorHttp':'Http Error', + 'errorServerUpload':'Server Result Error.' + }, + + 'insertvideo':{ + 'static':{ + 'lang_tab_insertV':"Video", + 'lang_tab_searchV':"Search", + 'lang_tab_uploadV':"Upload", + 'lang_video_url':" URL ", + 'lang_video_size':"Video Size", + 'lang_videoW':"Width", + 'lang_videoH':"Height", + 'lang_alignment':"Alignment", + 'videoSearchTxt':{'value':"Enter the search keyword!"}, + 'videoType':{'options':["All", "Hot", "Entertainment", "Funny", "Sports", "Science", "variety"]}, + 'videoSearchBtn':{'value':"Search in Baidu"}, + 'videoSearchReset':{'value':"Clear result"}, + + 'lang_input_fileStatus':' No file uploaded!', + 'startUpload':{'style':"background:url(upload.png) no-repeat;"}, + + 'lang_upload_size':"Video Size", + 'lang_upload_width':"Width", + 'lang_upload_height':"Height", + 'lang_upload_alignment':"Alignment", + 'lang_format_advice':"Recommends mp4 format." + }, + 'numError':"Please enter the correct Num. e.g 123,400", + 'floatLeft':"Float left", + 'floatRight':"Float right", + 'default':"Default", + 'block':"Display in block", + 'urlError':"The video url format may be wrong!", + 'loading':"  The video is loading, please wait…", + 'clickToSelect':"Click to select", + 'goToSource':'Visit source video ', + 'noVideo':"    Sorry,can't find the video,please try again!", + + 'browseFiles':'Open files', + 'uploadSuccess':'Upload Successful!', + 'delSuccessFile':'Remove from the success of the queue', + 'delFailSaveFile':'Remove the save failed file', + 'statusPrompt':' file(s) uploaded! ', + 'flashVersionError':'The current Flash version is too low, please update FlashPlayer,then try again!', + 'flashLoadingError':'The Flash failed loading! Please check the path or network state', + 'fileUploadReady':'Wait for uploading...', + 'delUploadQueue':'Remove from the uploading queue ', + 'limitPrompt1':'Can not choose more than single', + 'limitPrompt2':'file(s)!Please choose again!', + 'delFailFile':'Remove failure file', + 'fileSizeLimit':'File size exceeds the limit!', + 'emptyFile':'Can not upload an empty file!', + 'fileTypeError':'File type error!', + 'unknownError':'Unknown error!', + 'fileUploading':'Uploading,please wait...', + 'cancelUpload':'Cancel upload', + 'netError':'Network error', + 'failUpload':'Upload failed', + 'serverIOError':'Server IO error!', + 'noAuthority':'No Permission!', + 'fileNumLimit':'Upload limit to the number', + 'failCheck':'Authentication fails, the upload is skipped!', + 'fileCanceling':'Cancel, please wait...', + 'stopUploading':'Upload has stopped...', + + 'uploadSelectFile':'Select File', + 'uploadAddFile':'Add File', + 'uploadStart':'Start Upload', + 'uploadPause':'Pause Upload', + 'uploadContinue':'Continue Upload', + 'uploadRetry':'Retry Upload', + 'uploadDelete':'Delete', + 'uploadTurnLeft':'Turn Left', + 'uploadTurnRight':'Turn Right', + 'uploadPreview':'Doing Preview', + 'updateStatusReady': 'Selected _ files, total _KB.', + 'updateStatusConfirm': '_ uploaded successfully and _ upload failed', + 'updateStatusFinish': 'Total _ files (_KB), _ uploaded successfully', + 'updateStatusError': ' and _ upload failed', + 'errorNotSupport': 'WebUploader does not support the browser you are using. Please upgrade your browser or flash player', + 'errorLoadConfig': 'Server config not loaded, upload can not work.', + 'errorExceedSize':'File Size Exceed', + 'errorFileType':'File Type Not Allow', + 'errorInterrupt':'File Upload Interrupted', + 'errorUploadRetry':'Upload Error, Please Retry.', + 'errorHttp':'Http Error', + 'errorServerUpload':'Server Result Error.' + }, + 'webapp':{ + 'tip1':"This function provided by Baidu APP,please apply for baidu APPKey webmaster first!", + 'tip2':"And then open the file ueditor.config.js to set it! ", + 'applyFor':"APPLY FOR", + 'anthorApi':"Baidu API" + }, + 'template':{ + 'static':{ + 'lang_template_bkcolor':'Background Color', + 'lang_template_clear' : 'Keep Content', + 'lang_template_select':'Select Template' + }, + 'blank':"Blank", + 'blog':"Blog", + 'resume':"Resume", + 'richText':"Rich Text", + 'scrPapers':"Scientific Papers" + }, + scrawl:{ + 'static':{ + 'lang_input_previousStep':"Previous", + 'lang_input_nextsStep':"Next", + 'lang_input_clear':'Clear', + 'lang_input_addPic':'AddImage', + 'lang_input_ScalePic':'ScaleImage', + 'lang_input_removePic':'RemoveImage', + 'J_imgTxt':{title:'Add background image'} + }, + 'noScarwl':"No paint, a white paper...", + 'scrawlUpLoading':"Image is uploading, please wait...", + 'continueBtn':"Try again", + 'imageError':"Image failed to load!", + 'backgroundUploading':'Image is uploading,please wait...' + }, + 'music':{ + 'static':{ + 'lang_input_tips':"Input singer/song/album, search you interested in music!", + 'J_searchBtn':{value:'Search songs'} + }, + 'emptyTxt':'Not search to the relevant music results, please change a keyword try.', + 'chapter':'Songs', + 'singer':'Singer', + 'special':'Album', + 'listenTest':'Audition' + }, + anchor:{ + 'static':{ + 'lang_input_anchorName':'Anchor Name:' + } + }, + 'charts':{ + 'static':{ + 'lang_data_source':'Data source:', + 'lang_chart_format': 'Chart format:', + 'lang_data_align': 'Align', + 'lang_chart_align_same': 'Consistent with the X-axis Y-axis', + 'lang_chart_align_reverse': 'X-axis Y-axis opposite', + 'lang_chart_title': 'Title', + 'lang_chart_main_title': 'main title:', + 'lang_chart_sub_title': 'sub title:', + 'lang_chart_x_title': 'X-axis title:', + 'lang_chart_y_title': 'Y-axis title:', + 'lang_chart_tip': 'Prompt', + 'lang_cahrt_tip_prefix': 'prefix:', + 'lang_cahrt_tip_description': '仅饼图有效, 当鼠标移动到饼图中相应的块上时,提示框内的文字的前缀', + 'lang_chart_data_unit': 'Unit', + 'lang_chart_data_unit_title': 'unit:', + 'lang_chart_data_unit_description': '显示在每个数据点上的数据的单位, 比如: 温度的单位 ℃', + 'lang_chart_type': 'Chart type:', + 'lang_prev_btn': 'Previous', + 'lang_next_btn': 'Next' + } + }, + emotion:{ + 'static':{ + 'lang_input_choice':'Choice', + 'lang_input_Tuzki':'Tuzki', + 'lang_input_lvdouwa':'LvDouWa', + 'lang_input_BOBO':'BOBO', + 'lang_input_babyCat':'BabyCat', + 'lang_input_bubble':'Bubble', + 'lang_input_youa':'YouA' + } + }, + gmap:{ + 'static':{ + 'lang_input_address':'Address:', + 'lang_input_search':'Search', + 'address':{value:"Beijing"} + }, + searchError:'Unable to locate the address!' + }, + help:{ + 'static':{ + 'lang_input_about':'About', + 'lang_input_shortcuts':'Shortcuts', + 'lang_input_introduction':"UEditor is developed by Baidu Co.ltd. It is lightweight, customizable , focusing on user experience and etc. , UEditor is based on open source BSD license , allowing free use and redistribution.", + 'lang_Txt_shortcuts':'Shortcuts', + 'lang_Txt_func':'Function', + 'lang_Txt_bold':'Bold', + 'lang_Txt_copy':'Copy', + 'lang_Txt_cut':'Cut', + 'lang_Txt_Paste':'Paste', + 'lang_Txt_undo':'Undo', + 'lang_Txt_redo':'Redo', + 'lang_Txt_italic':'Italic', + 'lang_Txt_underline':'Underline', + 'lang_Txt_selectAll':'Select All', + 'lang_Txt_visualEnter':'Submit', + 'lang_Txt_fullscreen':'Fullscreen' + } + }, + insertframe:{ + 'static':{ + 'lang_input_address':'Address:', + 'lang_input_width':'Width:', + 'lang_input_height':'height:', + 'lang_input_isScroll':'Enable scrollbars:', + 'lang_input_frameborder':'Show frame border:', + 'lang_input_alignMode':'Alignment:', + 'align':{title:"Alignment", options:["Default", "Left", "Right", "Center"]} + }, + 'enterAddress':'Please enter an address!' + }, + link:{ + 'static':{ + 'lang_input_text':'Text:', + 'lang_input_url':'URL:', + 'lang_input_title':'Title:', + 'lang_input_target':'open in new window:' + }, + 'validLink':'Supports only effective when a link is selected', + 'httpPrompt':'The hyperlink you enter should start with "http|https|ftp://"!' + }, + map:{ + 'static':{ + lang_city:"City", + lang_address:"Address", + city:{value:"Beijing"}, + lang_search:"Search", + lang_dynamicmap:"Dynamic map" + }, + cityMsg:"Please enter the city name!", + errorMsg:"Can't find the place!" + }, + searchreplace:{ + 'static':{ + lang_tab_search:"Search", + lang_tab_replace:"Replace", + lang_search1:"Search", + lang_search2:"Search", + lang_replace:"Replace", + lang_searchReg:'Support regular expression ,which starts and ends with a slash ,for example "/expression/"', + lang_searchReg1:'Support regular expression ,which starts and ends with a slash ,for example "/expression/"', + lang_case_sensitive1:"Case sense", + lang_case_sensitive2:"Case sense", + nextFindBtn:{value:"Next"}, + preFindBtn:{value:"Preview"}, + nextReplaceBtn:{value:"Next"}, + preReplaceBtn:{value:"Preview"}, + repalceBtn:{value:"Replace"}, + repalceAllBtn:{value:"Replace all"} + }, + getEnd:"Has the search to the bottom!", + getStart:"Has the search to the top!", + countMsg:"Altogether replaced {#count} character(s)!" + }, + snapscreen:{ + 'static':{ + lang_showMsg:"You should install the UEditor screenshots program first!", + lang_download:"Download!", + lang_step1:"Step1:Download the program and then run it", + lang_step2:"Step2:After complete install,try to click the button again" + } + }, + spechars:{ + 'static':{}, + tsfh:"Special", + lmsz:"Roman", + szfh:"Numeral", + rwfh:"Japanese", + xlzm:"The Greek", + ewzm:"Russian", + pyzm:"Phonetic", + yyyb:"English", + zyzf:"Others" + }, + 'edittable':{ + 'static':{ + 'lang_tableStyle':'Table style', + 'lang_insertCaption':'Add table header row', + 'lang_insertTitle':'Add table title row', + 'lang_insertTitleCol':'Add table title col', + 'lang_tableSize':'Automatically adjust table size', + 'lang_autoSizeContent':'Adaptive by form text', + 'lang_orderbycontent':"Table of contents sortable", + 'lang_autoSizePage':'Page width adaptive', + 'lang_example':'Example', + 'lang_borderStyle':'Table Border', + 'lang_color':'Color:' + }, + captionName:'Caption', + titleName:'Title', + cellsName:'text', + errorMsg:'There are merged cells, can not sort.' + }, + 'edittip':{ + 'static':{ + lang_delRow:'Delete entire row', + lang_delCol:'Delete entire col' + } + }, + 'edittd':{ + 'static':{ + lang_tdBkColor:'Background Color:' + } + }, + 'formula':{ + 'static':{ + } + }, + wordimage:{ + 'static':{ + lang_resave:"The re-save step", + uploadBtn:{src:"upload.png", alt:"Upload"}, + clipboard:{style:"background: url(copy.png) -153px -1px no-repeat;"}, + lang_step:" 1. Click top button to copy the url and then open the dialog to paste it. 2. Open after choose photos uploaded process." + }, + fileType:"Image", + flashError:"Flash initialization failed!", + netError:"Network error! Please try again!", + copySuccess:"URL has been copied!", + + 'flashI18n':{ + lang:encodeURI( '{"UploadingState":"totalNum: ${a},uploadComplete: ${b}", "BeforeUpload":"waitingNum: ${a}", "ExceedSize":"Size exceed${a}", "ErrorInPreview":"Preview failed", "DefaultDescription":"Description", "LoadingImage":"Loading..."}' ), + uploadingTF:encodeURI( '{"font":"Arial", "size":12, "color":"0x000", "bold":"true", "italic":"false", "underline":"false"}' ), + imageTF:encodeURI( '{"font":"Arial", "size":11, "color":"red", "bold":"false", "italic":"false", "underline":"false"}' ), + textEncoding:"utf-8", + addImageSkinURL:"addImage.png", + allDeleteBtnUpSkinURL:"allDeleteBtnUpSkin.png", + allDeleteBtnHoverSkinURL:"allDeleteBtnHoverSkin.png", + rotateLeftBtnEnableSkinURL:"rotateLeftEnable.png", + rotateLeftBtnDisableSkinURL:"rotateLeftDisable.png", + rotateRightBtnEnableSkinURL:"rotateRightEnable.png", + rotateRightBtnDisableSkinURL:"rotateRightDisable.png", + deleteBtnEnableSkinURL:"deleteEnable.png", + deleteBtnDisableSkinURL:"deleteDisable.png", + backgroundURL:'', + listBackgroundURL:'', + buttonURL:'button.png' + } + }, + 'autosave': { + 'success':'Local conservation success' + } +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/addimage.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/addimage.png new file mode 100644 index 000000000..3a2fd1712 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/addimage.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/alldeletebtnhoverskin.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/alldeletebtnhoverskin.png new file mode 100644 index 000000000..355eeabbd Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/alldeletebtnhoverskin.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/alldeletebtnupskin.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/alldeletebtnupskin.png new file mode 100644 index 000000000..61658ce6f Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/alldeletebtnupskin.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/background.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/background.png new file mode 100644 index 000000000..d5bf5fdd8 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/background.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/button.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/button.png new file mode 100644 index 000000000..098874cb1 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/button.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/copy.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/copy.png new file mode 100644 index 000000000..f982e8bcb Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/copy.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/deletedisable.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/deletedisable.png new file mode 100644 index 000000000..c8ee75094 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/deletedisable.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/deleteenable.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/deleteenable.png new file mode 100644 index 000000000..26acc8835 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/deleteenable.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/listbackground.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/listbackground.png new file mode 100644 index 000000000..4f82ccd88 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/listbackground.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/localimage.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/localimage.png new file mode 100644 index 000000000..12c8e6aef Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/localimage.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/music.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/music.png new file mode 100644 index 000000000..2f495fe92 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/music.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/rotateleftdisable.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/rotateleftdisable.png new file mode 100644 index 000000000..741526e0d Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/rotateleftdisable.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/rotateleftenable.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/rotateleftenable.png new file mode 100644 index 000000000..e164ddbd6 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/rotateleftenable.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/rotaterightdisable.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/rotaterightdisable.png new file mode 100644 index 000000000..5a78c2606 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/rotaterightdisable.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/rotaterightenable.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/rotaterightenable.png new file mode 100644 index 000000000..d768531fc Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/rotaterightenable.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/upload.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/upload.png new file mode 100644 index 000000000..7bb15b3d6 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/en/images/upload.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/zh-cn/images/copy.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/zh-cn/images/copy.png new file mode 100644 index 000000000..b2536aac7 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/zh-cn/images/copy.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/zh-cn/images/localimage.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/zh-cn/images/localimage.png new file mode 100644 index 000000000..7303c3643 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/zh-cn/images/localimage.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/zh-cn/images/music.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/zh-cn/images/music.png new file mode 100644 index 000000000..354edebc3 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/zh-cn/images/music.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/zh-cn/images/upload.png b/nezha-fronted/static/ueditor-1.4.3.3/lang/zh-cn/images/upload.png new file mode 100644 index 000000000..08d4d9268 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/lang/zh-cn/images/upload.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/lang/zh-cn/zh-cn.js b/nezha-fronted/static/ueditor-1.4.3.3/lang/zh-cn/zh-cn.js new file mode 100644 index 000000000..4d5178f98 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/lang/zh-cn/zh-cn.js @@ -0,0 +1,669 @@ +/** + * Created with JetBrains PhpStorm. + * User: taoqili + * Date: 12-6-12 + * Time: 下午5:02 + * To change this template use File | Settings | File Templates. + */ +UE.I18N['zh-cn'] = { + 'labelMap':{ + 'anchor':'锚点', 'undo':'撤销', 'redo':'重做', 'bold':'加粗', 'indent':'首行缩进', 'snapscreen':'截图', + 'italic':'斜体', 'underline':'下划线', 'strikethrough':'删除线', 'subscript':'下标','fontborder':'字符边框', + 'superscript':'上标', 'formatmatch':'格式刷', 'source':'源代码', 'blockquote':'引用', + 'pasteplain':'纯文本粘贴模式', 'selectall':'全选', 'print':'打印', 'preview':'预览', + 'horizontal':'分隔线', 'removeformat':'清除格式', 'time':'时间', 'date':'日期', + 'unlink':'取消链接', 'insertrow':'前插入行', 'insertcol':'前插入列', 'mergeright':'右合并单元格', 'mergedown':'下合并单元格', + 'deleterow':'删除行', 'deletecol':'删除列', 'splittorows':'拆分成行', + 'splittocols':'拆分成列', 'splittocells':'完全拆分单元格','deletecaption':'删除表格标题','inserttitle':'插入标题', + 'mergecells':'合并多个单元格', 'deletetable':'删除表格', 'cleardoc':'清空文档','insertparagraphbeforetable':"表格前插入行",'insertcode':'代码语言', + 'fontfamily':'字体', 'fontsize':'字号', 'paragraph':'段落格式', 'simpleupload':'单图上传', 'insertimage':'多图上传','edittable':'表格属性','edittd':'单元格属性', 'link':'超链接', + 'emotion':'表情', 'spechars':'特殊字符', 'searchreplace':'查询替换', 'map':'Baidu地图', 'gmap':'Google地图', + 'insertvideo':'视频', 'help':'帮助', 'justifyleft':'居左对齐', 'justifyright':'居右对齐', 'justifycenter':'居中对齐', + 'justifyjustify':'两端对齐', 'forecolor':'字体颜色', 'backcolor':'背景色', 'insertorderedlist':'有序列表', + 'insertunorderedlist':'无序列表', 'fullscreen':'全屏', 'directionalityltr':'从左向右输入', 'directionalityrtl':'从右向左输入', + 'rowspacingtop':'段前距', 'rowspacingbottom':'段后距', 'pagebreak':'分页', 'insertframe':'插入Iframe', 'imagenone':'默认', + 'imageleft':'左浮动', 'imageright':'右浮动', 'attachment':'附件', 'imagecenter':'居中', 'wordimage':'图片转存', + 'lineheight':'行间距','edittip' :'编辑提示','customstyle':'自定义标题', 'autotypeset':'自动排版', + 'webapp':'百度应用','touppercase':'字母大写', 'tolowercase':'字母小写','background':'背景','template':'模板','scrawl':'涂鸦', + 'music':'音乐','inserttable':'插入表格','drafts': '从草稿箱加载', 'charts': '图表' + }, + 'insertorderedlist':{ + 'num':'1,2,3...', + 'num1':'1),2),3)...', + 'num2':'(1),(2),(3)...', + 'cn':'一,二,三....', + 'cn1':'一),二),三)....', + 'cn2':'(一),(二),(三)....', + 'decimal':'1,2,3...', + 'lower-alpha':'a,b,c...', + 'lower-roman':'i,ii,iii...', + 'upper-alpha':'A,B,C...', + 'upper-roman':'I,II,III...' + }, + 'insertunorderedlist':{ + 'circle':'○ 大圆圈', + 'disc':'● 小黑点', + 'square':'■ 小方块 ', + 'dash' :'— 破折号', + 'dot':' 。 小圆圈' + }, + 'paragraph':{'p':'段落', 'h1':'标题 1', 'h2':'标题 2', 'h3':'标题 3', 'h4':'标题 4', 'h5':'标题 5', 'h6':'标题 6'}, + 'fontfamily':{ + 'songti':'宋体', + 'kaiti':'楷体', + 'heiti':'黑体', + 'lishu':'隶书', + 'yahei':'微软雅黑', + 'andaleMono':'andale mono', + 'arial': 'arial', + 'arialBlack':'arial black', + 'comicSansMs':'comic sans ms', + 'impact':'impact', + 'timesNewRoman':'times new roman' + }, + 'customstyle':{ + 'tc':'标题居中', + 'tl':'标题居左', + 'im':'强调', + 'hi':'明显强调' + }, + 'autoupload': { + 'exceedSizeError': '文件大小超出限制', + 'exceedTypeError': '文件格式不允许', + 'jsonEncodeError': '服务器返回格式错误', + 'loading':"正在上传...", + 'loadError':"上传错误", + 'errorLoadConfig': '后端配置项没有正常加载,上传插件不能正常使用!' + }, + 'simpleupload':{ + 'exceedSizeError': '文件大小超出限制', + 'exceedTypeError': '文件格式不允许', + 'jsonEncodeError': '服务器返回格式错误', + 'loading':"正在上传...", + 'loadError':"上传错误", + 'errorLoadConfig': '后端配置项没有正常加载,上传插件不能正常使用!' + }, + 'elementPathTip':"元素路径", + 'wordCountTip':"字数统计", + 'wordCountMsg':'当前已输入{#count}个字符, 您还可以输入{#leave}个字符。 ', + 'wordOverFlowMsg':'字数超出最大允许值,服务器可能拒绝保存!', + 'ok':"确认", + 'cancel':"取消", + 'closeDialog':"关闭对话框", + 'tableDrag':"表格拖动必须引入uiUtils.js文件!", + 'autofloatMsg':"工具栏浮动依赖编辑器UI,您首先需要引入UI文件!", + 'loadconfigError': '获取后台配置项请求出错,上传功能将不能正常使用!', + 'loadconfigFormatError': '后台配置项返回格式出错,上传功能将不能正常使用!', + 'loadconfigHttpError': '请求后台配置项http错误,上传功能将不能正常使用!', + 'snapScreen_plugin':{ + 'browserMsg':"仅支持IE浏览器!", + 'callBackErrorMsg':"服务器返回数据有误,请检查配置项之后重试。", + 'uploadErrorMsg':"截图上传失败,请检查服务器端环境! " + }, + 'insertcode':{ + 'as3':'ActionScript 3', + 'bash':'Bash/Shell', + 'cpp':'C/C++', + 'css':'CSS', + 'cf':'ColdFusion', + 'c#':'C#', + 'delphi':'Delphi', + 'diff':'Diff', + 'erlang':'Erlang', + 'groovy':'Groovy', + 'html':'HTML', + 'java':'Java', + 'jfx':'JavaFX', + 'js':'JavaScript', + 'pl':'Perl', + 'php':'PHP', + 'plain':'Plain Text', + 'ps':'PowerShell', + 'python':'Python', + 'ruby':'Ruby', + 'scala':'Scala', + 'sql':'SQL', + 'vb':'Visual Basic', + 'xml':'XML' + }, + 'confirmClear':"确定清空当前文档么?", + 'contextMenu':{ + 'delete':"删除", + 'selectall':"全选", + 'deletecode':"删除代码", + 'cleardoc':"清空文档", + 'confirmclear':"确定清空当前文档么?", + 'unlink':"删除超链接", + 'paragraph':"段落格式", + 'edittable':"表格属性", + 'aligntd':"单元格对齐方式", + 'aligntable':'表格对齐方式', + 'tableleft':'左浮动', + 'tablecenter':'居中显示', + 'tableright':'右浮动', + 'edittd':"单元格属性", + 'setbordervisible':'设置表格边线可见', + 'justifyleft':'左对齐', + 'justifyright':'右对齐', + 'justifycenter':'居中对齐', + 'justifyjustify':'两端对齐', + 'table':"表格", + 'inserttable':'插入表格', + 'deletetable':"删除表格", + 'insertparagraphbefore':"前插入段落", + 'insertparagraphafter':'后插入段落', + 'deleterow':"删除当前行", + 'deletecol':"删除当前列", + 'insertrow':"前插入行", + 'insertcol':"左插入列", + 'insertrownext':'后插入行', + 'insertcolnext':'右插入列', + 'insertcaption':'插入表格名称', + 'deletecaption':'删除表格名称', + 'inserttitle':'插入表格标题行', + 'deletetitle':'删除表格标题行', + 'inserttitlecol':'插入表格标题列', + 'deletetitlecol':'删除表格标题列', + 'averageDiseRow':'平均分布各行', + 'averageDisCol':'平均分布各列', + 'mergeright':"向右合并", + 'mergeleft':"向左合并", + 'mergedown':"向下合并", + 'mergecells':"合并单元格", + 'splittocells':"完全拆分单元格", + 'splittocols':"拆分成列", + 'splittorows':"拆分成行", + 'tablesort':'表格排序', + 'enablesort':'设置表格可排序', + 'disablesort':'取消表格可排序', + 'reversecurrent':'逆序当前', + 'orderbyasc':'按ASCII字符升序', + 'reversebyasc':'按ASCII字符降序', + 'orderbynum':'按数值大小升序', + 'reversebynum':'按数值大小降序', + 'borderbk':'边框底纹', + 'setcolor':'表格隔行变色', + 'unsetcolor':'取消表格隔行变色', + 'setbackground':'选区背景隔行', + 'unsetbackground':'取消选区背景', + 'redandblue':'红蓝相间', + 'threecolorgradient':'三色渐变', + 'copy':"复制(Ctrl + c)", + 'copymsg': "浏览器不支持,请使用 'Ctrl + c'", + 'paste':"粘贴(Ctrl + v)", + 'pastemsg': "浏览器不支持,请使用 'Ctrl + v'" + }, + 'copymsg': "浏览器不支持,请使用 'Ctrl + c'", + 'pastemsg': "浏览器不支持,请使用 'Ctrl + v'", + 'anthorMsg':"链接", + 'clearColor':'清空颜色', + 'standardColor':'标准颜色', + 'themeColor':'主题颜色', + 'property':'属性', + 'default':'默认', + 'modify':'修改', + 'justifyleft':'左对齐', + 'justifyright':'右对齐', + 'justifycenter':'居中', + 'justify':'默认', + 'clear':'清除', + 'anchorMsg':'锚点', + 'delete':'删除', + 'clickToUpload':"点击上传", + 'unset':'尚未设置语言文件', + 't_row':'行', + 't_col':'列', + 'more':'更多', + 'pasteOpt':'粘贴选项', + 'pasteSourceFormat':"保留源格式", + 'tagFormat':'只保留标签', + 'pasteTextFormat':'只保留文本', + 'autoTypeSet':{ + 'mergeLine':"合并空行", + 'delLine':"清除空行", + 'removeFormat':"清除格式", + 'indent':"首行缩进", + 'alignment':"对齐方式", + 'imageFloat':"图片浮动", + 'removeFontsize':"清除字号", + 'removeFontFamily':"清除字体", + 'removeHtml':"清除冗余HTML代码", + 'pasteFilter':"粘贴过滤", + 'run':"执行", + 'symbol':'符号转换', + 'bdc2sb':'全角转半角', + 'tobdc':'半角转全角' + }, + + 'background':{ + 'static':{ + 'lang_background_normal':'背景设置', + 'lang_background_local':'在线图片', + 'lang_background_set':'选项', + 'lang_background_none':'无背景色', + 'lang_background_colored':'有背景色', + 'lang_background_color':'颜色设置', + 'lang_background_netimg':'网络图片', + 'lang_background_align':'对齐方式', + 'lang_background_position':'精确定位', + 'repeatType':{'options':["居中", "横向重复", "纵向重复", "平铺","自定义"]} + + }, + 'noUploadImage':"当前未上传过任何图片!", + 'toggleSelect':"单击可切换选中状态\n原图尺寸: " + }, + //===============dialog i18N======================= + 'insertimage':{ + 'static':{ + 'lang_tab_remote':"插入图片", //节点 + 'lang_tab_upload':"本地上传", + 'lang_tab_online':"在线管理", + 'lang_tab_search':"图片搜索", + 'lang_input_url':"地 址:", + 'lang_input_size':"大 小:", + 'lang_input_width':"宽度", + 'lang_input_height':"高度", + 'lang_input_border':"边 框:", + 'lang_input_vhspace':"边 距:", + 'lang_input_title':"描 述:", + 'lang_input_align':'图片浮动方式:', + 'lang_imgLoading':" 图片加载中……", + 'lang_start_upload':"开始上传", + 'lock':{'title':"锁定宽高比例"}, //属性 + 'searchType':{'title':"图片类型", 'options':["新闻", "壁纸", "表情", "头像"]}, //select的option + 'searchTxt':{'value':"请输入搜索关键词"}, + 'searchBtn':{'value':"百度一下"}, + 'searchReset':{'value':"清空搜索"}, + 'noneAlign':{'title':'无浮动'}, + 'leftAlign':{'title':'左浮动'}, + 'rightAlign':{'title':'右浮动'}, + 'centerAlign':{'title':'居中独占一行'} + }, + 'uploadSelectFile':'点击选择图片', + 'uploadAddFile':'继续添加', + 'uploadStart':'开始上传', + 'uploadPause':'暂停上传', + 'uploadContinue':'继续上传', + 'uploadRetry':'重试上传', + 'uploadDelete':'删除', + 'uploadTurnLeft':'向左旋转', + 'uploadTurnRight':'向右旋转', + 'uploadPreview':'预览中', + 'uploadNoPreview':'不能预览', + 'updateStatusReady': '选中_张图片,共_KB。', + 'updateStatusConfirm': '已成功上传_张照片,_张照片上传失败', + 'updateStatusFinish': '共_张(_KB),_张上传成功', + 'updateStatusError': ',_张上传失败。', + 'errorNotSupport': 'WebUploader 不支持您的浏览器!如果你使用的是IE浏览器,请尝试升级 flash 播放器。', + 'errorLoadConfig': '后端配置项没有正常加载,上传插件不能正常使用!', + 'errorExceedSize':'文件大小超出', + 'errorFileType':'文件格式不允许', + 'errorInterrupt':'文件传输中断', + 'errorUploadRetry':'上传失败,请重试', + 'errorHttp':'http请求错误', + 'errorServerUpload':'服务器返回出错', + 'remoteLockError':"宽高不正确,不能所定比例", + 'numError':"请输入正确的长度或者宽度值!例如:123,400", + 'imageUrlError':"不允许的图片格式或者图片域!", + 'imageLoadError':"图片加载失败!请检查链接地址或网络状态!", + 'searchRemind':"请输入搜索关键词", + 'searchLoading':"图片加载中,请稍后……", + 'searchRetry':" :( ,抱歉,没有找到图片!请重试一次!" + }, + 'attachment':{ + 'static':{ + 'lang_tab_upload': '上传附件', + 'lang_tab_online': '在线附件', + 'lang_start_upload':"开始上传", + 'lang_drop_remind':"可以将文件拖到这里,单次最多可选100个文件" + }, + 'uploadSelectFile':'点击选择文件', + 'uploadAddFile':'继续添加', + 'uploadStart':'开始上传', + 'uploadPause':'暂停上传', + 'uploadContinue':'继续上传', + 'uploadRetry':'重试上传', + 'uploadDelete':'删除', + 'uploadTurnLeft':'向左旋转', + 'uploadTurnRight':'向右旋转', + 'uploadPreview':'预览中', + 'updateStatusReady': '选中_个文件,共_KB。', + 'updateStatusConfirm': '已成功上传_个文件,_个文件上传失败', + 'updateStatusFinish': '共_个(_KB),_个上传成功', + 'updateStatusError': ',_张上传失败。', + 'errorNotSupport': 'WebUploader 不支持您的浏览器!如果你使用的是IE浏览器,请尝试升级 flash 播放器。', + 'errorLoadConfig': '后端配置项没有正常加载,上传插件不能正常使用!', + 'errorExceedSize':'文件大小超出', + 'errorFileType':'文件格式不允许', + 'errorInterrupt':'文件传输中断', + 'errorUploadRetry':'上传失败,请重试', + 'errorHttp':'http请求错误', + 'errorServerUpload':'服务器返回出错' + }, + 'insertvideo':{ + 'static':{ + 'lang_tab_insertV':"插入视频", + 'lang_tab_searchV':"搜索视频", + 'lang_tab_uploadV':"上传视频", + 'lang_video_url':"视频网址", + 'lang_video_size':"视频尺寸", + 'lang_videoW':"宽度", + 'lang_videoH':"高度", + 'lang_alignment':"对齐方式", + 'videoSearchTxt':{'value':"请输入搜索关键字!"}, + 'videoType':{'options':["全部", "热门", "娱乐", "搞笑", "体育", "科技", "综艺"]}, + 'videoSearchBtn':{'value':"百度一下"}, + 'videoSearchReset':{'value':"清空结果"}, + + 'lang_input_fileStatus':' 当前未上传文件', + 'startUpload':{'style':"background:url(upload.png) no-repeat;"}, + + 'lang_upload_size':"视频尺寸", + 'lang_upload_width':"宽度", + 'lang_upload_height':"高度", + 'lang_upload_alignment':"对齐方式", + 'lang_format_advice':"建议使用mp4格式." + + }, + 'numError':"请输入正确的数值,如123,400", + 'floatLeft':"左浮动", + 'floatRight':"右浮动", + '"default"':"默认", + 'block':"独占一行", + 'urlError':"输入的视频地址有误,请检查后再试!", + 'loading':"  视频加载中,请等待……", + 'clickToSelect':"点击选中", + 'goToSource':'访问源视频', + 'noVideo':"    抱歉,找不到对应的视频,请重试!", + + 'browseFiles':'浏览文件', + 'uploadSuccess':'上传成功!', + 'delSuccessFile':'从成功队列中移除', + 'delFailSaveFile':'移除保存失败文件', + 'statusPrompt':' 个文件已上传! ', + 'flashVersionError':'当前Flash版本过低,请更新FlashPlayer后重试!', + 'flashLoadingError':'Flash加载失败!请检查路径或网络状态', + 'fileUploadReady':'等待上传……', + 'delUploadQueue':'从上传队列中移除', + 'limitPrompt1':'单次不能选择超过', + 'limitPrompt2':'个文件!请重新选择!', + 'delFailFile':'移除失败文件', + 'fileSizeLimit':'文件大小超出限制!', + 'emptyFile':'空文件无法上传!', + 'fileTypeError':'文件类型不允许!', + 'unknownError':'未知错误!', + 'fileUploading':'上传中,请等待……', + 'cancelUpload':'取消上传', + 'netError':'网络错误', + 'failUpload':'上传失败!', + 'serverIOError':'服务器IO错误!', + 'noAuthority':'无权限!', + 'fileNumLimit':'上传个数限制', + 'failCheck':'验证失败,本次上传被跳过!', + 'fileCanceling':'取消中,请等待……', + 'stopUploading':'上传已停止……', + + 'uploadSelectFile':'点击选择文件', + 'uploadAddFile':'继续添加', + 'uploadStart':'开始上传', + 'uploadPause':'暂停上传', + 'uploadContinue':'继续上传', + 'uploadRetry':'重试上传', + 'uploadDelete':'删除', + 'uploadTurnLeft':'向左旋转', + 'uploadTurnRight':'向右旋转', + 'uploadPreview':'预览中', + 'updateStatusReady': '选中_个文件,共_KB。', + 'updateStatusConfirm': '成功上传_个,_个失败', + 'updateStatusFinish': '共_个(_KB),_个成功上传', + 'updateStatusError': ',_张上传失败。', + 'errorNotSupport': 'WebUploader 不支持您的浏览器!如果你使用的是IE浏览器,请尝试升级 flash 播放器。', + 'errorLoadConfig': '后端配置项没有正常加载,上传插件不能正常使用!', + 'errorExceedSize':'文件大小超出', + 'errorFileType':'文件格式不允许', + 'errorInterrupt':'文件传输中断', + 'errorUploadRetry':'上传失败,请重试', + 'errorHttp':'http请求错误', + 'errorServerUpload':'服务器返回出错' + }, + 'webapp':{ + 'tip1':"本功能由百度APP提供,如看到此页面,请各位站长首先申请百度APPKey!", + 'tip2':"申请完成之后请至ueditor.config.js中配置获得的appkey! ", + 'applyFor':"点此申请", + 'anthorApi':"百度API" + }, + 'template':{ + 'static':{ + 'lang_template_bkcolor':'背景颜色', + 'lang_template_clear' : '保留原有内容', + 'lang_template_select' : '选择模板' + }, + 'blank':"空白文档", + 'blog':"博客文章", + 'resume':"个人简历", + 'richText':"图文混排", + 'sciPapers':"科技论文" + + + }, + 'scrawl':{ + 'static':{ + 'lang_input_previousStep':"上一步", + 'lang_input_nextsStep':"下一步", + 'lang_input_clear':'清空', + 'lang_input_addPic':'添加背景', + 'lang_input_ScalePic':'缩放背景', + 'lang_input_removePic':'删除背景', + 'J_imgTxt':{title:'添加背景图片'} + }, + 'noScarwl':"尚未作画,白纸一张~", + 'scrawlUpLoading':"涂鸦上传中,别急哦~", + 'continueBtn':"继续", + 'imageError':"糟糕,图片读取失败了!", + 'backgroundUploading':'背景图片上传中,别急哦~' + }, + 'music':{ + 'static':{ + 'lang_input_tips':"输入歌手/歌曲/专辑,搜索您感兴趣的音乐!", + 'J_searchBtn':{value:'搜索歌曲'} + }, + 'emptyTxt':'未搜索到相关音乐结果,请换一个关键词试试。', + 'chapter':'歌曲', + 'singer':'歌手', + 'special':'专辑', + 'listenTest':'试听' + }, + 'anchor':{ + 'static':{ + 'lang_input_anchorName':'锚点名字:' + } + }, + 'charts':{ + 'static':{ + 'lang_data_source':'数据源:', + 'lang_chart_format': '图表格式:', + 'lang_data_align': '数据对齐方式', + 'lang_chart_align_same': '数据源与图表X轴Y轴一致', + 'lang_chart_align_reverse': '数据源与图表X轴Y轴相反', + 'lang_chart_title': '图表标题', + 'lang_chart_main_title': '主标题:', + 'lang_chart_sub_title': '子标题:', + 'lang_chart_x_title': 'X轴标题:', + 'lang_chart_y_title': 'Y轴标题:', + 'lang_chart_tip': '提示文字', + 'lang_cahrt_tip_prefix': '提示文字前缀:', + 'lang_cahrt_tip_description': '仅饼图有效, 当鼠标移动到饼图中相应的块上时,提示框内的文字的前缀', + 'lang_chart_data_unit': '数据单位', + 'lang_chart_data_unit_title': '单位:', + 'lang_chart_data_unit_description': '显示在每个数据点上的数据的单位, 比如: 温度的单位 ℃', + 'lang_chart_type': '图表类型:', + 'lang_prev_btn': '上一个', + 'lang_next_btn': '下一个' + } + }, + 'emotion':{ + 'static':{ + 'lang_input_choice':'精选', + 'lang_input_Tuzki':'兔斯基', + 'lang_input_BOBO':'BOBO', + 'lang_input_lvdouwa':'绿豆蛙', + 'lang_input_babyCat':'baby猫', + 'lang_input_bubble':'泡泡', + 'lang_input_youa':'有啊' + } + }, + 'gmap':{ + 'static':{ + 'lang_input_address':'地址', + 'lang_input_search':'搜索', + 'address':{value:"北京"} + }, + searchError:'无法定位到该地址!' + }, + 'help':{ + 'static':{ + 'lang_input_about':'关于UEditor', + 'lang_input_shortcuts':'快捷键', + 'lang_input_introduction':'UEditor是由百度web前端研发部开发的所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点。开源基于BSD协议,允许自由使用和修改代码。', + 'lang_Txt_shortcuts':'快捷键', + 'lang_Txt_func':'功能', + 'lang_Txt_bold':'给选中字设置为加粗', + 'lang_Txt_copy':'复制选中内容', + 'lang_Txt_cut':'剪切选中内容', + 'lang_Txt_Paste':'粘贴', + 'lang_Txt_undo':'重新执行上次操作', + 'lang_Txt_redo':'撤销上一次操作', + 'lang_Txt_italic':'给选中字设置为斜体', + 'lang_Txt_underline':'给选中字加下划线', + 'lang_Txt_selectAll':'全部选中', + 'lang_Txt_visualEnter':'软回车', + 'lang_Txt_fullscreen':'全屏' + } + }, + 'insertframe':{ + 'static':{ + 'lang_input_address':'地址:', + 'lang_input_width':'宽度:', + 'lang_input_height':'高度:', + 'lang_input_isScroll':'允许滚动条:', + 'lang_input_frameborder':'显示框架边框:', + 'lang_input_alignMode':'对齐方式:', + 'align':{title:"对齐方式", options:["默认", "左对齐", "右对齐", "居中"]} + }, + 'enterAddress':'请输入地址!' + }, + 'link':{ + 'static':{ + 'lang_input_text':'文本内容:', + 'lang_input_url':'链接地址:', + 'lang_input_title':'标题:', + 'lang_input_target':'是否在新窗口打开:' + }, + 'validLink':'只支持选中一个链接时生效', + 'httpPrompt':'您输入的超链接中不包含http等协议名称,默认将为您添加http://前缀' + }, + 'map':{ + 'static':{ + lang_city:"城市", + lang_address:"地址", + city:{value:"北京"}, + lang_search:"搜索", + lang_dynamicmap:"插入动态地图" + }, + cityMsg:"请选择城市", + errorMsg:"抱歉,找不到该位置!" + }, + 'searchreplace':{ + 'static':{ + lang_tab_search:"查找", + lang_tab_replace:"替换", + lang_search1:"查找", + lang_search2:"查找", + lang_replace:"替换", + lang_searchReg:'支持正则表达式,添加前后斜杠标示为正则表达式,例如“/表达式/”', + lang_searchReg1:'支持正则表达式,添加前后斜杠标示为正则表达式,例如“/表达式/”', + lang_case_sensitive1:"区分大小写", + lang_case_sensitive2:"区分大小写", + nextFindBtn:{value:"下一个"}, + preFindBtn:{value:"上一个"}, + nextReplaceBtn:{value:"下一个"}, + preReplaceBtn:{value:"上一个"}, + repalceBtn:{value:"替换"}, + repalceAllBtn:{value:"全部替换"} + }, + getEnd:"已经搜索到文章末尾!", + getStart:"已经搜索到文章头部", + countMsg:"总共替换了{#count}处!" + }, + 'snapscreen':{ + 'static':{ + lang_showMsg:"截图功能需要首先安装UEditor截图插件! ", + lang_download:"点此下载", + lang_step1:"第一步,下载UEditor截图插件并运行安装。", + lang_step2:"第二步,插件安装完成后即可使用,如不生效,请重启浏览器后再试!" + } + }, + 'spechars':{ + 'static':{}, + tsfh:"特殊字符", + lmsz:"罗马字符", + szfh:"数学字符", + rwfh:"日文字符", + xlzm:"希腊字母", + ewzm:"俄文字符", + pyzm:"拼音字母", + yyyb:"英语音标", + zyzf:"其他" + }, + 'edittable':{ + 'static':{ + 'lang_tableStyle':'表格样式', + 'lang_insertCaption':'添加表格名称行', + 'lang_insertTitle':'添加表格标题行', + 'lang_insertTitleCol':'添加表格标题列', + 'lang_orderbycontent':"使表格内容可排序", + 'lang_tableSize':'自动调整表格尺寸', + 'lang_autoSizeContent':'按表格文字自适应', + 'lang_autoSizePage':'按页面宽度自适应', + 'lang_example':'示例', + 'lang_borderStyle':'表格边框', + 'lang_color':'颜色:' + }, + captionName:'表格名称', + titleName:'标题', + cellsName:'内容', + errorMsg:'有合并单元格,不可排序' + }, + 'edittip':{ + 'static':{ + lang_delRow:'删除整行', + lang_delCol:'删除整列' + } + }, + 'edittd':{ + 'static':{ + lang_tdBkColor:'背景颜色:' + } + }, + 'formula':{ + 'static':{ + } + }, + 'wordimage':{ + 'static':{ + lang_resave:"转存步骤", + uploadBtn:{src:"upload.png",alt:"上传"}, + clipboard:{style:"background: url(copy.png) -153px -1px no-repeat;"}, + lang_step:"1、点击顶部复制按钮,将地址复制到剪贴板;2、点击添加照片按钮,在弹出的对话框中使用Ctrl+V粘贴地址;3、点击打开后选择图片上传流程。" + }, + 'fileType':"图片", + 'flashError':"FLASH初始化失败,请检查FLASH插件是否正确安装!", + 'netError':"网络连接错误,请重试!", + 'copySuccess':"图片地址已经复制!", + 'flashI18n':{} //留空默认中文 + }, + 'autosave': { + 'saving':'保存中...', + 'success':'本地保存成功' + } +}; diff --git a/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/Config.cs b/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/Config.cs new file mode 100644 index 000000000..91c130f76 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/Config.cs @@ -0,0 +1,55 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.IO; +using System.Linq; +using System.Web; + +/// +/// Config 的摘要说明 +/// +public static class Config +{ + private static bool noCache = true; + private static JObject BuildItems() + { + var json = File.ReadAllText(HttpContext.Current.Server.MapPath("config.json")); + return JObject.Parse(json); + } + + public static JObject Items + { + get + { + if (noCache || _Items == null) + { + _Items = BuildItems(); + } + return _Items; + } + } + private static JObject _Items; + + + public static T GetValue(string key) + { + return Items[key].Value(); + } + + public static String[] GetStringList(string key) + { + return Items[key].Select(x => x.Value()).ToArray(); + } + + public static String GetString(string key) + { + return GetValue(key); + } + + public static int GetInt(string key) + { + return GetValue(key); + } +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/ConfigHandler.cs b/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/ConfigHandler.cs new file mode 100644 index 000000000..03cdc9a42 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/ConfigHandler.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +/// +/// Config 的摘要说明 +/// +public class ConfigHandler : Handler +{ + public ConfigHandler(HttpContext context) : base(context) { } + + public override void Process() + { + WriteJson(Config.Items); + } +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/CrawlerHandler.cs b/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/CrawlerHandler.cs new file mode 100644 index 000000000..2fdf94088 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/CrawlerHandler.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Web; + +/// +/// Crawler 的摘要说明 +/// +public class CrawlerHandler : Handler +{ + private string[] Sources; + private Crawler[] Crawlers; + public CrawlerHandler(HttpContext context) : base(context) { } + + public override void Process() + { + Sources = Request.Form.GetValues("source[]"); + if (Sources == null || Sources.Length == 0) + { + WriteJson(new + { + state = "参数错误:没有指定抓取源" + }); + return; + } + Crawlers = Sources.Select(x => new Crawler(x, Server).Fetch()).ToArray(); + WriteJson(new + { + state = "SUCCESS", + list = Crawlers.Select(x => new + { + state = x.State, + source = x.SourceUrl, + url = x.ServerUrl + }) + }); + } +} + +public class Crawler +{ + public string SourceUrl { get; set; } + public string ServerUrl { get; set; } + public string State { get; set; } + + private HttpServerUtility Server { get; set; } + + + public Crawler(string sourceUrl, HttpServerUtility server) + { + this.SourceUrl = sourceUrl; + this.Server = server; + } + + public Crawler Fetch() + { + if (!IsExternalIPAddress(this.SourceUrl)) + { + State = "INVALID_URL"; + return this; + } + var request = HttpWebRequest.Create(this.SourceUrl) as HttpWebRequest; + using (var response = request.GetResponse() as HttpWebResponse) + { + if (response.StatusCode != HttpStatusCode.OK) + { + State = "Url returns " + response.StatusCode + ", " + response.StatusDescription; + return this; + } + if (response.ContentType.IndexOf("image") == -1) + { + State = "Url is not an image"; + return this; + } + ServerUrl = PathFormatter.Format(Path.GetFileName(this.SourceUrl), Config.GetString("catcherPathFormat")); + var savePath = Server.MapPath(ServerUrl); + if (!Directory.Exists(Path.GetDirectoryName(savePath))) + { + Directory.CreateDirectory(Path.GetDirectoryName(savePath)); + } + try + { + var stream = response.GetResponseStream(); + var reader = new BinaryReader(stream); + byte[] bytes; + using (var ms = new MemoryStream()) + { + byte[] buffer = new byte[4096]; + int count; + while ((count = reader.Read(buffer, 0, buffer.Length)) != 0) + { + ms.Write(buffer, 0, count); + } + bytes = ms.ToArray(); + } + File.WriteAllBytes(savePath, bytes); + State = "SUCCESS"; + } + catch (Exception e) + { + State = "抓取错误:" + e.Message; + } + return this; + } + } + + private bool IsExternalIPAddress(string url) + { + var uri = new Uri(url); + switch (uri.HostNameType) + { + case UriHostNameType.Dns: + var ipHostEntry = Dns.GetHostEntry(uri.DnsSafeHost); + foreach (IPAddress ipAddress in ipHostEntry.AddressList) + { + byte[] ipBytes = ipAddress.GetAddressBytes(); + if (ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) + { + if (!IsPrivateIP(ipAddress)) + { + return true; + } + } + } + break; + + case UriHostNameType.IPv4: + return !IsPrivateIP(IPAddress.Parse(uri.DnsSafeHost)); + } + return false; + } + + private bool IsPrivateIP(IPAddress myIPAddress) + { + if (IPAddress.IsLoopback(myIPAddress)) return true; + if (myIPAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) + { + byte[] ipBytes = myIPAddress.GetAddressBytes(); + // 10.0.0.0/24 + if (ipBytes[0] == 10) + { + return true; + } + // 172.16.0.0/16 + else if (ipBytes[0] == 172 && ipBytes[1] == 16) + { + return true; + } + // 192.168.0.0/16 + else if (ipBytes[0] == 192 && ipBytes[1] == 168) + { + return true; + } + // 169.254.0.0/16 + else if (ipBytes[0] == 169 && ipBytes[1] == 254) + { + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/Handler.cs b/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/Handler.cs new file mode 100644 index 000000000..4d20ed52e --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/Handler.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using Newtonsoft.Json; + + +/// +/// Handler 的摘要说明 +/// +public abstract class Handler +{ + public Handler(HttpContext context) + { + this.Request = context.Request; + this.Response = context.Response; + this.Context = context; + this.Server = context.Server; + } + + public abstract void Process(); + + protected void WriteJson(object response) + { + string jsonpCallback = Request["callback"], + json = JsonConvert.SerializeObject(response); + if (String.IsNullOrWhiteSpace(jsonpCallback)) + { + Response.AddHeader("Content-Type", "text/plain"); + Response.Write(json); + } + else + { + Response.AddHeader("Content-Type", "application/javascript"); + Response.Write(String.Format("{0}({1});", jsonpCallback, json)); + } + Response.End(); + } + + public HttpRequest Request { get; private set; } + public HttpResponse Response { get; private set; } + public HttpContext Context { get; private set; } + public HttpServerUtility Server { get; private set; } +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/ListFileHandler.cs b/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/ListFileHandler.cs new file mode 100644 index 000000000..2cfa22a18 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/ListFileHandler.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Web; + +/// +/// FileManager 的摘要说明 +/// +public class ListFileManager : Handler +{ + enum ResultState + { + Success, + InvalidParam, + AuthorizError, + IOError, + PathNotFound + } + + private int Start; + private int Size; + private int Total; + private ResultState State; + private String PathToList; + private String[] FileList; + private String[] SearchExtensions; + + public ListFileManager(HttpContext context, string pathToList, string[] searchExtensions) + : base(context) + { + this.SearchExtensions = searchExtensions.Select(x => x.ToLower()).ToArray(); + this.PathToList = pathToList; + } + + public override void Process() + { + try + { + Start = String.IsNullOrEmpty(Request["start"]) ? 0 : Convert.ToInt32(Request["start"]); + Size = String.IsNullOrEmpty(Request["size"]) ? Config.GetInt("imageManagerListSize") : Convert.ToInt32(Request["size"]); + } + catch (FormatException) + { + State = ResultState.InvalidParam; + WriteResult(); + return; + } + var buildingList = new List(); + try + { + var localPath = Server.MapPath(PathToList); + buildingList.AddRange(Directory.GetFiles(localPath, "*", SearchOption.AllDirectories) + .Where(x => SearchExtensions.Contains(Path.GetExtension(x).ToLower())) + .Select(x => PathToList + x.Substring(localPath.Length).Replace("\\", "/"))); + Total = buildingList.Count; + FileList = buildingList.OrderBy(x => x).Skip(Start).Take(Size).ToArray(); + } + catch (UnauthorizedAccessException) + { + State = ResultState.AuthorizError; + } + catch (DirectoryNotFoundException) + { + State = ResultState.PathNotFound; + } + catch (IOException) + { + State = ResultState.IOError; + } + finally + { + WriteResult(); + } + } + + private void WriteResult() + { + WriteJson(new + { + state = GetStateString(), + list = FileList == null ? null : FileList.Select(x => new { url = x }), + start = Start, + size = Size, + total = Total + }); + } + + private string GetStateString() + { + switch (State) + { + case ResultState.Success: + return "SUCCESS"; + case ResultState.InvalidParam: + return "参数不正确"; + case ResultState.PathNotFound: + return "路径不存在"; + case ResultState.AuthorizError: + return "文件系统权限不足"; + case ResultState.IOError: + return "文件系统读取错误"; + } + return "未知错误"; + } +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/NotSupportedHandler.cs b/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/NotSupportedHandler.cs new file mode 100644 index 000000000..d9d73230d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/NotSupportedHandler.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +/// +/// NotSupportedHandler 的摘要说明 +/// +public class NotSupportedHandler : Handler +{ + public NotSupportedHandler(HttpContext context) + : base(context) + { + } + + public override void Process() + { + WriteJson(new + { + state = "action 参数为空或者 action 不被支持。" + }); + } +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/PathFormater.cs b/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/PathFormater.cs new file mode 100644 index 000000000..e6fbfd471 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/PathFormater.cs @@ -0,0 +1,50 @@ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Web; + +/// +/// PathFormater 的摘要说明 +/// +public static class PathFormatter +{ + public static string Format(string originFileName, string pathFormat) + { + if (String.IsNullOrWhiteSpace(pathFormat)) + { + pathFormat = "{filename}{rand:6}"; + } + + var invalidPattern = new Regex(@"[\\\/\:\*\?\042\<\>\|]"); + originFileName = invalidPattern.Replace(originFileName, ""); + + string extension = Path.GetExtension(originFileName); + string filename = Path.GetFileNameWithoutExtension(originFileName); + + pathFormat = pathFormat.Replace("{filename}", filename); + pathFormat = new Regex(@"\{rand(\:?)(\d+)\}", RegexOptions.Compiled).Replace(pathFormat, new MatchEvaluator(delegate(Match match) + { + var digit = 6; + if (match.Groups.Count > 2) + { + digit = Convert.ToInt32(match.Groups[2].Value); + } + var rand = new Random(); + return rand.Next((int)Math.Pow(10, digit), (int)Math.Pow(10, digit + 1)).ToString(); + })); + + pathFormat = pathFormat.Replace("{time}", DateTime.Now.Ticks.ToString()); + pathFormat = pathFormat.Replace("{yyyy}", DateTime.Now.Year.ToString()); + pathFormat = pathFormat.Replace("{yy}", (DateTime.Now.Year % 100).ToString("D2")); + pathFormat = pathFormat.Replace("{mm}", DateTime.Now.Month.ToString("D2")); + pathFormat = pathFormat.Replace("{dd}", DateTime.Now.Day.ToString("D2")); + pathFormat = pathFormat.Replace("{hh}", DateTime.Now.Hour.ToString("D2")); + pathFormat = pathFormat.Replace("{ii}", DateTime.Now.Minute.ToString("D2")); + pathFormat = pathFormat.Replace("{ss}", DateTime.Now.Second.ToString("D2")); + + return pathFormat + extension; + } +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/UploadHandler.cs b/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/UploadHandler.cs new file mode 100644 index 000000000..ea45e79c2 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/net/App_Code/UploadHandler.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Web; + +/// +/// UploadHandler 的摘要说明 +/// +public class UploadHandler : Handler +{ + + public UploadConfig UploadConfig { get; private set; } + public UploadResult Result { get; private set; } + + public UploadHandler(HttpContext context, UploadConfig config) + : base(context) + { + this.UploadConfig = config; + this.Result = new UploadResult() { State = UploadState.Unknown }; + } + + public override void Process() + { + byte[] uploadFileBytes = null; + string uploadFileName = null; + + if (UploadConfig.Base64) + { + uploadFileName = UploadConfig.Base64Filename; + uploadFileBytes = Convert.FromBase64String(Request[UploadConfig.UploadFieldName]); + } + else + { + var file = Request.Files[UploadConfig.UploadFieldName]; + uploadFileName = file.FileName; + + if (!CheckFileType(uploadFileName)) + { + Result.State = UploadState.TypeNotAllow; + WriteResult(); + return; + } + if (!CheckFileSize(file.ContentLength)) + { + Result.State = UploadState.SizeLimitExceed; + WriteResult(); + return; + } + + uploadFileBytes = new byte[file.ContentLength]; + try + { + file.InputStream.Read(uploadFileBytes, 0, file.ContentLength); + } + catch (Exception) + { + Result.State = UploadState.NetworkError; + WriteResult(); + } + } + + Result.OriginFileName = uploadFileName; + + var savePath = PathFormatter.Format(uploadFileName, UploadConfig.PathFormat); + var localPath = Server.MapPath(savePath); + try + { + if (!Directory.Exists(Path.GetDirectoryName(localPath))) + { + Directory.CreateDirectory(Path.GetDirectoryName(localPath)); + } + File.WriteAllBytes(localPath, uploadFileBytes); + Result.Url = savePath; + Result.State = UploadState.Success; + } + catch (Exception e) + { + Result.State = UploadState.FileAccessError; + Result.ErrorMessage = e.Message; + } + finally + { + WriteResult(); + } + } + + private void WriteResult() + { + this.WriteJson(new + { + state = GetStateMessage(Result.State), + url = Result.Url, + title = Result.OriginFileName, + original = Result.OriginFileName, + error = Result.ErrorMessage + }); + } + + private string GetStateMessage(UploadState state) + { + switch (state) + { + case UploadState.Success: + return "SUCCESS"; + case UploadState.FileAccessError: + return "文件访问出错,请检查写入权限"; + case UploadState.SizeLimitExceed: + return "文件大小超出服务器限制"; + case UploadState.TypeNotAllow: + return "不允许的文件格式"; + case UploadState.NetworkError: + return "网络错误"; + } + return "未知错误"; + } + + private bool CheckFileType(string filename) + { + var fileExtension = Path.GetExtension(filename).ToLower(); + return UploadConfig.AllowExtensions.Select(x => x.ToLower()).Contains(fileExtension); + } + + private bool CheckFileSize(int size) + { + return size < UploadConfig.SizeLimit; + } +} + +public class UploadConfig +{ + /// + /// 文件命名规则 + /// + public string PathFormat { get; set; } + + /// + /// 上传表单域名称 + /// + public string UploadFieldName { get; set; } + + /// + /// 上传大小限制 + /// + public int SizeLimit { get; set; } + + /// + /// 上传允许的文件格式 + /// + public string[] AllowExtensions { get; set; } + + /// + /// 文件是否以 Base64 的形式上传 + /// + public bool Base64 { get; set; } + + /// + /// Base64 字符串所表示的文件名 + /// + public string Base64Filename { get; set; } +} + +public class UploadResult +{ + public UploadState State { get; set; } + public string Url { get; set; } + public string OriginFileName { get; set; } + + public string ErrorMessage { get; set; } +} + +public enum UploadState +{ + Success = 0, + SizeLimitExceed = -1, + TypeNotAllow = -2, + FileAccessError = -3, + NetworkError = -4, + Unknown = 1, +} + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/net/README.md b/nezha-fronted/static/ueditor-1.4.3.3/net/README.md new file mode 100644 index 000000000..b7c7ddd50 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/net/README.md @@ -0,0 +1,141 @@ +UEditor ASP.NET 后台使用说明 +===== + +## 背景 + +UEditor 在 1.4 版本之后进行了一次[前后端统一配置](../_doc/3.1 后端请求规范.md)的整理,.Net 的后台也进行了一次重写,跟之前的版本差别较大,升级的用户注意阅读本文档。 + +本文档介绍 UEditor ASP.NET 后台的部署、配置、源码说明。 + + +## 1. 部署说明 + +### 1.1. 安装并注册 .NET Framework 4.0 + +代码的运行时环境是 .NET Framework 4.0,首先要确认 IIS 已经安装了 .NET 4.0 的运行时框架。方法是打开「IIS 管理器」,选择根目录下的「应用程序池」,在右侧查看是否有一个应用程序池的版本是 v4.0,如果存在,则 IIS 已经安装了所需的运行时环境,此时读者可以跳过本节。 + +![检查 .NET 4.0 安装情况](../_doc/images/net-publish-1.png) + +如果没有找到对应的应用程序池,需要手动安装。 + +Windows 7 和 Windows Server 2008 R2 默认安装了 .Net Framework 4.0,如果是 Server 03 和老掉牙的 Windows XP,则需要手动安装 [.NET Framework 4.0](http://www.microsoft.com/zh-cn/download/details.aspx?id=17718)。 + +安装完 .NET Framework 4.0 后,还需要向 IIS 注册应用程序池,注册的方法是,使用**管理员权限**打开命令提示符(CMD),输入以下命令: + +```shell +C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis -i +``` + +安装完毕后,在 IIS 管理器刷新就能看到 4.0 的应用程序池。 + +### 1.2. 设置 .NET 应用程序 + +代码要求以应用程序的形式来运行(可以方便加入库依赖和组织代码)。需要把 `net` 目录转换为应用程序。 + +1. 在 IIS 中,展开到 `ueditor/net` 目录,在目录上右击,点击「转换为应用程序」。 + + ![转换为应用程序](../_doc/images/net-publish-2.png) + +2. 弹出的对话框中,点击「选择...」来指定使用的应用程序池。选择版本为 4.0 的应用程序池,然后点确定。 + + ![选择应用程序池](../_doc/images/net-publish-3.png) + +3. 设置连接凭据。点击「链接为...」按钮,在弹出的对话框中指定一个对目录具有读写权限的用户(如 administrator),然后点确定。 + + ![设置连接凭据](../_doc/images/net-publish-4.png) + + 设置完毕后,可以点击「测试设置...」来测试权限是否正常。 + + ![设置连接凭据](../_doc/images/net-publish-5.png) + +### 1.3. 运行测试 + +在浏览器中运行 `net/controller.ashx`,如果返回 "`{"state":"action 参数为空或者 action 不被支持。"}`",则表示应用程序运行成功。 + +如果你确认上述步骤已经执行,但是依然有问题,请给我们[提 Issue](https://github.com/fex-team/ueditor/issues/new?labels=NET%E5%90%8E%E5%8F%B0),我们会尽快答复解决。 + +## 2. 配置说明 + +前后端配置统一之后,配置文件由后台读取,返回给前端。但是部分配置是给后台使用的。 + +### 2.1. 上传配置说明 + +关于上传的部分,后台需要关心以下模板的配置项。 + +```json +{ + "{tpl}FieldName": "upfile", + "{tpl}PathFormat": "upload/{tpl}/{yyyy}{mm}{dd}/{time}{rand:6}", + "{tpl}UrlPrefix": "/ueditor/net/", + "{tpl}AllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], + "{tpl}MaxSize": 2048000 +} +``` + +"{tpl}FieldName" 表示提交的表单的文件域名称。 + +"{tpl}PathFormat" 表示上传文件保存的路径和名称。注意,这里的路径是相对应用程序的,如果需要修改的话,请自行修改源码。 + +"{tpl}UrlPrefix" 表示上传文件访问的 URL 前缀。注意,这里应该给出应用程序的 URL 路径,否则上传的文件不能正确定位。 + +> 举个例子,如果你的 UEditor 的位置在 `http://www.mydomain.com/myapp/ueditor`,对应的本地路径是 `C:\iis_pub\www\myapp\ueditor`,那么 .NET 应用程序的位置在 `http://www.mydomain.com/myapp/ueditor/net`,对应的本地路径是 `C:\iis_pub\www\myapp\ueditor\net`。图片上传配置项应该如下: +> +> { +> "imagePathFormat": "upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", +> "imageUrlPrefix": "/myapp/ueditor/net/", +> } +> +> 上传的文件会保存在 `C:\iis_pub\www\myapp\ueditor\net\upload\image\{日期}\{文件名}` + +"{tpl}AllowFiles" 限制文件上传的类型,注意要有 "."。 + +"{tpl}MaxSize" 限制文件上传的大小。注意这里的限制是代码上的判断,应用程序本身还有一个请求报文大小限制。该限制在 web.config 文件中修改,注意要有以下的节: + +```xml + + + + + +``` + +maxRequestLength 就是请求报文大小限制,该大小应该要比设置的所有上传大小都大,否则应用程序执行之前,请求会被被拒绝。 + +## 3. 源码说明 + +可以看到 net 目录内的源码结构是这样的: + +``` +net + App_Code + Config.cs + Handler.cs + PathFormatter.cs + *Handler.cs + Bin + Newtonsoft.Json.dll + config.json + controller.ashx + net.sln + README.md + Web.config +``` + +App_Code 上的文件是应用程序的源码。 + +- Config.cs 负责读取配置文件 +- Handler.cs 是请求处理器的基类,提供了一些基本对象的访问以及输出控制。如果需要增加处理器,应该从该基类继承 +- PathFormatter.cs 解析 PathFormat,把信息填充为运行时信息。 +- *Handler.cs 是各种处理器,处理各种 UEditor 需要的请求。 + +Bin 里面的是应用程序的依赖库,当前依赖 Newtonsoft 的 Json 库。Bin 目录和 App_Code 目录受应用程序保护,不用担心被用户访问到。 + +config.json 是 UEditor 后端的配置文件,上一节已经介绍了比较重要的配置项。 + +controller.ashx 是 UEditor 请求的入口,它把不同的 action 分发到不同的 Handler 来处理。 + +net.sln 是项目的解决方案文件,安装 Visual Studio 2013 或以上的机器可以打开进行项目的改造。 + +README.md 是本说明文件。 + +Web.config 是应用程序的配置文件。 diff --git a/nezha-fronted/static/ueditor-1.4.3.3/net/Web.config b/nezha-fronted/static/ueditor-1.4.3.3/net/Web.config new file mode 100644 index 000000000..992ee5280 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/net/Web.config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/net/config.json b/nezha-fronted/static/ueditor-1.4.3.3/net/config.json new file mode 100644 index 000000000..55d948f22 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/net/config.json @@ -0,0 +1,94 @@ +/* 前后端通信相关的配置,注释只允许使用多行方式 */ +{ + /* 上传图片配置项 */ + "imageActionName": "uploadimage", /* 执行上传图片的action名称 */ + "imageFieldName": "upfile", /* 提交的图片表单名称 */ + "imageMaxSize": 2048000, /* 上传大小限制,单位B */ + "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */ + "imageCompressEnable": true, /* 是否压缩图片,默认是true */ + "imageCompressBorder": 1600, /* 图片压缩最长边限制 */ + "imageInsertAlign": "none", /* 插入的图片浮动方式 */ + "imageUrlPrefix": "/ueditor/net/", /* 图片访问路径前缀 */ + "imagePathFormat": "upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */ + /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */ + /* {time} 会替换成时间戳 */ + /* {yyyy} 会替换成四位年份 */ + /* {yy} 会替换成两位年份 */ + /* {mm} 会替换成两位月份 */ + /* {dd} 会替换成两位日期 */ + /* {hh} 会替换成两位小时 */ + /* {ii} 会替换成两位分钟 */ + /* {ss} 会替换成两位秒 */ + /* 非法字符 \ : * ? " < > | */ + /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */ + + /* 涂鸦图片上传配置项 */ + "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */ + "scrawlFieldName": "upfile", /* 提交的图片表单名称 */ + "scrawlPathFormat": "upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "scrawlMaxSize": 2048000, /* 上传大小限制,单位B */ + "scrawlUrlPrefix": "/ueditor/net/", /* 图片访问路径前缀 */ + "scrawlInsertAlign": "none", + + /* 截图工具上传 */ + "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */ + "snapscreenPathFormat": "upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "snapscreenUrlPrefix": "/ueditor/net/", /* 图片访问路径前缀 */ + "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */ + + /* 抓取远程图片配置 */ + "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"], + "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */ + "catcherFieldName": "source", /* 提交的图片列表表单名称 */ + "catcherPathFormat": "upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "catcherUrlPrefix": "/ueditor/net/", /* 图片访问路径前缀 */ + "catcherMaxSize": 2048000, /* 上传大小限制,单位B */ + "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */ + + /* 上传视频配置 */ + "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */ + "videoFieldName": "upfile", /* 提交的视频表单名称 */ + "videoPathFormat": "upload/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "videoUrlPrefix": "/ueditor/net/", /* 视频访问路径前缀 */ + "videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */ + "videoAllowFiles": [ + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */ + + /* 上传文件配置 */ + "fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */ + "fileFieldName": "upfile", /* 提交的文件表单名称 */ + "filePathFormat": "upload/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "fileUrlPrefix": "/ueditor/net/", /* 文件访问路径前缀 */ + "fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */ + "fileAllowFiles": [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ], /* 上传文件格式显示 */ + + /* 列出指定目录下的图片 */ + "imageManagerActionName": "listimage", /* 执行图片管理的action名称 */ + "imageManagerListPath": "upload/image", /* 指定要列出图片的目录 */ + "imageManagerListSize": 20, /* 每次列出文件数量 */ + "imageManagerUrlPrefix": "/ueditor/net/", /* 图片访问路径前缀 */ + "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */ + "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */ + + /* 列出指定目录下的文件 */ + "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */ + "fileManagerListPath": "upload/file", /* 指定要列出文件的目录 */ + "fileManagerUrlPrefix": "/ueditor/net/", /* 文件访问路径前缀 */ + "fileManagerListSize": 20, /* 每次列出文件数量 */ + "fileManagerAllowFiles": [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ] /* 列出的文件类型 */ + +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/net/controller.ashx b/nezha-fronted/static/ueditor-1.4.3.3/net/controller.ashx new file mode 100644 index 000000000..320714e9e --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/net/controller.ashx @@ -0,0 +1,80 @@ +<%@ WebHandler Language="C#" Class="UEditorHandler" %> + +using System; +using System.Web; +using System.IO; +using System.Collections; +using Newtonsoft.Json; + +public class UEditorHandler : IHttpHandler +{ + public void ProcessRequest(HttpContext context) + { + Handler action = null; + switch (context.Request["action"]) + { + case "config": + action = new ConfigHandler(context); + break; + case "uploadimage": + action = new UploadHandler(context, new UploadConfig() + { + AllowExtensions = Config.GetStringList("imageAllowFiles"), + PathFormat = Config.GetString("imagePathFormat"), + SizeLimit = Config.GetInt("imageMaxSize"), + UploadFieldName = Config.GetString("imageFieldName") + }); + break; + case "uploadscrawl": + action = new UploadHandler(context, new UploadConfig() + { + AllowExtensions = new string[] { ".png" }, + PathFormat = Config.GetString("scrawlPathFormat"), + SizeLimit = Config.GetInt("scrawlMaxSize"), + UploadFieldName = Config.GetString("scrawlFieldName"), + Base64 = true, + Base64Filename = "scrawl.png" + }); + break; + case "uploadvideo": + action = new UploadHandler(context, new UploadConfig() + { + AllowExtensions = Config.GetStringList("videoAllowFiles"), + PathFormat = Config.GetString("videoPathFormat"), + SizeLimit = Config.GetInt("videoMaxSize"), + UploadFieldName = Config.GetString("videoFieldName") + }); + break; + case "uploadfile": + action = new UploadHandler(context, new UploadConfig() + { + AllowExtensions = Config.GetStringList("fileAllowFiles"), + PathFormat = Config.GetString("filePathFormat"), + SizeLimit = Config.GetInt("fileMaxSize"), + UploadFieldName = Config.GetString("fileFieldName") + }); + break; + case "listimage": + action = new ListFileManager(context, Config.GetString("imageManagerListPath"), Config.GetStringList("imageManagerAllowFiles")); + break; + case "listfile": + action = new ListFileManager(context, Config.GetString("fileManagerListPath"), Config.GetStringList("fileManagerAllowFiles")); + break; + case "catchimage": + action = new CrawlerHandler(context); + break; + default: + action = new NotSupportedHandler(context); + break; + } + action.Process(); + } + + public bool IsReusable + { + get + { + return false; + } + } +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/package.json b/nezha-fronted/static/ueditor-1.4.3.3/package.json new file mode 100644 index 000000000..1988b1f39 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/package.json @@ -0,0 +1,36 @@ +{ + "name": "ueditor", + "title": "ueditor", + "description": "UEditor富文本web编辑器", + "version": "1.4.3", + "homepage": "http://ueditor.baidu.com/", + "author": { + "name": "f-cube @ FEX", + "url": "http://fex.baidu.com" + }, + "repository": { + "type": "git", + "url": "https://github.com/fex-team/ueditor.git" + }, + "keywords": [ + "ueditor", + "web editor", + "javascript" + ], + "bugs": { + "url": "https://github.com/fex-team/ueditor/issues" + }, + "dependencies": { + "grunt": "~0.4.1", + "grunt-contrib-concat": "~0.3.0", + "grunt-contrib-cssmin": "~0.6.0", + "grunt-contrib-uglify": "~1.0.1", + "grunt-contrib-copy": "~0.4.0", + "grunt-transcoding": "~0.1.1", + "grunt-text-replace": "~0.3.9", + "grunt-contrib-clean": "~0.5.0" + }, + "devDependencies": { + "grunt": "~0.4.1" + } +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/php/Uploader.class.php b/nezha-fronted/static/ueditor-1.4.3.3/php/Uploader.class.php new file mode 100644 index 000000000..b7d6bf8d5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/php/Uploader.class.php @@ -0,0 +1,372 @@ + "临时文件错误", + "ERROR_TMP_FILE_NOT_FOUND" => "找不到临时文件", + "ERROR_SIZE_EXCEED" => "文件大小超出网站限制", + "ERROR_TYPE_NOT_ALLOWED" => "文件类型不允许", + "ERROR_CREATE_DIR" => "目录创建失败", + "ERROR_DIR_NOT_WRITEABLE" => "目录没有写权限", + "ERROR_FILE_MOVE" => "文件保存时出错", + "ERROR_FILE_NOT_FOUND" => "找不到上传文件", + "ERROR_WRITE_CONTENT" => "写入文件内容错误", + "ERROR_UNKNOWN" => "未知错误", + "ERROR_DEAD_LINK" => "链接不可用", + "ERROR_HTTP_LINK" => "链接不是http链接", + "ERROR_HTTP_CONTENTTYPE" => "链接contentType不正确", + "INVALID_URL" => "非法 URL", + "INVALID_IP" => "非法 IP" + ); + + /** + * 构造函数 + * @param string $fileField 表单名称 + * @param array $config 配置项 + * @param bool $base64 是否解析base64编码,可省略。若开启,则$fileField代表的是base64编码的字符串表单名 + */ + public function __construct($fileField, $config, $type = "upload") + { + $this->fileField = $fileField; + $this->config = $config; + $this->type = $type; + if ($type == "remote") { + $this->saveRemote(); + } else if($type == "base64") { + $this->upBase64(); + } else { + $this->upFile(); + } + + $this->stateMap['ERROR_TYPE_NOT_ALLOWED'] = iconv('unicode', 'utf-8', $this->stateMap['ERROR_TYPE_NOT_ALLOWED']); + } + + /** + * 上传文件的主处理方法 + * @return mixed + */ + private function upFile() + { + $file = $this->file = $_FILES[$this->fileField]; + if (!$file) { + $this->stateInfo = $this->getStateInfo("ERROR_FILE_NOT_FOUND"); + return; + } + if ($this->file['error']) { + $this->stateInfo = $this->getStateInfo($file['error']); + return; + } else if (!file_exists($file['tmp_name'])) { + $this->stateInfo = $this->getStateInfo("ERROR_TMP_FILE_NOT_FOUND"); + return; + } else if (!is_uploaded_file($file['tmp_name'])) { + $this->stateInfo = $this->getStateInfo("ERROR_TMPFILE"); + return; + } + + $this->oriName = $file['name']; + $this->fileSize = $file['size']; + $this->fileType = $this->getFileExt(); + $this->fullName = $this->getFullName(); + $this->filePath = $this->getFilePath(); + $this->fileName = $this->getFileName(); + $dirname = dirname($this->filePath); + + //检查文件大小是否超出限制 + if (!$this->checkSize()) { + $this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED"); + return; + } + + //检查是否不允许的文件格式 + if (!$this->checkType()) { + $this->stateInfo = $this->getStateInfo("ERROR_TYPE_NOT_ALLOWED"); + return; + } + + //创建目录失败 + if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) { + $this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR"); + return; + } else if (!is_writeable($dirname)) { + $this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE"); + return; + } + + //移动文件 + if (!(move_uploaded_file($file["tmp_name"], $this->filePath) && file_exists($this->filePath))) { //移动失败 + $this->stateInfo = $this->getStateInfo("ERROR_FILE_MOVE"); + } else { //移动成功 + $this->stateInfo = $this->stateMap[0]; + } + } + + /** + * 处理base64编码的图片上传 + * @return mixed + */ + private function upBase64() + { + $base64Data = $_POST[$this->fileField]; + $img = base64_decode($base64Data); + + $this->oriName = $this->config['oriName']; + $this->fileSize = strlen($img); + $this->fileType = $this->getFileExt(); + $this->fullName = $this->getFullName(); + $this->filePath = $this->getFilePath(); + $this->fileName = $this->getFileName(); + $dirname = dirname($this->filePath); + + //检查文件大小是否超出限制 + if (!$this->checkSize()) { + $this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED"); + return; + } + + //创建目录失败 + if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) { + $this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR"); + return; + } else if (!is_writeable($dirname)) { + $this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE"); + return; + } + + //移动文件 + if (!(file_put_contents($this->filePath, $img) && file_exists($this->filePath))) { //移动失败 + $this->stateInfo = $this->getStateInfo("ERROR_WRITE_CONTENT"); + } else { //移动成功 + $this->stateInfo = $this->stateMap[0]; + } + + } + + /** + * 拉取远程图片 + * @return mixed + */ + private function saveRemote() + { + $imgUrl = htmlspecialchars($this->fileField); + $imgUrl = str_replace("&", "&", $imgUrl); + + //http开头验证 + if (strpos($imgUrl, "http") !== 0) { + $this->stateInfo = $this->getStateInfo("ERROR_HTTP_LINK"); + return; + } + + preg_match('/(^https*:\/\/[^:\/]+)/', $imgUrl, $matches); + $host_with_protocol = count($matches) > 1 ? $matches[1] : ''; + + // 判断是否是合法 url + if (!filter_var($host_with_protocol, FILTER_VALIDATE_URL)) { + $this->stateInfo = $this->getStateInfo("INVALID_URL"); + return; + } + + preg_match('/^https*:\/\/(.+)/', $host_with_protocol, $matches); + $host_without_protocol = count($matches) > 1 ? $matches[1] : ''; + + // 此时提取出来的可能是 ip 也有可能是域名,先获取 ip + $ip = gethostbyname($host_without_protocol); + // 判断是否是私有 ip + if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) { + $this->stateInfo = $this->getStateInfo("INVALID_IP"); + return; + } + + //获取请求头并检测死链 + $heads = get_headers($imgUrl, 1); + if (!(stristr($heads[0], "200") && stristr($heads[0], "OK"))) { + $this->stateInfo = $this->getStateInfo("ERROR_DEAD_LINK"); + return; + } + //格式验证(扩展名验证和Content-Type验证) + $fileType = strtolower(strrchr($imgUrl, '.')); + if (!in_array($fileType, $this->config['allowFiles']) || !isset($heads['Content-Type']) || !stristr($heads['Content-Type'], "image")) { + $this->stateInfo = $this->getStateInfo("ERROR_HTTP_CONTENTTYPE"); + return; + } + + //打开输出缓冲区并获取远程图片 + ob_start(); + $context = stream_context_create( + array('http' => array( + 'follow_location' => false // don't follow redirects + )) + ); + readfile($imgUrl, false, $context); + $img = ob_get_contents(); + ob_end_clean(); + preg_match("/[\/]([^\/]*)[\.]?[^\.\/]*$/", $imgUrl, $m); + + $this->oriName = $m ? $m[1]:""; + $this->fileSize = strlen($img); + $this->fileType = $this->getFileExt(); + $this->fullName = $this->getFullName(); + $this->filePath = $this->getFilePath(); + $this->fileName = $this->getFileName(); + $dirname = dirname($this->filePath); + + //检查文件大小是否超出限制 + if (!$this->checkSize()) { + $this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED"); + return; + } + + //创建目录失败 + if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) { + $this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR"); + return; + } else if (!is_writeable($dirname)) { + $this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE"); + return; + } + + //移动文件 + if (!(file_put_contents($this->filePath, $img) && file_exists($this->filePath))) { //移动失败 + $this->stateInfo = $this->getStateInfo("ERROR_WRITE_CONTENT"); + } else { //移动成功 + $this->stateInfo = $this->stateMap[0]; + } + + } + + /** + * 上传错误检查 + * @param $errCode + * @return string + */ + private function getStateInfo($errCode) + { + return !$this->stateMap[$errCode] ? $this->stateMap["ERROR_UNKNOWN"] : $this->stateMap[$errCode]; + } + + /** + * 获取文件扩展名 + * @return string + */ + private function getFileExt() + { + return strtolower(strrchr($this->oriName, '.')); + } + + /** + * 重命名文件 + * @return string + */ + private function getFullName() + { + //替换日期事件 + $t = time(); + $d = explode('-', date("Y-y-m-d-H-i-s")); + $format = $this->config["pathFormat"]; + $format = str_replace("{yyyy}", $d[0], $format); + $format = str_replace("{yy}", $d[1], $format); + $format = str_replace("{mm}", $d[2], $format); + $format = str_replace("{dd}", $d[3], $format); + $format = str_replace("{hh}", $d[4], $format); + $format = str_replace("{ii}", $d[5], $format); + $format = str_replace("{ss}", $d[6], $format); + $format = str_replace("{time}", $t, $format); + + //过滤文件名的非法自负,并替换文件名 + $oriName = substr($this->oriName, 0, strrpos($this->oriName, '.')); + $oriName = preg_replace("/[\|\?\"\<\>\/\*\\\\]+/", '', $oriName); + $format = str_replace("{filename}", $oriName, $format); + + //替换随机字符串 + $randNum = rand(1, 10000000000) . rand(1, 10000000000); + if (preg_match("/\{rand\:([\d]*)\}/i", $format, $matches)) { + $format = preg_replace("/\{rand\:[\d]*\}/i", substr($randNum, 0, $matches[1]), $format); + } + + $ext = $this->getFileExt(); + return $format . $ext; + } + + /** + * 获取文件名 + * @return string + */ + private function getFileName () { + return substr($this->filePath, strrpos($this->filePath, '/') + 1); + } + + /** + * 获取文件完整路径 + * @return string + */ + private function getFilePath() + { + $fullname = $this->fullName; + $rootPath = $_SERVER['DOCUMENT_ROOT']; + + if (substr($fullname, 0, 1) != '/') { + $fullname = '/' . $fullname; + } + + return $rootPath . $fullname; + } + + /** + * 文件类型检测 + * @return bool + */ + private function checkType() + { + return in_array($this->getFileExt(), $this->config["allowFiles"]); + } + + /** + * 文件大小检测 + * @return bool + */ + private function checkSize() + { + return $this->fileSize <= ($this->config["maxSize"]); + } + + /** + * 获取当前上传成功文件的各项信息 + * @return array + */ + public function getFileInfo() + { + return array( + "state" => $this->stateInfo, + "url" => $this->fullName, + "title" => $this->fileName, + "original" => $this->oriName, + "type" => $this->fileType, + "size" => $this->fileSize + ); + } + +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/php/action_crawler.php b/nezha-fronted/static/ueditor-1.4.3.3/php/action_crawler.php new file mode 100644 index 000000000..b9e18dfae --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/php/action_crawler.php @@ -0,0 +1,44 @@ + $CONFIG['catcherPathFormat'], + "maxSize" => $CONFIG['catcherMaxSize'], + "allowFiles" => $CONFIG['catcherAllowFiles'], + "oriName" => "remote.png" +); +$fieldName = $CONFIG['catcherFieldName']; + +/* 抓取远程图片 */ +$list = array(); +if (isset($_POST[$fieldName])) { + $source = $_POST[$fieldName]; +} else { + $source = $_GET[$fieldName]; +} +foreach ($source as $imgUrl) { + $item = new Uploader($imgUrl, $config, "remote"); + $info = $item->getFileInfo(); + array_push($list, array( + "state" => $info["state"], + "url" => $info["url"], + "size" => $info["size"], + "title" => htmlspecialchars($info["title"]), + "original" => htmlspecialchars($info["original"]), + "source" => htmlspecialchars($imgUrl) + )); +} + +/* 返回抓取数据 */ +return json_encode(array( + 'state'=> count($list) ? 'SUCCESS':'ERROR', + 'list'=> $list +)); \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/php/action_list.php b/nezha-fronted/static/ueditor-1.4.3.3/php/action_list.php new file mode 100644 index 000000000..bf9cd62c1 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/php/action_list.php @@ -0,0 +1,92 @@ + "no match file", + "list" => array(), + "start" => $start, + "total" => count($files) + )); +} + +/* 获取指定范围的列表 */ +$len = count($files); +for ($i = min($end, $len) - 1, $list = array(); $i < $len && $i >= 0 && $i >= $start; $i--){ + $list[] = $files[$i]; +} +//倒序 +//for ($i = $end, $list = array(); $i < $len && $i < $end; $i++){ +// $list[] = $files[$i]; +//} + +/* 返回数据 */ +$result = json_encode(array( + "state" => "SUCCESS", + "list" => $list, + "start" => $start, + "total" => count($files) +)); + +return $result; + + +/** + * 遍历获取目录下的指定类型的文件 + * @param $path + * @param array $files + * @return array + */ +function getfiles($path, $allowFiles, &$files = array()) +{ + if (!is_dir($path)) return null; + if(substr($path, strlen($path) - 1) != '/') $path .= '/'; + $handle = opendir($path); + while (false !== ($file = readdir($handle))) { + if ($file != '.' && $file != '..') { + $path2 = $path . $file; + if (is_dir($path2)) { + getfiles($path2, $allowFiles, $files); + } else { + if (preg_match("/\.(".$allowFiles.")$/i", $file)) { + $files[] = array( + 'url'=> substr($path2, strlen($_SERVER['DOCUMENT_ROOT'])), + 'mtime'=> filemtime($path2) + ); + } + } + } + } + return $files; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/php/action_upload.php b/nezha-fronted/static/ueditor-1.4.3.3/php/action_upload.php new file mode 100644 index 000000000..d55b6591a --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/php/action_upload.php @@ -0,0 +1,66 @@ + $CONFIG['imagePathFormat'], + "maxSize" => $CONFIG['imageMaxSize'], + "allowFiles" => $CONFIG['imageAllowFiles'] + ); + $fieldName = $CONFIG['imageFieldName']; + break; + case 'uploadscrawl': + $config = array( + "pathFormat" => $CONFIG['scrawlPathFormat'], + "maxSize" => $CONFIG['scrawlMaxSize'], + "allowFiles" => $CONFIG['scrawlAllowFiles'], + "oriName" => "scrawl.png" + ); + $fieldName = $CONFIG['scrawlFieldName']; + $base64 = "base64"; + break; + case 'uploadvideo': + $config = array( + "pathFormat" => $CONFIG['videoPathFormat'], + "maxSize" => $CONFIG['videoMaxSize'], + "allowFiles" => $CONFIG['videoAllowFiles'] + ); + $fieldName = $CONFIG['videoFieldName']; + break; + case 'uploadfile': + default: + $config = array( + "pathFormat" => $CONFIG['filePathFormat'], + "maxSize" => $CONFIG['fileMaxSize'], + "allowFiles" => $CONFIG['fileAllowFiles'] + ); + $fieldName = $CONFIG['fileFieldName']; + break; +} + +/* 生成上传实例对象并完成上传 */ +$up = new Uploader($fieldName, $config, $base64); + +/** + * 得到上传文件所对应的各个参数,数组结构 + * array( + * "state" => "", //上传状态,上传成功时必须返回"SUCCESS" + * "url" => "", //返回的地址 + * "title" => "", //新文件名 + * "original" => "", //原始文件名 + * "type" => "" //文件类型 + * "size" => "", //文件大小 + * ) + */ + +/* 返回数据 */ +return json_encode($up->getFileInfo()); diff --git a/nezha-fronted/static/ueditor-1.4.3.3/php/config.json b/nezha-fronted/static/ueditor-1.4.3.3/php/config.json new file mode 100644 index 000000000..dd5bc1743 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/php/config.json @@ -0,0 +1,94 @@ +/* 前后端通信相关的配置,注释只允许使用多行方式 */ +{ + /* 上传图片配置项 */ + "imageActionName": "uploadimage", /* 执行上传图片的action名称 */ + "imageFieldName": "upfile", /* 提交的图片表单名称 */ + "imageMaxSize": 2048000, /* 上传大小限制,单位B */ + "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */ + "imageCompressEnable": true, /* 是否压缩图片,默认是true */ + "imageCompressBorder": 1600, /* 图片压缩最长边限制 */ + "imageInsertAlign": "none", /* 插入的图片浮动方式 */ + "imageUrlPrefix": "", /* 图片访问路径前缀 */ + "imagePathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */ + /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */ + /* {time} 会替换成时间戳 */ + /* {yyyy} 会替换成四位年份 */ + /* {yy} 会替换成两位年份 */ + /* {mm} 会替换成两位月份 */ + /* {dd} 会替换成两位日期 */ + /* {hh} 会替换成两位小时 */ + /* {ii} 会替换成两位分钟 */ + /* {ss} 会替换成两位秒 */ + /* 非法字符 \ : * ? " < > | */ + /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */ + + /* 涂鸦图片上传配置项 */ + "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */ + "scrawlFieldName": "upfile", /* 提交的图片表单名称 */ + "scrawlPathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "scrawlMaxSize": 2048000, /* 上传大小限制,单位B */ + "scrawlUrlPrefix": "", /* 图片访问路径前缀 */ + "scrawlInsertAlign": "none", + + /* 截图工具上传 */ + "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */ + "snapscreenPathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "snapscreenUrlPrefix": "", /* 图片访问路径前缀 */ + "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */ + + /* 抓取远程图片配置 */ + "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"], + "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */ + "catcherFieldName": "source", /* 提交的图片列表表单名称 */ + "catcherPathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "catcherUrlPrefix": "", /* 图片访问路径前缀 */ + "catcherMaxSize": 2048000, /* 上传大小限制,单位B */ + "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */ + + /* 上传视频配置 */ + "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */ + "videoFieldName": "upfile", /* 提交的视频表单名称 */ + "videoPathFormat": "/ueditor/php/upload/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "videoUrlPrefix": "", /* 视频访问路径前缀 */ + "videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */ + "videoAllowFiles": [ + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */ + + /* 上传文件配置 */ + "fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */ + "fileFieldName": "upfile", /* 提交的文件表单名称 */ + "filePathFormat": "/ueditor/php/upload/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "fileUrlPrefix": "", /* 文件访问路径前缀 */ + "fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */ + "fileAllowFiles": [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ], /* 上传文件格式显示 */ + + /* 列出指定目录下的图片 */ + "imageManagerActionName": "listimage", /* 执行图片管理的action名称 */ + "imageManagerListPath": "/ueditor/php/upload/image/", /* 指定要列出图片的目录 */ + "imageManagerListSize": 20, /* 每次列出文件数量 */ + "imageManagerUrlPrefix": "", /* 图片访问路径前缀 */ + "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */ + "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */ + + /* 列出指定目录下的文件 */ + "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */ + "fileManagerListPath": "/ueditor/php/upload/file/", /* 指定要列出文件的目录 */ + "fileManagerUrlPrefix": "", /* 文件访问路径前缀 */ + "fileManagerListSize": 20, /* 每次列出文件数量 */ + "fileManagerAllowFiles": [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ] /* 列出的文件类型 */ + +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/php/controller.php b/nezha-fronted/static/ueditor-1.4.3.3/php/controller.php new file mode 100644 index 000000000..feac890ce --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/php/controller.php @@ -0,0 +1,59 @@ + '请求地址出错' + )); + break; +} + +/* 输出结果 */ +if (isset($_GET["callback"])) { + if (preg_match("/^[\w_]+$/", $_GET["callback"])) { + echo htmlspecialchars($_GET["callback"]) . '(' . $result . ')'; + } else { + echo json_encode(array( + 'state'=> 'callback参数不合法' + )); + } +} else { + echo $result; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/autotypesetpicker.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/autotypesetpicker.css new file mode 100644 index 000000000..72c4c76cd --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/autotypesetpicker.css @@ -0,0 +1,21 @@ +/*自动排版弹出菜单*/ +.edui-default .edui-autotypesetpicker .edui-autotypesetpicker-body { + font-size: 12px; + margin-bottom: 3px; + clear: both; +} + +.edui-default .edui-autotypesetpicker-body table { + border-collapse: separate; + border-spacing: 2px; +} + +.edui-default .edui-autotypesetpicker-body td { + font-size: 12px; + word-wrap:break-word; +} + +.edui-default .edui-autotypesetpicker-body td input { + margin: 3px 3px 3px 4px; + *margin: 1px 0 0 0; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/button.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/button.css new file mode 100644 index 000000000..722639fd2 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/button.css @@ -0,0 +1,42 @@ +/*普通按钮样式及状态*/ +.edui-default .edui-toolbar .edui-button .edui-icon, +.edui-default .edui-toolbar .edui-menubutton .edui-icon, +.edui-default .edui-toolbar .edui-splitbutton .edui-icon { + height: 20px !important; + width: 20px !important; + background-image: url(../images/icons.png); + background-image: url(../images/icons.gif) \9; +} + +.edui-default .edui-toolbar .edui-button .edui-button-wrap { + padding: 1px; + position: relative; +} + +.edui-default .edui-toolbar .edui-button .edui-state-hover .edui-button-wrap { + background-color: #fff5d4; + padding: 0; + border: 1px solid #dcac6c; +} + +.edui-default .edui-toolbar .edui-button .edui-state-checked .edui-button-wrap { + background-color: #ffe69f; + padding: 0; + border: 1px solid #dcac6c; + border-radius: 2px; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; +} + +.edui-default .edui-toolbar .edui-button .edui-state-active .edui-button-wrap { + background-color: #ffffff; + padding: 0; + border: 1px solid gray; +} +.edui-default .edui-toolbar .edui-state-disabled .edui-label { + color: #ccc; +} +.edui-default .edui-toolbar .edui-state-disabled .edui-icon { + opacity: 0.3; + filter: alpha(opacity = 30); +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/buttonicon.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/buttonicon.css new file mode 100644 index 000000000..ee086e9ab --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/buttonicon.css @@ -0,0 +1,419 @@ +/* toolbar icons */ +.edui-default .edui-for-undo .edui-icon { + background-position: -160px 0; +} + +.edui-default .edui-for-redo .edui-icon { + background-position: -100px 0; +} + +.edui-default .edui-for-bold .edui-icon { + background-position: 0 0; +} + +.edui-default .edui-for-italic .edui-icon { + background-position: -60px 0; +} + +.edui-default .edui-for-fontborder .edui-icon { + background-position:-160px -40px; +} +.edui-default .edui-for-underline .edui-icon { + background-position: -140px 0; +} + +.edui-default .edui-for-strikethrough .edui-icon { + background-position: -120px 0; +} + +.edui-default .edui-for-subscript .edui-icon { + background-position: -600px 0; +} + +.edui-default .edui-for-superscript .edui-icon { + background-position: -620px 0; +} + +.edui-default .edui-for-blockquote .edui-icon { + background-position: -220px 0; +} + +.edui-default .edui-for-forecolor .edui-icon { + background-position: -720px 0; +} + +.edui-default .edui-for-backcolor .edui-icon { + background-position: -760px 0; +} + +.edui-default .edui-for-inserttable .edui-icon { + background-position: -580px -20px; +} + +.edui-default .edui-for-autotypeset .edui-icon { + background-position: -640px -40px; +} + +.edui-default .edui-for-justifyleft .edui-icon { + background-position: -460px 0; +} + +.edui-default .edui-for-justifycenter .edui-icon { + background-position: -420px 0; +} + +.edui-default .edui-for-justifyright .edui-icon { + background-position: -480px 0; +} + +.edui-default .edui-for-justifyjustify .edui-icon { + background-position: -440px 0; +} + +.edui-default .edui-for-insertorderedlist .edui-icon { + background-position: -80px 0; +} + +.edui-default .edui-for-insertunorderedlist .edui-icon { + background-position: -20px 0; +} + +.edui-default .edui-for-lineheight .edui-icon { + background-position: -725px -40px; +} + +.edui-default .edui-for-rowspacingbottom .edui-icon { + background-position: -745px -40px; +} + +.edui-default .edui-for-rowspacingtop .edui-icon { + background-position: -765px -40px; +} + +.edui-default .edui-for-horizontal .edui-icon { + background-position: -360px 0; +} + +.edui-default .edui-for-link .edui-icon { + background-position: -500px 0; +} + +.edui-default .edui-for-code .edui-icon { + background-position: -440px -40px; +} + +.edui-default .edui-for-insertimage .edui-icon { + background-position: -726px -77px; +} + +.edui-default .edui-for-insertframe .edui-icon { + background-position: -240px -40px; +} + +.edui-default .edui-for-emoticon .edui-icon { + background-position: -60px -20px; +} + +.edui-default .edui-for-spechars .edui-icon { + background-position: -240px 0; +} + +.edui-default .edui-for-help .edui-icon { + background-position: -340px 0; +} + +.edui-default .edui-for-print .edui-icon { + background-position: -440px -20px; +} + +.edui-default .edui-for-preview .edui-icon { + background-position: -420px -20px; +} + +.edui-default .edui-for-selectall .edui-icon { + background-position: -400px -20px; +} + +.edui-default .edui-for-searchreplace .edui-icon { + background-position: -520px -20px; +} + +.edui-default .edui-for-map .edui-icon { + background-position: -40px -40px; +} + +.edui-default .edui-for-gmap .edui-icon { + background-position: -260px -40px; +} + +.edui-default .edui-for-insertvideo .edui-icon { + background-position: -320px -20px; +} + +.edui-default .edui-for-time .edui-icon { + background-position: -160px -20px; +} + +.edui-default .edui-for-date .edui-icon { + background-position: -140px -20px; +} + +.edui-default .edui-for-cut .edui-icon { + background-position: -680px 0; +} + +.edui-default .edui-for-copy .edui-icon { + background-position: -700px 0; +} + +.edui-default .edui-for-paste .edui-icon { + background-position: -560px 0; +} + +.edui-default .edui-for-formatmatch .edui-icon { + background-position: -40px 0; +} + +.edui-default .edui-for-pasteplain .edui-icon { + background-position: -360px -20px; +} + +.edui-default .edui-for-directionalityltr .edui-icon { + background-position: -20px -20px; +} + +.edui-default .edui-for-directionalityrtl .edui-icon { + background-position: -40px -20px; +} + +.edui-default .edui-for-source .edui-icon { + background-position: -261px -0px; +} + +.edui-default .edui-for-removeformat .edui-icon { + background-position: -580px 0; +} + +.edui-default .edui-for-unlink .edui-icon { + background-position: -640px 0; +} + +.edui-default .edui-for-touppercase .edui-icon { + background-position: -786px 0; +} + +.edui-default .edui-for-tolowercase .edui-icon { + background-position: -806px 0; +} + +.edui-default .edui-for-insertrow .edui-icon { + background-position: -478px -76px; +} + +.edui-default .edui-for-insertrownext .edui-icon { + background-position: -498px -76px; +} + +.edui-default .edui-for-insertcol .edui-icon { + background-position: -455px -76px; +} + +.edui-default .edui-for-insertcolnext .edui-icon { + background-position: -429px -76px; +} + +.edui-default .edui-for-mergeright .edui-icon { + background-position: -60px -40px; +} + +.edui-default .edui-for-mergedown .edui-icon { + background-position: -80px -40px; +} + +.edui-default .edui-for-splittorows .edui-icon { + background-position: -100px -40px; +} + +.edui-default .edui-for-splittocols .edui-icon { + background-position: -120px -40px; +} + +.edui-default .edui-for-insertparagraphbeforetable .edui-icon { + background-position: -140px -40px; +} + +.edui-default .edui-for-deleterow .edui-icon { + background-position: -660px -20px; +} + +.edui-default .edui-for-deletecol .edui-icon { + background-position: -640px -20px; +} + +.edui-default .edui-for-splittocells .edui-icon { + background-position: -800px -20px; +} + +.edui-default .edui-for-mergecells .edui-icon { + background-position: -760px -20px; +} + +.edui-default .edui-for-deletetable .edui-icon { + background-position: -620px -20px; +} + +.edui-default .edui-for-cleardoc .edui-icon { + background-position: -520px 0; +} + +.edui-default .edui-for-fullscreen .edui-icon { + background-position: -100px -20px; +} + +.edui-default .edui-for-anchor .edui-icon { + background-position: -200px 0; +} + +.edui-default .edui-for-pagebreak .edui-icon { + background-position: -460px -40px; +} + +.edui-default .edui-for-imagenone .edui-icon { + background-position: -480px -40px; +} + +.edui-default .edui-for-imageleft .edui-icon { + background-position: -500px -40px; +} + +.edui-default .edui-for-wordimage .edui-icon { + background-position: -660px -40px; +} + +.edui-default .edui-for-imageright .edui-icon { + background-position: -520px -40px; +} + +.edui-default .edui-for-imagecenter .edui-icon { + background-position: -540px -40px; +} + +.edui-default .edui-for-indent .edui-icon { + background-position: -400px 0; +} + +.edui-default .edui-for-outdent .edui-icon { + background-position: -540px 0; +} + +.edui-default .edui-for-webapp .edui-icon { + background-position: -601px -40px +} + +.edui-default .edui-for-table .edui-icon { + background-position: -580px -20px; +} + +.edui-default .edui-for-edittable .edui-icon { + background-position: -420px -40px; +} + +.edui-default .edui-for-template .edui-icon { + background-position: -339px -40px; +} + +.edui-default .edui-for-delete .edui-icon { + background-position: -360px -40px; +} + +.edui-default .edui-for-attachment .edui-icon { + background-position: -620px -40px; +} + +.edui-default .edui-for-edittd .edui-icon { + background-position: -700px -40px; +} + +.edui-default .edui-for-snapscreen .edui-icon { + background-position: -581px -40px +} + +.edui-default .edui-for-scrawl .edui-icon { + background-position: -801px -41px +} + +.edui-default .edui-for-background .edui-icon { + background-position: -680px -40px; +} + +.edui-default .edui-for-music .edui-icon { + background-position: -18px -40px +} + +.edui-default .edui-for-formula .edui-icon { + background-position: -200px -40px +} + +.edui-default .edui-for-aligntd .edui-icon { + background-position: -236px -76px; +} + +.edui-default .edui-for-insertparagraphtrue .edui-icon { + background-position: -625px -76px; +} + +.edui-default .edui-for-insertparagraph .edui-icon { + background-position: -602px -76px; +} + +.edui-default .edui-for-insertcaption .edui-icon { + background-position: -336px -76px; +} + +.edui-default .edui-for-deletecaption .edui-icon { + background-position: -362px -76px; +} + +.edui-default .edui-for-inserttitle .edui-icon { + background-position: -286px -76px; +} + +.edui-default .edui-for-deletetitle .edui-icon { + background-position: -311px -76px; +} + +.edui-default .edui-for-aligntable .edui-icon { + background-position: -440px 0; +} + +.edui-default .edui-for-tablealignment-left .edui-icon { + background-position: -460px 0; +} + +.edui-default .edui-for-tablealignment-center .edui-icon { + background-position: -420px 0; +} + +.edui-default .edui-for-tablealignment-right .edui-icon { + background-position: -480px 0; +} + +.edui-default .edui-for-drafts .edui-icon { + background-position: -560px 0; +} + +.edui-default .edui-for-charts .edui-icon { + background: url( ../images/charts.png ) no-repeat 2px 3px!important; +} + +.edui-default .edui-for-inserttitlecol .edui-icon { + background-position: -673px -76px; +} + +.edui-default .edui-for-deletetitlecol .edui-icon { + background-position: -698px -76px; +} + +.edui-default .edui-for-simpleupload .edui-icon { + background-position: -380px 0px; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/cellalignpicker.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/cellalignpicker.css new file mode 100644 index 000000000..9f5aa5ca5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/cellalignpicker.css @@ -0,0 +1,56 @@ +/*自动排版弹出菜单*/ +.edui-default .edui-cellalignpicker .edui-cellalignpicker-body { + width: 70px; + font-size: 12px; + cursor: default; +} + +.edui-default .edui-cellalignpicker-body table { + border-collapse: separate; + border-spacing: 0; +} +.edui-default .edui-cellalignpicker-body td{ + padding: 1px; +} +.edui-default .edui-cellalignpicker-body .edui-icon{ + height: 20px; + width: 20px; + padding: 1px; + background-image: url(../images/table-cell-align.png); +} + +.edui-default .edui-cellalignpicker-body .edui-left{ + background-position: 0 0; +} + +.edui-default .edui-cellalignpicker-body .edui-center{ + background-position: -25px 0; +} +.edui-default .edui-cellalignpicker-body .edui-right{ + background-position: -51px 0; +} + +.edui-default .edui-cellalignpicker-body td.edui-state-hover .edui-left{ + background-position: -73px 0; +} + +.edui-default .edui-cellalignpicker-body td.edui-state-hover .edui-center{ + background-position: -98px 0; +} + +.edui-default .edui-cellalignpicker-body td.edui-state-hover .edui-right{ + background-position: -124px 0; +} + +.edui-default .edui-cellalignpicker-body td.edui-cellalign-selected .edui-left { + background-position: -146px 0; + background-color: #f1f4f5; +} + +.edui-default .edui-cellalignpicker-body td.edui-cellalign-selected .edui-center { + background-position: -245px 0; +} + +.edui-default .edui-cellalignpicker-body td.edui-cellalign-selected .edui-right { + background-position: -271px 0; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/colorbutton.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/colorbutton.css new file mode 100644 index 000000000..791c61d96 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/colorbutton.css @@ -0,0 +1,9 @@ +/*颜色按钮 */ +.edui-default .edui-toolbar .edui-colorbutton .edui-colorlump { + position: absolute; + overflow: hidden; + bottom: 1px; + left: 1px; + width: 18px; + height: 4px; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/colorpicker.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/colorpicker.css new file mode 100644 index 000000000..fae12192c --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/colorpicker.css @@ -0,0 +1,119 @@ +/* 颜色弹出菜单 */ +.edui-default .edui-colorpicker-topbar { + height: 27px; + width: 200px; + /*border-bottom: 1px gray dashed;*/ +} + +.edui-default .edui-colorpicker-preview { + height: 20px; + border: 1px inset black; + margin-left: 1px; + width: 128px; + float: left; +} + +.edui-default .edui-colorpicker-nocolor { + float: right; + margin-right: 1px; + font-size: 12px; + line-height: 14px; + height: 14px; + border: 1px solid #333; + padding: 3px 5px; + cursor: pointer; +} + +.edui-default .edui-colorpicker-tablefirstrow { + height: 30px; +} + +.edui-default .edui-colorpicker-colorcell { + width: 14px; + height: 14px; + display: block; + margin: 0; + cursor: pointer; +} + +.edui-default .edui-colorpicker-colorcell:hover { + width: 14px; + height: 14px; + margin: 0; +} +.edui-default .edui-colorpicker-advbtn{ + display: block; + text-align: center; + cursor: pointer; + height:20px; +} +.arrow_down{ + background: white url('../images/arrow_down.png') no-repeat center; +} +.arrow_up{ + background: white url('../images/arrow_up.png') no-repeat center; +} +/*高级的样式*/ +.edui-colorpicker-adv{ + position: relative; + overflow: hidden; + height: 180px; + display: none; +} +.edui-colorpicker-plant, .edui-colorpicker-hue { + border: solid 1px #666; +} +.edui-colorpicker-pad { + width: 150px; + height: 150px; + left: 14px; + top: 13px; + position: absolute; + background: red; + overflow: hidden; + cursor: crosshair; +} +.edui-colorpicker-cover{ + position: absolute; + top: 0; + left: 0; + width: 150px; + height: 150px; + background: url("../images/tangram-colorpicker.png") -160px -200px; +} +.edui-colorpicker-padDot{ + position: absolute; + top: 0; + left: 0; + width: 11px; + height: 11px; + overflow: hidden; + background: url(../images/tangram-colorpicker.png) 0px -200px repeat-x; + z-index: 1000; + +} +.edui-colorpicker-sliderMain { + position: absolute; + left: 171px; + top: 13px; + width: 19px; + height: 152px; + background: url(../images/tangram-colorpicker.png) -179px -12px no-repeat; + +} +.edui-colorpicker-slider { + width: 100%; + height: 100%; + cursor: pointer; +} +.edui-colorpicker-thumb{ + position: absolute; + top: 0; + cursor: pointer; + height: 3px; + left: -1px; + right: -1px; + border: 1px solid black; + background: white; + opacity: .8; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/combox.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/combox.css new file mode 100644 index 000000000..796c1c09d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/combox.css @@ -0,0 +1,62 @@ +/*不可选中菜单按钮 */ +.edui-default .edui-toolbar .edui-combox-body .edui-button-body { + width: 60px; + font-size: 12px; + height: 20px; + line-height: 20px; + padding-left: 5px; + white-space: nowrap; + margin: 0 3px 0 0; +} + +.edui-default .edui-toolbar .edui-combox-body .edui-arrow { + background: url(../images/icons.png) -741px 0; + _background: url(../images/icons.gif) -741px 0; + height: 20px; + width: 9px; +} + +.edui-default .edui-toolbar .edui-combox .edui-combox-body { + border: 1px solid #CCC; + background-color: white; + border-radius: 2px; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; +} + +.edui-default .edui-toolbar .edui-combox-body .edui-splitborder { + display: none; +} + +.edui-default .edui-toolbar .edui-combox-body .edui-arrow { + border-left: 1px solid #CCC; +} + +.edui-default .edui-toolbar .edui-state-hover .edui-combox-body { + background-color: #fff5d4; + border: 1px solid #dcac6c; +} + +.edui-default .edui-toolbar .edui-state-hover .edui-combox-body .edui-arrow { + border-left: 1px solid #dcac6c; +} + +.edui-default .edui-toolbar .edui-state-checked .edui-combox-body { + background-color: #FFE69F; + border: 1px solid #DCAC6C; +} + +.edui-toolbar .edui-state-checked .edui-combox-body .edui-arrow { + border-left: 1px solid #DCAC6C; +} + +.edui-toolbar .edui-state-disabled .edui-combox-body { + background-color: #F0F0EE; + opacity: 0.3; + filter: alpha(opacity = 30); +} + +.edui-toolbar .edui-state-opened .edui-combox-body { + background-color: white; + border: 1px solid gray; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/contextmenu.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/contextmenu.css new file mode 100644 index 000000000..366e653a5 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/contextmenu.css @@ -0,0 +1,29 @@ +/*contextmenu*/ +.edui-default .edui-hassubmenu .edui-arrow { + height: 20px; + width: 20px; + float: right; + background: url("../images/icons-all.gif") no-repeat 10px -233px; +} + +.edui-default .edui-menu-body .edui-menuitem { + padding: 1px; +} + +.edui-default .edui-menuseparator { + margin: 2px 0; + height: 1px; + overflow: hidden; +} + +.edui-default .edui-menuseparator-inner { + border-bottom: 1px solid #e2e3e3; + margin-left: 29px; + margin-right: 1px; +} + +.edui-default .edui-menu-body .edui-state-hover { + padding: 0 !important; + background-color: #fff5d4; + border: 1px solid #dcac6c; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/dialog.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/dialog.css new file mode 100644 index 000000000..42e9855b2 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/dialog.css @@ -0,0 +1,294 @@ +/* 弹出对话框按钮和对话框大小 */ +.edui-default .edui-dialog { + z-index: 2000; + position: absolute; + +} + +.edui-dialog div{ + width:auto; +} + +.edui-default .edui-dialog-wrap { + margin-right: 6px; + margin-bottom: 6px; +} + +.edui-default .edui-dialog-fullscreen-flag { + margin-right: 0; + margin-bottom: 0; +} + +.edui-default .edui-dialog-body { + position: relative; + padding:2px 0 0 2px; + _zoom: 1; +} + +.edui-default .edui-dialog-fullscreen-flag .edui-dialog-body { + padding: 0; +} + +.edui-default .edui-dialog-shadow { + position: absolute; + z-index: -1; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + *border-right-width: 2px; + *border-bottom-width: 2px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + +.edui-default .edui-dialog-foot { + background-color: white; +} + +.edui-default .edui-dialog-titlebar { + height: 26px; + border-bottom: 1px solid #c6c6c6; + background: url(../images/dialog-title-bg.png) repeat-x bottom; + position: relative; + cursor: move; +} +.edui-default .edui-dialog-caption { + font-weight: bold; + font-size: 12px; + line-height: 26px; + padding-left: 5px; +} + +.edui-default .edui-dialog-draghandle { + height: 26px; +} + +.edui-default .edui-dialog-closebutton { + position: absolute !important; + right: 5px; + top: 3px; +} + +.edui-default .edui-dialog-closebutton .edui-button-body { + height: 20px; + width: 20px; + cursor: pointer; + background: url("../images/icons-all.gif") no-repeat 0 -59px; +} + +.edui-default .edui-dialog-closebutton .edui-state-hover .edui-button-body { + background: url("../images/icons-all.gif") no-repeat 0 -89px; +} + +.edui-default .edui-dialog-foot { + height: 40px; +} + +.edui-default .edui-dialog-buttons { + position: absolute; + right: 0; +} + +.edui-default .edui-dialog-buttons .edui-button { + margin-right: 10px; +} + +.edui-default .edui-dialog-buttons .edui-button .edui-button-body { + background: url("../images/icons-all.gif") no-repeat; + height: 24px; + width: 96px; + font-size: 12px; + line-height: 24px; + text-align: center; + cursor: default; +} + +.edui-default .edui-dialog-buttons .edui-button .edui-state-hover .edui-button-body { + background: url("../images/icons-all.gif") no-repeat 0 -30px; +} + +.edui-default .edui-dialog iframe { + border: 0; + padding: 0; + margin: 0; + vertical-align: top; +} + +.edui-default .edui-dialog-modalmask { + opacity: 0.3; + filter: alpha(opacity = 30); + background-color: #ccc; + position: absolute; + /*z-index: 1999;*/ +} + +.edui-default .edui-dialog-dragmask { + position: absolute; + /*z-index: 2001;*/ + background-color: transparent; + cursor: move; +} + +.edui-default .edui-dialog-content { + position: relative; +} + +.edui-default .dialogcontmask { + cursor: move; + visibility: hidden; + display: block; + position: absolute; + width: 100%; + height: 100%; + opacity: 0; + filter: alpha(opacity = 0); +} + +/*link-dialog*/ +.edui-default .edui-for-link .edui-dialog-content { + width: 420px; + height: 200px; + overflow: hidden; +} +/*background-dialog*/ +.edui-default .edui-for-background .edui-dialog-content { + width: 440px; + height: 280px; + overflow: hidden; +} + +/*template-dialog*/ +.edui-default .edui-for-template .edui-dialog-content { + width: 630px; + height: 390px; + overflow: hidden; +} + +/*scrawl-dialog*/ +.edui-default .edui-for-scrawl .edui-dialog-content { + width: 515px; + *width: 506px; + height: 360px; +} + +/*spechars-dialog*/ +.edui-default .edui-for-spechars .edui-dialog-content { + width: 620px; + height: 500px; + *width: 630px; + *height: 570px; +} + +/*image-dialog*/ +.edui-default .edui-for-insertimage .edui-dialog-content { + width: 650px; + height: 400px; + overflow: hidden; +} +/*webapp-dialog*/ +.edui-default .edui-for-webapp .edui-dialog-content { + width: 560px; + _width: 565px; + height: 450px; + overflow: hidden; +} + +/*image-insertframe*/ +.edui-default .edui-for-insertframe .edui-dialog-content { + width: 350px; + height: 200px; + overflow: hidden; +} + +/*wordImage-dialog*/ +.edui-default .edui-for-wordimage .edui-dialog-content { + width: 620px; + height: 380px; + overflow: hidden; +} + +/*attachment-dialog*/ +.edui-default .edui-for-attachment .edui-dialog-content { + width: 650px; + height: 400px; + overflow: hidden; +} + + +/*map-dialog*/ +.edui-default .edui-for-map .edui-dialog-content { + width: 550px; + height: 400px; +} + +/*gmap-dialog*/ +.edui-default .edui-for-gmap .edui-dialog-content { + width: 550px; + height: 400px; +} + +/*video-dialog*/ +.edui-default .edui-for-insertvideo .edui-dialog-content { + width: 590px; + height: 390px; +} + +/*anchor-dialog*/ +.edui-default .edui-for-anchor .edui-dialog-content { + width: 320px; + height: 60px; + overflow: hidden; +} + +/*searchreplace-dialog*/ +.edui-default .edui-for-searchreplace .edui-dialog-content { + width: 400px; + height: 220px; +} + +/*help-dialog*/ +.edui-default .edui-for-help .edui-dialog-content { + width: 400px; + height: 420px; +} + +/*edittable-dialog*/ +.edui-default .edui-for-edittable .edui-dialog-content { + width: 540px; + _width:590px; + height: 335px; +} + +/*edittip-dialog*/ +.edui-default .edui-for-edittip .edui-dialog-content { + width: 225px; + height: 60px; +} + +/*edittd-dialog*/ +.edui-default .edui-for-edittd .edui-dialog-content { + width: 240px; + height: 50px; +} +/*snapscreen-dialog*/ +.edui-default .edui-for-snapscreen .edui-dialog-content { + width: 400px; + height: 220px; +} + +/*music-dialog*/ +.edui-default .edui-for-music .edui-dialog-content { + width: 515px; + height: 360px; +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/editor.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/editor.css new file mode 100644 index 000000000..de6af7ab6 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/editor.css @@ -0,0 +1,168 @@ +/*UI工具栏、编辑区域、底部*/ +.edui-default .edui-editor { + border: 1px solid #d4d4d4; + background-color: white; + position: relative; + overflow: visible; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.edui-editor div{ + width:auto; + height:auto; +} +.edui-default .edui-editor-toolbarbox { + position: relative; + zoom: 1; + -webkit-box-shadow:0 1px 4px rgba(204, 204, 204, 0.6); + -moz-box-shadow:0 1px 4px rgba(204, 204, 204, 0.6); + box-shadow:0 1px 4px rgba(204, 204, 204, 0.6); + border-top-left-radius:2px; + border-top-right-radius:2px; +} + +.edui-default .edui-editor-toolbarboxouter { + border-bottom: 1px solid #d4d4d4; + background-color: #fafafa; + background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2)); + background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2); + background-image: -o-linear-gradient(top, #ffffff, #f2f2f2); + background-image: linear-gradient(to bottom, #ffffff, #f2f2f2); + background-repeat: repeat-x; + /*border: 1px solid #d4d4d4;*/ + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0); + *zoom: 1; + -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); +} + +.edui-default .edui-editor-toolbarboxinner { + padding: 2px; +} + +.edui-default .edui-editor-iframeholder { + position: relative; + /*for fix ie6 toolbarmsg under iframe bug. relative -> static */ + /*_position: static !important;* +} + +.edui-default .edui-editor-iframeholder textarea { + font-family: consolas, "Courier New", "lucida console", monospace; + font-size: 12px; + line-height: 18px; +} + +.edui-default .edui-editor-bottombar { + /*border-top: 1px solid #ccc;*/ + /*height: 20px;*/ + /*width: 40%;*/ + /*float: left;*/ + /*overflow: hidden;*/ +} + +.edui-default .edui-editor-bottomContainer { + overflow: hidden; +} + +.edui-default .edui-editor-bottomContainer table { + width: 100%; + height: 0; + overflow: hidden; + border-spacing: 0; +} + +.edui-default .edui-editor-bottomContainer td { + white-space: nowrap; + border-top: 1px solid #ccc; + line-height: 20px; + font-size: 12px; + font-family: Arial, Helvetica, Tahoma, Verdana, Sans-Serif; +} + +.edui-default .edui-editor-wordcount { + text-align: right; + margin-right: 5px; + color: #aaa; +} +.edui-default .edui-editor-scale { + width: 12px; +} +.edui-default .edui-editor-scale .edui-editor-icon { + float: right; + width: 100%; + height: 12px; + margin-top: 10px; + background: url(../images/scale.png) no-repeat; + cursor: se-resize; +} +.edui-default .edui-editor-breadcrumb { + margin: 2px 0 0 3px; +} + +.edui-default .edui-editor-breadcrumb span { + cursor: pointer; + text-decoration: underline; + color: blue; +} + +.edui-default .edui-toolbar .edui-for-fullscreen { + float: right; +} + +.edui-default .edui-bubble .edui-popup-content { + border: 1px solid #DCAC6C; + background-color: #fff6d9; + padding: 5px; + font-size: 10pt; + font-family: "宋体"; +} + +.edui-default .edui-bubble .edui-shadow { + /*box-shadow: 1px 1px 3px #818181;*/ + /*-webkit-box-shadow: 2px 2px 3px #818181;*/ + /*-moz-box-shadow: 2px 2px 3px #818181;*/ + /*filter: progid:DXImageTransform.Microsoft.Blur(PixelRadius = '2', MakeShadow = 'true', ShadowOpacity = '0.5');*/ +} + +.edui-default .edui-editor-toolbarmsg { + background-color: #FFF6D9; + border-bottom: 1px solid #ccc; + position: absolute; + bottom: -25px; + left: 0; + z-index: 1009; + width: 99.9%; +} + +.edui-default .edui-editor-toolbarmsg-upload { + font-size: 14px; + color: blue; + width: 100px; + height: 16px; + line-height: 16px; + cursor: pointer; + position: absolute; + top: 5px; + left: 350px; +} + +.edui-default .edui-editor-toolbarmsg-label { + font-size: 12px; + line-height: 16px; + padding: 4px; +} + +.edui-default .edui-editor-toolbarmsg-close { + float: right; + width: 20px; + height: 16px; + line-height: 16px; + cursor: pointer; + color: red; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/menu.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/menu.css new file mode 100644 index 000000000..92bf7aaef --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/menu.css @@ -0,0 +1,46 @@ +/* 可选中按钮弹出菜单*/ +.edui-default .edui-menu { + z-index: 3000; +} + +.edui-default .edui-menu .edui-popup-content { + padding: 3px; +} + +.edui-default .edui-menu-body { + _width: 150px; + min-width: 170px; + background: url("../images/sparator_v.png") repeat-y 25px; +} + +.edui-default .edui-menuitem-body { +} + +.edui-default .edui-menuitem { + height: 20px; + cursor: default; + vertical-align: top; +} + +.edui-default .edui-menuitem .edui-icon { + width: 20px !important; + height: 20px !important; + background: url(../images/icons.png) 0 -4000px; + background: url(../images/icons.gif) 0 -4000px\9; +} + +.edui-default .edui-menuitem .edui-label { + font-size: 12px; + line-height: 20px; + height: 20px; + padding-left: 10px; +} + +.edui-default .edui-state-checked .edui-menuitem-body { + background: url("../images/icons-all.gif") no-repeat 6px -205px; +} + +.edui-default .edui-state-disabled .edui-menuitem-label { + color: gray; +} + diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/menubutton.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/menubutton.css new file mode 100644 index 000000000..966519214 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/menubutton.css @@ -0,0 +1,72 @@ +/*可选中菜单按钮*/ +.edui-default .edui-list .edui-bordereraser { + display: none; +} + +.edui-default .edui-listitem { + padding: 1px; + white-space: nowrap; +} + +.edui-default .edui-list .edui-state-hover { + position: relative; + background-color: #fff5d4; + border: 1px solid #dcac6c; + padding: 0; +} + +.edui-default .edui-for-fontfamily .edui-listitem-label { + min-width: 130px; + _width: 120px; + font-size: 12px; + height: 22px; + line-height: 22px; + padding-left: 5px; +} +.edui-default .edui-for-insertcode .edui-listitem-label { + min-width: 120px; + _width: 120px; + font-size: 12px; + height: 22px; + line-height: 22px; + padding-left: 5px; +} +.edui-default .edui-for-underline .edui-listitem-label { + min-width: 120px; + _width: 120px; + padding: 3px 5px; + font-size: 12px; +} + +.edui-default .edui-for-fontsize .edui-listitem-label { + min-width: 120px; + _width: 120px; + padding: 3px 5px; + +} + +.edui-default .edui-for-paragraph .edui-listitem-label { + min-width: 200px; + _width: 200px; + padding: 2px 5px; +} + +.edui-default .edui-for-rowspacingtop .edui-listitem-label, +.edui-default .edui-for-rowspacingbottom .edui-listitem-label { + min-width: 53px; + _width: 53px; + padding: 2px 5px; +} + +.edui-default .edui-for-lineheight .edui-listitem-label { + min-width: 53px; + _width: 53px; + padding: 2px 5px; +} + +.edui-default .edui-for-customstyle .edui-listitem-label { + min-width: 200px; + _width: 200px; + width: 200px !important; + padding: 2px 5px; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/message.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/message.css new file mode 100644 index 000000000..3088efd6d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/message.css @@ -0,0 +1,66 @@ +.edui-default .edui-editor-messageholder { + display: block; + width: 150px; + height: auto; + border: 0; + margin: 0; + padding: 0; + position: absolute; + top: 28px; + right: 3px; +} + +.edui-default .edui-message{ + min-height: 10px; + text-shadow: 0 1px 0 rgba(255,255,255,0.5); + padding: 0; + margin-bottom: 3px; + position: relative; +} +.edui-default .edui-message-body{ + border-radius: 3px; + padding: 8px 15px 8px 8px; + color: #c09853; + background-color: #fcf8e3; + border: 1px solid #fbeed5; +} +.edui-default .edui-message-type-info{ + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1 +} +.edui-default .edui-message-type-success{ + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6 +} +.edui-default .edui-message-type-danger, +.edui-default .edui-message-type-error{ + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7 +} +.edui-default .edui-message .edui-message-closer { + display: block; + width: 16px; + height: 16px; + line-height: 16px; + position: absolute; + top: 0; + right: 0; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + float: right; + font-size: 20px; + font-weight: bold; + color: #999; + text-shadow: 0 1px 0 #fff; + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; +} +.edui-default .edui-message .edui-message-content { + font-size: 10pt; + word-wrap: break-word; + word-break: normal; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/multiMenu.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/multiMenu.css new file mode 100644 index 000000000..78f354b7f --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/multiMenu.css @@ -0,0 +1,29 @@ +/*表情按钮及弹出菜单*/ +/*去除了表情的下拉箭头*/ +.edui-default .edui-for-emotion .edui-icon { + background-position: -60px -20px; +} +.edui-default .edui-for-emotion .edui-popup-content iframe +{ + width: 514px; + height: 380px; + overflow: hidden; +} +.edui-default .edui-for-emotion .edui-popup-content +{ + position: relative; + z-index: 555 +} + +.edui-default .edui-for-emotion .edui-splitborder { + display: none +} + +.edui-default .edui-for-emotion .edui-splitbutton-body .edui-arrow +{ + width: 0 +} +.edui-default .edui-toolbar .edui-for-emotion .edui-state-active .edui-splitborder +{ + border-left: 1px solid transparent; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/paragraphpicker.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/paragraphpicker.css new file mode 100644 index 000000000..9118c0632 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/paragraphpicker.css @@ -0,0 +1,45 @@ +/*段落弹出菜单*/ +.edui-default .edui-for-paragraph .edui-listitem-label { + font-family: Tahoma, Verdana, Arial, Helvetica; +} + +.edui-default .edui-for-paragraph .edui-listitem-label .edui-for-p { + font-size: 22px; + line-height: 27px; +} + +.edui-default .edui-for-paragraph .edui-listitem-label .edui-for-h1 { + font-weight: bolder; + font-size: 32px; + line-height: 36px; +} + +.edui-default .edui-for-paragraph .edui-listitem-label .edui-for-h2 { + font-weight: bolder; + font-size: 27px; + line-height: 29px; +} + +.edui-default .edui-for-paragraph .edui-listitem-label .edui-for-h3 { + font-weight: bolder; + font-size: 19px; + line-height: 23px; +} + +.edui-default .edui-for-paragraph .edui-listitem-label .edui-for-h4 { + font-weight: bolder; + font-size: 16px; + line-height: 19px +} + +.edui-default .edui-for-paragraph .edui-listitem-label .edui-for-h5 { + font-weight: bolder; + font-size: 13px; + line-height: 16px; +} + +.edui-default .edui-for-paragraph .edui-listitem-label .edui-for-h6 { + font-weight: bolder; + font-size: 12px; + line-height: 14px; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/pastepicker.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/pastepicker.css new file mode 100644 index 000000000..73c5b9556 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/pastepicker.css @@ -0,0 +1,72 @@ +/*粘贴弹出菜单*/ +.edui-default .edui-wordpastepop .edui-popup-content{ + border: none; + padding: 0; + width: 54px; + height: 21px; +} +.edui-default .edui-pasteicon { + width: 100%; + height: 100%; + background-image: url('../images/wordpaste.png'); + background-position: 0 0; +} + +.edui-default .edui-pasteicon.edui-state-opened { + background-position: 0 -34px; +} + +.edui-default .edui-pastecontainer { + position: relative; + visibility: hidden; + width: 97px; + background: #fff; + border: 1px solid #ccc; +} + +.edui-default .edui-pastecontainer .edui-title { + font-weight: bold; + background: #F8F8FF; + height: 25px; + line-height: 25px; + font-size: 12px; + padding-left: 5px; +} + +.edui-default .edui-pastecontainer .edui-button { + overflow: hidden; + margin: 3px 0; +} + +.edui-default .edui-pastecontainer .edui-button .edui-richtxticon, +.edui-default .edui-pastecontainer .edui-button .edui-tagicon, +.edui-default .edui-pastecontainer .edui-button .edui-plaintxticon{ + float: left; + cursor: pointer; + width: 29px; + height: 29px; + margin-left: 5px; + background-image: url('../images/wordpaste.png'); + background-repeat: no-repeat; +} +.edui-default .edui-pastecontainer .edui-button .edui-richtxticon { + margin-left: 0; + background-position: -109px 0; +} +.edui-default .edui-pastecontainer .edui-button .edui-tagicon { + background-position: -148px 1px; +} + +.edui-default .edui-pastecontainer .edui-button .edui-plaintxticon { + background-position: -72px 0; +} + +.edui-default .edui-pastecontainer .edui-button .edui-state-hover .edui-richtxticon { + background-position: -109px -34px; +} +.edui-default .edui-pastecontainer .edui-button .edui-state-hover .edui-tagicon{ + background-position: -148px -34px; +} +.edui-default .edui-pastecontainer .edui-button .edui-state-hover .edui-plaintxticon{ + background-position: -72px -34px; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/popup.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/popup.css new file mode 100644 index 000000000..bb4c50cc2 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/popup.css @@ -0,0 +1,73 @@ +/* 弹出菜单 */ +.edui-default .edui-popup { + z-index: 3000; + background-color: #ffffff; + width:auto; + height:auto; + +} + +.edui-default .edui-popup .edui-shadow { + left: 0; + top: 0; + width: 100%; + height: 100%; +} + +.edui-default .edui-popup-content { + border:1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + *border-right-width: 2px; + *border-bottom-width: 2px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 4px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 3px 4px rgba(0, 0, 0, 0.2); + box-shadow: 0 3px 4px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; + padding: 5px; + background:#ffffff; +} + +.edui-default .edui-popup .edui-bordereraser { + background-color: white; + height: 3px; +} + +.edui-default .edui-menu .edui-bordereraser { + height: 3px; +} + +.edui-default .edui-anchor-topleft .edui-bordereraser { + left: 1px; + top: -2px; +} + +.edui-default .edui-anchor-topright .edui-bordereraser { + right: 1px; + top: -2px; +} + +.edui-default .edui-anchor-bottomleft .edui-bordereraser { + left: 0; + bottom: -6px; + height: 7px; + border-left: 1px solid gray; + border-right: 1px solid gray; +} + +.edui-default .edui-anchor-bottomright .edui-bordereraser { + right: 0; + bottom: -6px; + height: 7px; + border-left: 1px solid gray; + border-right: 1px solid gray; +} + +.edui-popup div{ + width:auto; + height:auto; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/separtor.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/separtor.css new file mode 100644 index 000000000..f932a60d4 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/separtor.css @@ -0,0 +1,8 @@ +/*分隔线*/ +.edui-default .edui-toolbar .edui-separator { + width: 2px; + height: 20px; + margin: 2px 4px 2px 3px; + background: url(../images/icons.png) -181px 0; + background: url(../images/icons.gif) -181px 0 \9; +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/shortcutmenu.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/shortcutmenu.css new file mode 100644 index 000000000..ec4a81ac9 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/shortcutmenu.css @@ -0,0 +1,9 @@ +/*弹出菜单*/ +.edui-default .edui-shortcutmenu { + padding: 2px; + width: 190px; + height: 50px; + background-color: #fff; + border: 1px solid #ccc; + border-radius: 5px; +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/splitbutton.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/splitbutton.css new file mode 100644 index 000000000..ef7667260 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/splitbutton.css @@ -0,0 +1,84 @@ +/*splitbutton*/ +.edui-default .edui-toolbar .edui-splitbutton-body .edui-arrow, +.edui-default .edui-toolbar .edui-menubutton-body .edui-arrow { + background: url(../images/icons.png) -741px 0; + _background: url(../images/icons.gif) -741px 0; + height: 20px; + width: 9px; +} + +.edui-default .edui-toolbar .edui-splitbutton .edui-splitbutton-body, +.edui-default .edui-toolbar .edui-menubutton .edui-menubutton-body { + padding: 1px; +} + +.edui-default .edui-toolbar .edui-splitborder { + width: 1px; + height: 20px; +} + +.edui-default .edui-toolbar .edui-state-hover .edui-splitborder { + width: 1px; + border-left: 0px solid #dcac6c; +} + +.edui-default .edui-toolbar .edui-state-active .edui-splitborder { + width: 0; + border-left: 1px solid gray; +} + +.edui-default .edui-toolbar .edui-state-opened .edui-splitborder { + width: 1px; + border: 0; +} + +.edui-default .edui-toolbar .edui-splitbutton .edui-state-hover .edui-splitbutton-body, +.edui-default .edui-toolbar .edui-menubutton .edui-state-hover .edui-menubutton-body { + background-color: #fff5d4; + border: 1px solid #dcac6c; + padding: 0; +} + +.edui-default .edui-toolbar .edui-splitbutton .edui-state-checked .edui-splitbutton-body, +.edui-default .edui-toolbar .edui-menubutton .edui-state-checked .edui-menubutton-body { + background-color: #FFE69F; + border: 1px solid #DCAC6C; + padding: 0; +} + +.edui-default .edui-toolbar .edui-splitbutton .edui-state-active .edui-splitbutton-body, +.edui-default .edui-toolbar .edui-menubutton .edui-state-active .edui-menubutton-body { + background-color: #ffffff; + border: 1px solid gray; + padding: 0; +} + +.edui-default .edui-state-disabled .edui-arrow { + opacity: 0.3; + _filter: alpha(opacity = 30); +} + +.edui-default .edui-toolbar .edui-splitbutton .edui-state-opened .edui-splitbutton-body, +.edui-default .edui-toolbar .edui-menubutton .edui-state-opened .edui-menubutton-body { + background-color: white; + border: 1px solid gray; + padding: 0; +} + +.edui-default .edui-for-insertorderedlist .edui-bordereraser, +.edui-default .edui-for-lineheight .edui-bordereraser, +.edui-default .edui-for-rowspacingtop .edui-bordereraser, +.edui-default .edui-for-rowspacingbottom .edui-bordereraser, +.edui-default .edui-for-insertunorderedlist .edui-bordereraser { + background-color: white; +} + +/* 解决嵌套导致的图标问题 */ +.edui-default .edui-for-insertorderedlist .edui-popup-body .edui-icon, +.edui-default .edui-for-lineheight .edui-popup-body .edui-icon, +.edui-default .edui-for-rowspacingtop .edui-popup-body .edui-icon, +.edui-default .edui-for-rowspacingbottom .edui-popup-body .edui-icon, +.edui-default .edui-for-insertunorderedlist .edui-popup-body .edui-icon { + /*background-position: 0 -40px;*/ + background-image: none ; +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/tablepicker.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/tablepicker.css new file mode 100644 index 000000000..34232ed22 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/tablepicker.css @@ -0,0 +1,40 @@ +/* 表格弹出菜单 */ +.edui-default .edui-for-inserttable .edui-splitborder { + display: none +} +.edui-default .edui-for-inserttable .edui-splitbutton-body .edui-arrow { + width: 0 +} +.edui-default .edui-toolbar .edui-for-inserttable .edui-state-active .edui-splitborder{ + border-left: 1px solid transparent; +} +.edui-default .edui-tablepicker .edui-infoarea { + height: 14px; + line-height: 14px; + font-size: 12px; + width: 220px; + margin-bottom: 3px; + clear: both; +} + +.edui-default .edui-tablepicker .edui-infoarea .edui-label { + float: left; +} + +.edui-default .edui-dialog-buttons .edui-label { + line-height: 24px; +} + +.edui-default .edui-tablepicker .edui-infoarea .edui-clickable { + float: right; +} + +.edui-default .edui-tablepicker .edui-pickarea { + background: url("../images/unhighlighted.gif") repeat; + height: 220px; + width: 220px; +} + +.edui-default .edui-tablepicker .edui-pickarea .edui-overlay { + background: url("../images/highlighted.gif") repeat; +} diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/toolbar.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/toolbar.css new file mode 100644 index 000000000..9f7db121d --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/toolbar.css @@ -0,0 +1,18 @@ +/* 工具栏 */ +.edui-default .edui-toolbar { + cursor: default; + -webkit-user-select: none; + -moz-user-select: none; + padding: 1px; + overflow: hidden; /*全屏下单独一行不占位*/ + zoom: 1; + width:auto; + height:auto; +} + +.edui-default .edui-toolbar .edui-button, +.edui-default .edui-toolbar .edui-splitbutton, +.edui-default .edui-toolbar .edui-menubutton, +.edui-default .edui-toolbar .edui-combox { + margin: 1px; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/ueditor.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/ueditor.css new file mode 100644 index 000000000..fee7d8323 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/ueditor.css @@ -0,0 +1,59 @@ +/*根据UI结构重写CSS,仅在相应UI组件创建时,加载对应css,顺序加载 +*/ + +/*-------基础UI构建,必须加载-------*/ +@import "uibase.css"; +@import "toolbar.css"; +@import "editor.css"; + + +/*-------可选中菜单按钮,按需加载-------*/ + /*可选中菜单按钮--依赖splitbutton*/ +@import "menubutton.css"; + /*可选中菜单按钮-弹出菜单*/ +@import "menu.css"; + + +/*-------不可选中菜单按钮,按需加载-------*/ + /*不可选中菜单按钮--依赖splitbutton*/ +@import "combox.css"; + + +/*-------按钮类型,按需加载-------*/ + /*普通按钮*/ +@import "button.css"; + /*按钮icon*/ +@import "buttonicon.css"; + /*弹出菜单按钮-附加按钮*/ +@import "splitbutton.css"; + /*弹出菜单*/ +@import "popup.css"; + /*提示消息*/ +@import "message.css"; + + +/*-------独立按钮样式,按需加载-------*/ + /*弹出对话框样式*/ +@import "dialog.css"; + /*段落格式弹出菜单*/ +@import "paragraphpicker.css"; + /*表格弹出菜单*/ +@import "tablepicker.css"; + /*颜色弹出菜单*/ +@import "colorpicker.css"; + /*自动排版弹出菜单*/ +@import "autotypesetpicker.css"; + /*平均分布菜单*/ +@import "cellalignpicker.css"; + /*分隔线*/ +@import "separtor.css"; + /*颜色按钮--依赖splitbutton*/ +@import "colorbutton.css"; + /*表情按钮--依赖splitbutton*/ +@import "multiMenu.css"; + /*右键菜单*/ +@import "contextmenu.css"; + /*快捷菜单*/ +@import "shortcutmenu.css"; + /*粘贴提示*/ +@import "pastepicker.css"; \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/uibase.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/uibase.css new file mode 100644 index 000000000..6be464c36 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/_css/uibase.css @@ -0,0 +1,115 @@ +/*基础UI构建 +*/ +/* common layer */ +.edui-default .edui-box { + border: none; + padding: 0; + margin: 0; + overflow: hidden; +} + +.edui-default a.edui-box { + display: block; + text-decoration: none; + color: black; +} + +.edui-default a.edui-box:hover { + text-decoration: none; +} + +.edui-default a.edui-box:active { + text-decoration: none; +} + +.edui-default table.edui-box { + border-collapse: collapse; +} + +.edui-default ul.edui-box { + list-style-type: none; +} + +div.edui-box { + position: relative; + display: -moz-inline-box !important; + display: inline-block !important; + vertical-align: top; +} + +.edui-default .edui-clearfix { + zoom: 1 +} + +.edui-default .edui-clearfix:after { + content: '\20'; + display: block; + clear: both; +} + + * html div.edui-box { + display: inline !important; +} + +*:first-child+html div.edui-box { + display: inline !important; +} + +/* control layout */ +.edui-default .edui-button-body, .edui-splitbutton-body, .edui-menubutton-body, .edui-combox-body { + position: relative; +} + +.edui-default .edui-popup { + position: absolute; + -webkit-user-select: none; + -moz-user-select: none; +} + +.edui-default .edui-popup .edui-shadow { + position: absolute; + z-index: -1; +} + +.edui-default .edui-popup .edui-bordereraser { + position: absolute; + overflow: hidden; +} + +.edui-default .edui-tablepicker .edui-canvas { + position: relative; +} + +.edui-default .edui-tablepicker .edui-canvas .edui-overlay { + position: absolute; +} + +.edui-default .edui-dialog-modalmask, .edui-dialog-dragmask { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; +} + +.edui-default .edui-toolbar { + position: relative; +} + +/* + * default theme + */ +.edui-default .edui-label { + cursor: default; +} + +.edui-default span.edui-clickable { + color: blue; + cursor: pointer; + text-decoration: underline; +} + +.edui-default span.edui-unclickable { + color: gray; + cursor: default; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/dialogbase.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/dialogbase.css new file mode 100644 index 000000000..cd663d5de --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/dialogbase.css @@ -0,0 +1,100 @@ +/*弹出对话框页面样式组件 +*/ + +/*reset +*/ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + margin: 0; + padding: 0; + outline: 0; + font-size: 100%; +} + +body { + line-height: 1; +} + +ol, ul { + list-style: none; +} + +blockquote, q { + quotes: none; +} + +ins { + text-decoration: none; +} + +del { + text-decoration: line-through; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +/*module +*/ +body { + background-color: #fff; + font: 12px/1.5 sans-serif, "宋体", "Arial Narrow", HELVETICA; + color: #646464; +} + +/*tab*/ +.tabhead { + position: relative; + z-index: 10; +} + +.tabhead span { + display: inline-block; + padding: 0 5px; + height: 30px; + border: 1px solid #ccc; + background: url("images/dialog-title-bg.png") repeat-x; + text-align: center; + line-height: 30px; + cursor: pointer; + *margin-right: 5px; +} + +.tabhead span.focus { + height: 31px; + border-bottom: none; + background: #fff; +} + +.tabbody { + position: relative; + top: -1px; + margin: 0 auto; + border: 1px solid #ccc; +} + +/*button*/ +a.button { + display: block; + text-align: center; + line-height: 24px; + text-decoration: none; + height: 24px; + width: 95px; + border: 0; + color: #838383; + background: url(../../themes/default/images/icons-all.gif) no-repeat; +} + +a.button:hover { + background-position: 0 -30px; +} \ No newline at end of file diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/anchor.gif b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/anchor.gif new file mode 100644 index 000000000..5aa797b22 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/anchor.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/arrow.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/arrow.png new file mode 100644 index 000000000..d9008866b Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/arrow.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/arrow_down.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/arrow_down.png new file mode 100644 index 000000000..e9257e83b Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/arrow_down.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/arrow_up.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/arrow_up.png new file mode 100644 index 000000000..74277af1e Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/arrow_up.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/button-bg.gif b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/button-bg.gif new file mode 100644 index 000000000..ec7fa2eab Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/button-bg.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/cancelbutton.gif b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/cancelbutton.gif new file mode 100644 index 000000000..df4bc2c06 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/cancelbutton.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/charts.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/charts.png new file mode 100644 index 000000000..713965cc4 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/charts.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/cursor_h.gif b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/cursor_h.gif new file mode 100644 index 000000000..d7c3e7e9e Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/cursor_h.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/cursor_h.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/cursor_h.png new file mode 100644 index 000000000..2088fc240 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/cursor_h.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/cursor_v.gif b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/cursor_v.gif new file mode 100644 index 000000000..bb508db55 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/cursor_v.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/cursor_v.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/cursor_v.png new file mode 100644 index 000000000..6f39ca3d8 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/cursor_v.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/dialog-title-bg.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/dialog-title-bg.png new file mode 100644 index 000000000..f744f267f Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/dialog-title-bg.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/filescan.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/filescan.png new file mode 100644 index 000000000..1d2715886 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/filescan.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/highlighted.gif b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/highlighted.gif new file mode 100644 index 000000000..9272b4915 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/highlighted.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/icons-all.gif b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/icons-all.gif new file mode 100644 index 000000000..21915e59d Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/icons-all.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/icons.gif b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/icons.gif new file mode 100644 index 000000000..7abd30a1c Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/icons.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/icons.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/icons.png new file mode 100644 index 000000000..c015e3aac Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/icons.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/loaderror.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/loaderror.png new file mode 100644 index 000000000..35ff33364 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/loaderror.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/loading.gif b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/loading.gif new file mode 100644 index 000000000..b713e27df Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/loading.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/lock.gif b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/lock.gif new file mode 100644 index 000000000..b4e6d7822 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/lock.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/neweditor-tab-bg.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/neweditor-tab-bg.png new file mode 100644 index 000000000..8f398b095 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/neweditor-tab-bg.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/pagebreak.gif b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/pagebreak.gif new file mode 100644 index 000000000..8d1cffd64 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/pagebreak.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/scale.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/scale.png new file mode 100644 index 000000000..f45adb585 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/scale.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/sortable.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/sortable.png new file mode 100644 index 000000000..1bca64969 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/sortable.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/spacer.gif b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/spacer.gif new file mode 100644 index 000000000..5bfd67a2d Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/spacer.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/sparator_v.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/sparator_v.png new file mode 100644 index 000000000..8cf5662da Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/sparator_v.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/table-cell-align.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/table-cell-align.png new file mode 100644 index 000000000..ddf42853e Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/table-cell-align.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/tangram-colorpicker.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/tangram-colorpicker.png new file mode 100644 index 000000000..738e500cf Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/tangram-colorpicker.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/toolbar_bg.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/toolbar_bg.png new file mode 100644 index 000000000..7ab685f42 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/toolbar_bg.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/unhighlighted.gif b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/unhighlighted.gif new file mode 100644 index 000000000..7ad0b67ae Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/unhighlighted.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/upload.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/upload.png new file mode 100644 index 000000000..08d4d9268 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/upload.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/videologo.gif b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/videologo.gif new file mode 100644 index 000000000..555af7417 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/videologo.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/word.gif b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/word.gif new file mode 100644 index 000000000..9ef5d09b7 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/word.gif differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/wordpaste.png b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/wordpaste.png new file mode 100644 index 000000000..936775810 Binary files /dev/null and b/nezha-fronted/static/ueditor-1.4.3.3/themes/default/images/wordpaste.png differ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/themes/iframe.css b/nezha-fronted/static/ueditor-1.4.3.3/themes/iframe.css new file mode 100644 index 000000000..774013afd --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/themes/iframe.css @@ -0,0 +1 @@ +/*可以在这里添加你自己的css*/ diff --git a/nezha-fronted/static/ueditor-1.4.3.3/third-party/SyntaxHighlighter/shCore.js b/nezha-fronted/static/ueditor-1.4.3.3/third-party/SyntaxHighlighter/shCore.js new file mode 100644 index 000000000..324918425 --- /dev/null +++ b/nezha-fronted/static/ueditor-1.4.3.3/third-party/SyntaxHighlighter/shCore.js @@ -0,0 +1,3655 @@ +// XRegExp 1.5.1 +// (c) 2007-2012 Steven Levithan +// MIT License +// +// Provides an augmented, extensible, cross-browser implementation of regular expressions, +// including support for additional syntax, flags, and methods + +var XRegExp; + +if (XRegExp) { + // Avoid running twice, since that would break references to native globals + throw Error("can't load XRegExp twice in the same frame"); +} + +// Run within an anonymous function to protect variables and avoid new globals +(function (undefined) { + + //--------------------------------- + // Constructor + //--------------------------------- + + // Accepts a pattern and flags; returns a new, extended `RegExp` object. Differs from a native + // regular expression in that additional syntax and flags are supported and cross-browser + // syntax inconsistencies are ameliorated. `XRegExp(/regex/)` clones an existing regex and + // converts to type XRegExp + XRegExp = function (pattern, flags) { + var output = [], + currScope = XRegExp.OUTSIDE_CLASS, + pos = 0, + context, tokenResult, match, chr, regex; + + if (XRegExp.isRegExp(pattern)) { + if (flags !== undefined) + throw TypeError("can't supply flags when constructing one RegExp from another"); + return clone(pattern); + } + // Tokens become part of the regex construction process, so protect against infinite + // recursion when an XRegExp is constructed within a token handler or trigger + if (isInsideConstructor) + throw Error("can't call the XRegExp constructor within token definition functions"); + + flags = flags || ""; + context = { // `this` object for custom tokens + hasNamedCapture: false, + captureNames: [], + hasFlag: function (flag) {return flags.indexOf(flag) > -1;}, + setFlag: function (flag) {flags += flag;} + }; + + while (pos < pattern.length) { + // Check for custom tokens at the current position + tokenResult = runTokens(pattern, pos, currScope, context); + + if (tokenResult) { + output.push(tokenResult.output); + pos += (tokenResult.match[0].length || 1); + } else { + // Check for native multicharacter metasequences (excluding character classes) at + // the current position + if (match = nativ.exec.call(nativeTokens[currScope], pattern.slice(pos))) { + output.push(match[0]); + pos += match[0].length; + } else { + chr = pattern.charAt(pos); + if (chr === "[") + currScope = XRegExp.INSIDE_CLASS; + else if (chr === "]") + currScope = XRegExp.OUTSIDE_CLASS; + // Advance position one character + output.push(chr); + pos++; + } + } + } + + regex = RegExp(output.join(""), nativ.replace.call(flags, flagClip, "")); + regex._xregexp = { + source: pattern, + captureNames: context.hasNamedCapture ? context.captureNames : null + }; + return regex; + }; + + + //--------------------------------- + // Public properties + //--------------------------------- + + XRegExp.version = "1.5.1"; + + // Token scope bitflags + XRegExp.INSIDE_CLASS = 1; + XRegExp.OUTSIDE_CLASS = 2; + + + //--------------------------------- + // Private variables + //--------------------------------- + + var replacementToken = /\$(?:(\d\d?|[$&`'])|{([$\w]+)})/g, + flagClip = /[^gimy]+|([\s\S])(?=[\s\S]*\1)/g, // Nonnative and duplicate flags + quantifier = /^(?:[?*+]|{\d+(?:,\d*)?})\??/, + isInsideConstructor = false, + tokens = [], + // Copy native globals for reference ("native" is an ES3 reserved keyword) + nativ = { + exec: RegExp.prototype.exec, + test: RegExp.prototype.test, + match: String.prototype.match, + replace: String.prototype.replace, + split: String.prototype.split + }, + compliantExecNpcg = nativ.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups + compliantLastIndexIncrement = function () { + var x = /^/g; + nativ.test.call(x, ""); + return !x.lastIndex; + }(), + hasNativeY = RegExp.prototype.sticky !== undefined, + nativeTokens = {}; + + // `nativeTokens` match native multicharacter metasequences only (including deprecated octals, + // excluding character classes) + nativeTokens[XRegExp.INSIDE_CLASS] = /^(?:\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S]))/; + nativeTokens[XRegExp.OUTSIDE_CLASS] = /^(?:\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])|\(\?[:=!]|[?*+]\?|{\d+(?:,\d*)?}\??)/; + + + //--------------------------------- + // Public methods + //--------------------------------- + + // Lets you extend or change XRegExp syntax and create custom flags. This is used internally by + // the XRegExp library and can be used to create XRegExp plugins. This function is intended for + // users with advanced knowledge of JavaScript's regular expression syntax and behavior. It can + // be disabled by `XRegExp.freezeTokens` + XRegExp.addToken = function (regex, handler, scope, trigger) { + tokens.push({ + pattern: clone(regex, "g" + (hasNativeY ? "y" : "")), + handler: handler, + scope: scope || XRegExp.OUTSIDE_CLASS, + trigger: trigger || null + }); + }; + + // Accepts a pattern and flags; returns an extended `RegExp` object. If the pattern and flag + // combination has previously been cached, the cached copy is returned; otherwise the newly + // created regex is cached + XRegExp.cache = function (pattern, flags) { + var key = pattern + "/" + (flags || ""); + return XRegExp.cache[key] || (XRegExp.cache[key] = XRegExp(pattern, flags)); + }; + + // Accepts a `RegExp` instance; returns a copy with the `/g` flag set. The copy has a fresh + // `lastIndex` (set to zero). If you want to copy a regex without forcing the `global` + // property, use `XRegExp(regex)`. Do not use `RegExp(regex)` because it will not preserve + // special properties required for named capture + XRegExp.copyAsGlobal = function (regex) { + return clone(regex, "g"); + }; + + // Accepts a string; returns the string with regex metacharacters escaped. The returned string + // can safely be used at any point within a regex to match the provided literal string. Escaped + // characters are [ ] { } ( ) * + ? - . , \ ^ $ | # and whitespace + XRegExp.escape = function (str) { + return str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + }; + + // Accepts a string to search, regex to search with, position to start the search within the + // string (default: 0), and an optional Boolean indicating whether matches must start at-or- + // after the position or at the specified position only. This function ignores the `lastIndex` + // of the provided regex in its own handling, but updates the property for compatibility + XRegExp.execAt = function (str, regex, pos, anchored) { + var r2 = clone(regex, "g" + ((anchored && hasNativeY) ? "y" : "")), + match; + r2.lastIndex = pos = pos || 0; + match = r2.exec(str); // Run the altered `exec` (required for `lastIndex` fix, etc.) + if (anchored && match && match.index !== pos) + match = null; + if (regex.global) + regex.lastIndex = match ? r2.lastIndex : 0; + return match; + }; + + // Breaks the unrestorable link to XRegExp's private list of tokens, thereby preventing + // syntax and flag changes. Should be run after XRegExp and any plugins are loaded + XRegExp.freezeTokens = function () { + XRegExp.addToken = function () { + throw Error("can't run addToken after freezeTokens"); + }; + }; + + // Accepts any value; returns a Boolean indicating whether the argument is a `RegExp` object. + // Note that this is also `true` for regex literals and regexes created by the `XRegExp` + // constructor. This works correctly for variables created in another frame, when `instanceof` + // and `constructor` checks would fail to work as intended + XRegExp.isRegExp = function (o) { + return Object.prototype.toString.call(o) === "[object RegExp]"; + }; + + // Executes `callback` once per match within `str`. Provides a simpler and cleaner way to + // iterate over regex matches compared to the traditional approaches of subverting + // `String.prototype.replace` or repeatedly calling `exec` within a `while` loop + XRegExp.iterate = function (str, regex, callback, context) { + var r2 = clone(regex, "g"), + i = -1, match; + while (match = r2.exec(str)) { // Run the altered `exec` (required for `lastIndex` fix, etc.) + if (regex.global) + regex.lastIndex = r2.lastIndex; // Doing this to follow expectations if `lastIndex` is checked within `callback` + callback.call(context, match, ++i, str, regex); + if (r2.lastIndex === match.index) + r2.lastIndex++; + } + if (regex.global) + regex.lastIndex = 0; + }; + + // Accepts a string and an array of regexes; returns the result of using each successive regex + // to search within the matches of the previous regex. The array of regexes can also contain + // objects with `regex` and `backref` properties, in which case the named or numbered back- + // references specified are passed forward to the next regex or returned. E.g.: + // var xregexpImgFileNames = XRegExp.matchChain(html, [ + // {regex: /]+)>/i, backref: 1}, // tag attributes + // {regex: XRegExp('(?ix) \\s src=" (? [^"]+ )'), backref: "src"}, // src attribute values + // {regex: XRegExp("^http://xregexp\\.com(/[^#?]+)", "i"), backref: 1}, // xregexp.com paths + // /[^\/]+$/ // filenames (strip directory paths) + // ]); + XRegExp.matchChain = function (str, chain) { + return function recurseChain (values, level) { + var item = chain[level].regex ? chain[level] : {regex: chain[level]}, + regex = clone(item.regex, "g"), + matches = [], i; + for (i = 0; i < values.length; i++) { + XRegExp.iterate(values[i], regex, function (match) { + matches.push(item.backref ? (match[item.backref] || "") : match[0]); + }); + } + return ((level === chain.length - 1) || !matches.length) ? + matches : recurseChain(matches, level + 1); + }([str], 0); + }; + + + //--------------------------------- + // New RegExp prototype methods + //--------------------------------- + + // Accepts a context object and arguments array; returns the result of calling `exec` with the + // first value in the arguments array. the context is ignored but is accepted for congruity + // with `Function.prototype.apply` + RegExp.prototype.apply = function (context, args) { + return this.exec(args[0]); + }; + + // Accepts a context object and string; returns the result of calling `exec` with the provided + // string. the context is ignored but is accepted for congruity with `Function.prototype.call` + RegExp.prototype.call = function (context, str) { + return this.exec(str); + }; + + + //--------------------------------- + // Overriden native methods + //--------------------------------- + + // Adds named capture support (with backreferences returned as `result.name`), and fixes two + // cross-browser issues per ES3: + // - Captured values for nonparticipating capturing groups should be returned as `undefined`, + // rather than the empty string. + // - `lastIndex` should not be incremented after zero-length matches. + RegExp.prototype.exec = function (str) { + var match, name, r2, origLastIndex; + if (!this.global) + origLastIndex = this.lastIndex; + match = nativ.exec.apply(this, arguments); + if (match) { + // Fix browsers whose `exec` methods don't consistently return `undefined` for + // nonparticipating capturing groups + if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) { + r2 = RegExp(this.source, nativ.replace.call(getNativeFlags(this), "g", "")); + // Using `str.slice(match.index)` rather than `match[0]` in case lookahead allowed + // matching due to characters outside the match + nativ.replace.call((str + "").slice(match.index), r2, function () { + for (var i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undefined) + match[i] = undefined; + } + }); + } + // Attach named capture properties + if (this._xregexp && this._xregexp.captureNames) { + for (var i = 1; i < match.length; i++) { + name = this._xregexp.captureNames[i - 1]; + if (name) + match[name] = match[i]; + } + } + // Fix browsers that increment `lastIndex` after zero-length matches + if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index)) + this.lastIndex--; + } + if (!this.global) + this.lastIndex = origLastIndex; // Fix IE, Opera bug (last tested IE 9.0.5, Opera 11.61 on Windows) + return match; + }; + + // Fix browser bugs in native method + RegExp.prototype.test = function (str) { + // Use the native `exec` to skip some processing overhead, even though the altered + // `exec` would take care of the `lastIndex` fixes + var match, origLastIndex; + if (!this.global) + origLastIndex = this.lastIndex; + match = nativ.exec.call(this, str); + // Fix browsers that increment `lastIndex` after zero-length matches + if (match && !compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index)) + this.lastIndex--; + if (!this.global) + this.lastIndex = origLastIndex; // Fix IE, Opera bug (last tested IE 9.0.5, Opera 11.61 on Windows) + return !!match; + }; + + // Adds named capture support and fixes browser bugs in native method + String.prototype.match = function (regex) { + if (!XRegExp.isRegExp(regex)) + regex = RegExp(regex); // Native `RegExp` + if (regex.global) { + var result = nativ.match.apply(this, arguments); + regex.lastIndex = 0; // Fix IE bug + return result; + } + return regex.exec(this); // Run the altered `exec` + }; + + // Adds support for `${n}` tokens for named and numbered backreferences in replacement text, + // and provides named backreferences to replacement functions as `arguments[0].name`. Also + // fixes cross-browser differences in replacement text syntax when performing a replacement + // using a nonregex search value, and the value of replacement regexes' `lastIndex` property + // during replacement iterations. Note that this doesn't support SpiderMonkey's proprietary + // third (`flags`) parameter + String.prototype.replace = function (search, replacement) { + var isRegex = XRegExp.isRegExp(search), + captureNames, result, str, origLastIndex; + + // There are too many combinations of search/replacement types/values and browser bugs that + // preclude passing to native `replace`, so don't try + //if (...) + // return nativ.replace.apply(this, arguments); + + if (isRegex) { + if (search._xregexp) + captureNames = search._xregexp.captureNames; // Array or `null` + if (!search.global) + origLastIndex = search.lastIndex; + } else { + search = search + ""; // Type conversion + } + + if (Object.prototype.toString.call(replacement) === "[object Function]") { + result = nativ.replace.call(this + "", search, function () { + if (captureNames) { + // Change the `arguments[0]` string primitive to a String object which can store properties + arguments[0] = new String(arguments[0]); + // Store named backreferences on `arguments[0]` + for (var i = 0; i < captureNames.length; i++) { + if (captureNames[i]) + arguments[0][captureNames[i]] = arguments[i + 1]; + } + } + // Update `lastIndex` before calling `replacement` (fix browsers) + if (isRegex && search.global) + search.lastIndex = arguments[arguments.length - 2] + arguments[0].length; + return replacement.apply(null, arguments); + }); + } else { + str = this + ""; // Type conversion, so `args[args.length - 1]` will be a string (given nonstring `this`) + result = nativ.replace.call(str, search, function () { + var args = arguments; // Keep this function's `arguments` available through closure + return nativ.replace.call(replacement + "", replacementToken, function ($0, $1, $2) { + // Numbered backreference (without delimiters) or special variable + if ($1) { + switch ($1) { + case "$": return "$"; + case "&": return args[0]; + case "`": return args[args.length - 1].slice(0, args[args.length - 2]); + case "'": return args[args.length - 1].slice(args[args.length - 2] + args[0].length); + // Numbered backreference + default: + // What does "$10" mean? + // - Backreference 10, if 10 or more capturing groups exist + // - Backreference 1 followed by "0", if 1-9 capturing groups exist + // - Otherwise, it's the string "$10" + // Also note: + // - Backreferences cannot be more than two digits (enforced by `replacementToken`) + // - "$01" is equivalent to "$1" if a capturing group exists, otherwise it's the string "$01" + // - There is no "$0" token ("$&" is the entire match) + var literalNumbers = ""; + $1 = +$1; // Type conversion; drop leading zero + if (!$1) // `$1` was "0" or "00" + return $0; + while ($1 > args.length - 3) { + literalNumbers = String.prototype.slice.call($1, -1) + literalNumbers; + $1 = Math.floor($1 / 10); // Drop the last digit + } + return ($1 ? args[$1] || "" : "$") + literalNumbers; + } + // Named backreference or delimited numbered backreference + } else { + // What does "${n}" mean? + // - Backreference to numbered capture n. Two differences from "$n": + // - n can be more than two digits + // - Backreference 0 is allowed, and is the entire match + // - Backreference to named capture n, if it exists and is not a number overridden by numbered capture + // - Otherwise, it's the string "${n}" + var n = +$2; // Type conversion; drop leading zeros + if (n <= args.length - 3) + return args[n]; + n = captureNames ? indexOf(captureNames, $2) : -1; + return n > -1 ? args[n + 1] : $0; + } + }); + }); + } + + if (isRegex) { + if (search.global) + search.lastIndex = 0; // Fix IE, Safari bug (last tested IE 9.0.5, Safari 5.1.2 on Windows) + else + search.lastIndex = origLastIndex; // Fix IE, Opera bug (last tested IE 9.0.5, Opera 11.61 on Windows) + } + + return result; + }; + + // A consistent cross-browser, ES3 compliant `split` + String.prototype.split = function (s /* separator */, limit) { + // If separator `s` is not a regex, use the native `split` + if (!XRegExp.isRegExp(s)) + return nativ.split.apply(this, arguments); + + var str = this + "", // Type conversion + output = [], + lastLastIndex = 0, + match, lastLength; + + // Behavior for `limit`: if it's... + // - `undefined`: No limit + // - `NaN` or zero: Return an empty array + // - A positive number: Use `Math.floor(limit)` + // - A negative number: No limit + // - Other: Type-convert, then use the above rules + if (limit === undefined || +limit < 0) { + limit = Infinity; + } else { + limit = Math.floor(+limit); + if (!limit) + return []; + } + + // This is required if not `s.global`, and it avoids needing to set `s.lastIndex` to zero + // and restore it to its original value when we're done using the regex + s = XRegExp.copyAsGlobal(s); + + while (match = s.exec(str)) { // Run the altered `exec` (required for `lastIndex` fix, etc.) + if (s.lastIndex > lastLastIndex) { + output.push(str.slice(lastLastIndex, match.index)); + + if (match.length > 1 && match.index < str.length) + Array.prototype.push.apply(output, match.slice(1)); + + lastLength = match[0].length; + lastLastIndex = s.lastIndex; + + if (output.length >= limit) + break; + } + + if (s.lastIndex === match.index) + s.lastIndex++; + } + + if (lastLastIndex === str.length) { + if (!nativ.test.call(s, "") || lastLength) + output.push(""); + } else { + output.push(str.slice(lastLastIndex)); + } + + return output.length > limit ? output.slice(0, limit) : output; + }; + + + //--------------------------------- + // Private helper functions + //--------------------------------- + + // Supporting function for `XRegExp`, `XRegExp.copyAsGlobal`, etc. Returns a copy of a `RegExp` + // instance with a fresh `lastIndex` (set to zero), preserving properties required for named + // capture. Also allows adding new flags in the process of copying the regex + function clone (regex, additionalFlags) { + if (!XRegExp.isRegExp(regex)) + throw TypeError("type RegExp expected"); + var x = regex._xregexp; + regex = XRegExp(regex.source, getNativeFlags(regex) + (additionalFlags || "")); + if (x) { + regex._xregexp = { + source: x.source, + captureNames: x.captureNames ? x.captureNames.slice(0) : null + }; + } + return regex; + } + + function getNativeFlags (regex) { + return (regex.global ? "g" : "") + + (regex.ignoreCase ? "i" : "") + + (regex.multiline ? "m" : "") + + (regex.extended ? "x" : "") + // Proposed for ES4; included in AS3 + (regex.sticky ? "y" : ""); + } + + function runTokens (pattern, index, scope, context) { + var i = tokens.length, + result, match, t; + // Protect against constructing XRegExps within token handler and trigger functions + isInsideConstructor = true; + // Must reset `isInsideConstructor`, even if a `trigger` or `handler` throws + try { + while (i--) { // Run in reverse order + t = tokens[i]; + if ((scope & t.scope) && (!t.trigger || t.trigger.call(context))) { + t.pattern.lastIndex = index; + match = t.pattern.exec(pattern); // Running the altered `exec` here allows use of named backreferences, etc. + if (match && match.index === index) { + result = { + output: t.handler.call(context, match, scope), + match: match + }; + break; + } + } + } + } catch (err) { + throw err; + } finally { + isInsideConstructor = false; + } + return result; + } + + function indexOf (array, item, from) { + if (Array.prototype.indexOf) // Use the native array method if available + return array.indexOf(item, from); + for (var i = from || 0; i < array.length; i++) { + if (array[i] === item) + return i; + } + return -1; + } + + + //--------------------------------- + // Built-in tokens + //--------------------------------- + + // Augment XRegExp's regular expression syntax and flags. Note that when adding tokens, the + // third (`scope`) argument defaults to `XRegExp.OUTSIDE_CLASS` + + // Comment pattern: (?# ) + XRegExp.addToken( + /\(\?#[^)]*\)/, + function (match) { + // Keep tokens separated unless the following token is a quantifier + return nativ.test.call(quantifier, match.input.slice(match.index + match[0].length)) ? "" : "(?:)"; + } + ); + + // Capturing group (match the opening parenthesis only). + // Required for support of named capturing groups + XRegExp.addToken( + /\((?!\?)/, + function () { + this.captureNames.push(null); + return "("; + } + ); + + // Named capturing group (match the opening delimiter only): (? + XRegExp.addToken( + /\(\?<([$\w]+)>/, + function (match) { + this.captureNames.push(match[1]); + this.hasNamedCapture = true; + return "("; + } + ); + + // Named backreference: \k + XRegExp.addToken( + /\\k<([\w$]+)>/, + function (match) { + var index = indexOf(this.captureNames, match[1]); + // Keep backreferences separate from subsequent literal numbers. Preserve back- + // references to named groups that are undefined at this point as literal strings + return index > -1 ? + "\\" + (index + 1) + (isNaN(match.input.charAt(match.index + match[0].length)) ? "" : "(?:)") : + match[0]; + } + ); + + // Empty character class: [] or [^] + XRegExp.addToken( + /\[\^?]/, + function (match) { + // For cross-browser compatibility with ES3, convert [] to \b\B and [^] to [\s\S]. + // (?!) should work like \b\B, but is unreliable in Firefox + return match[0] === "[]" ? "\\b\\B" : "[\\s\\S]"; + } + ); + + // Mode modifier at the start of the pattern only, with any combination of flags imsx: (?imsx) + // Does not support x(?i), (?-i), (?i-m), (?i: ), (?i)(?m), etc. + XRegExp.addToken( + /^\(\?([imsx]+)\)/, + function (match) { + this.setFlag(match[1]); + return ""; + } + ); + + // Whitespace and comments, in free-spacing (aka extended) mode only + XRegExp.addToken( + /(?:\s+|#.*)+/, + function (match) { + // Keep tokens separated unless the following token is a quantifier + return nativ.test.call(quantifier, match.input.slice(match.index + match[0].length)) ? "" : "(?:)"; + }, + XRegExp.OUTSIDE_CLASS, + function () {return this.hasFlag("x");} + ); + + // Dot, in dotall (aka singleline) mode only + XRegExp.addToken( + /\./, + function () {return "[\\s\\S]";}, + XRegExp.OUTSIDE_CLASS, + function () {return this.hasFlag("s");} + ); + + + //--------------------------------- + // Backward compatibility + //--------------------------------- + + // Uncomment the following block for compatibility with XRegExp 1.0-1.2: + /* + XRegExp.matchWithinChain = XRegExp.matchChain; + RegExp.prototype.addFlags = function (s) {return clone(this, s);}; + RegExp.prototype.execAll = function (s) {var r = []; XRegExp.iterate(s, this, function (m) {r.push(m);}); return r;}; + RegExp.prototype.forEachExec = function (s, f, c) {return XRegExp.iterate(s, this, f, c);}; + RegExp.prototype.validate = function (s) {var r = RegExp("^(?:" + this.source + ")$(?!\\s)", getNativeFlags(this)); if (this.global) this.lastIndex = 0; return s.search(r) === 0;}; + */ + +})(); + +// +// Begin anonymous function. This is used to contain local scope variables without polutting global scope. +// +if (typeof(SyntaxHighlighter) == 'undefined') var SyntaxHighlighter = function() { + +// CommonJS + if (typeof(require) != 'undefined' && typeof(XRegExp) == 'undefined') + { + XRegExp = require('XRegExp').XRegExp; + } + +// Shortcut object which will be assigned to the SyntaxHighlighter variable. +// This is a shorthand for local reference in order to avoid long namespace +// references to SyntaxHighlighter.whatever... + var sh = { + defaults : { + /** Additional CSS class names to be added to highlighter elements. */ + 'class-name' : '', + + /** First line number. */ + 'first-line' : 1, + + /** + * Pads line numbers. Possible values are: + * + * false - don't pad line numbers. + * true - automaticaly pad numbers with minimum required number of leading zeroes. + * [int] - length up to which pad line numbers. + */ + 'pad-line-numbers' : false, + + /** Lines to highlight. */ + 'highlight' : false, + + /** Title to be displayed above the code block. */ + 'title' : null, + + /** Enables or disables smart tabs. */ + 'smart-tabs' : true, + + /** Gets or sets tab size. */ + 'tab-size' : 4, + + /** Enables or disables gutter. */ + 'gutter' : true, + + /** Enables or disables toolbar. */ + 'toolbar' : true, + + /** Enables quick code copy and paste from double click. */ + 'quick-code' : true, + + /** Forces code view to be collapsed. */ + 'collapse' : false, + + /** Enables or disables automatic links. */ + 'auto-links' : false, + + /** Gets or sets light mode. Equavalent to turning off gutter and toolbar. */ + 'light' : false, + + 'unindent' : true, + + 'html-script' : false + }, + + config : { + space : ' ', + + /** Enables use of '); + } +})();